Orchestrata Ultimate / Specs / 099-security-auth-framework

099-security-auth-framework: Security & Auth Framework

This specification defines the security and authentication framework for orchestrata-ultimate. It provides centralized authentication, encryption, session management, and integrates with PAM++ governance for authorization.

At a glance

Item Value
Spec directory specs/099-security-auth-framework/
Status line in the spec Complete
Requirement IDs defined 171
With a @traces citation in src/ 0 (0.0%)
With a @traces citation in tests/ 0 (0.0%)
Tracked files 2
RTM page 099-security-auth-framework

Reading this spec

This spec defines the security and authentication framework for orchestrata-ultimate. It provides centralized authentication, encryption and session management, and it hands authorization decisions to PAM++ governance. It is the reference for how users and programs prove who they are, how access is limited, and how security events are recorded and answered.

Four user stories set the scope: a CLI user authenticating with an API key (generated with the permissions needed, sent in the Authorization header, expiring after a configurable time, revocable at any time), an administrator enabling multi-factor authentication, a user managing sessions, and security incident response. Data models describe the user, API key, session and MFA setup. The functional requirement groups are authentication, authorization, session management, token security, rate limiting, audit logging, account security and MFA security. Further sections cover thirty named error conditions (ERR-001 to ERR-030), token revocation with a blacklist and revocation API, and MFA with time-based one-time passwords.

The 171 requirement IDs (REQ-099-NNN) state the design decisions. Authentication supports API keys, OAuth and sessions as interchangeable strategies, and encryption uses AES-256-GCM. Authorization enforces role-based access control across all resources, with permissions cached in Redis for 3600 seconds and invalidated on role change. Sessions live in a Redis cluster with TTL-based expiry and distributed invalidation, and all sessions can be invalidated during a security incident. Accounts are blocked after 5 failed login attempts and common passwords are rejected. Secrets management supports HashiCorp Vault and AWS Secrets Manager, with environment variables as a backend for development only. Audit logs are tamper-resistant with hash-chain verification. The PAM++ client has a 5.0 second timeout, and security incidents are classified with response times, for example 1 hour for critical ones. The spec also defines the refresh and session-deletion endpoints.

This is a framework spec, and no code module cites it. The requirements traceability matrix lists every ID. The spec's own status line reads Complete and it tracks 2 files. No src/ symbol cites any of the 171 requirements, so measured trace coverage is 0.0%, and in tests/, 0 requirements are cited by a test-side @traces. All 171 requirements have no citing symbol; untraced means no @traces names the ID, and the behaviour may still exist in code that was never annotated.

Requirements

Checkbox is the state recorded in the requirements checklist; Traced by is the count of src/ symbols whose @traces names the ID.

ID Done Requirement Traced by
REQ-099-001 - The system SHALL allow a CLI user to authenticate with an API key. The key SHALL be generated with the permissions required for its use, SHALL be presented in the Authorization header, SHALL expire after a configurable time, and SHALL be revocable at any time. none
REQ-099-002 - The system SHALL allow a security admin to enable multi-factor authentication. MFA SHALL support TOTP and SMS backup, SHALL generate backup codes, and SHALL be enforceable for all users or for specific roles. none
REQ-099-003 - Login SHALL create a session carrying a JWT, the session SHALL expire after 24 hours, the refresh token SHALL be valid for 7 days, and logout SHALL invalidate the session. none
REQ-099-004 - A security officer SHALL be able to revoke all active sessions and invalidate all API keys, SHALL be able to block a user account, and every revocation action SHALL be written to the audit log. none
REQ-099-005 - The system SHALL represent a User conforming to the schema above: id, email, name and role SHALL be required; id SHALL match ^user_[a-zA-Z0-9]+$; role SHALL be one of admin, auditor, project_admin, developer, viewer or guest; and the record SHALL carry projects, created_at, last_login, mfa_enabled, mfa_secret (base32 TOTP secret), password_hash (bcrypt), account_locked and failed_login_attempts. none
REQ-099-006 - The system SHALL represent an API Key conforming to the schema above: id, user_id, name, prefix and permissions SHALL be required; id SHALL match ^key_[a-zA-Z0-9]+$; prefix SHALL match ^sk_[a-zA-Z0-9]{8}$; each permission SHALL be one of read, write, admin or audit; and the record SHALL carry created_at, expires_at, last_used, revoked and revoked_at. none
REQ-099-007 - The system SHALL represent a Session conforming to the schema above: id, user_id, refresh_token and expires_at SHALL be required; id SHALL match ^sess_[a-zA-Z0-9]+$; the access token SHALL be a JWT that expires in 1 hour; and the record SHALL carry ip_address, user_agent, created_at, revoked and revoked_at. none
REQ-099-008 - The system SHALL represent an MFA setup conforming to the schema above: secret (base32 TOTP secret) and backup_codes SHALL be required; qr_code SHALL be a base64-encoded QR image; each backup code SHALL match ^[0-9]{8}$; and method SHALL be one of totp, sms or u2f. none
REQ-099-009 - The system MUST support API key authentication for CLI and programmatic access. none
REQ-099-010 - The system MUST support OAuth 2.0 authentication for web UI access. none
REQ-099-011 - The system MUST support session-based authentication with JWT tokens. none
REQ-099-012 - The system MUST support MFA using TOTP (Time-based One-Time Password). none
REQ-099-013 - The system MUST support MFA using SMS backup codes. none
REQ-099-014 - The system MUST validate all authentication tokens before allowing access. none
REQ-099-015 - The system MUST expire authentication tokens after configurable duration. none
REQ-099-016 - The system MUST query PAM++ for all authorization decisions. none
REQ-099-017 - The system MUST enforce RBAC (Role-Based Access Control) across all resources. none
REQ-099-018 - The system MUST support permission levels: global, project, resource, and action. none
REQ-099-019 - The system MUST deny access by default when no explicit allow policy exists. none
REQ-099-020 - The system MUST provide fine-grained permission control at the resource level. none
REQ-099-021 - The system MUST create sessions upon successful authentication. none
REQ-099-022 - The system MUST invalidate sessions on logout. none
REQ-099-023 - The system MUST enforce session expiry (24 hours default). none
REQ-099-024 - The system MUST support refresh tokens valid for 7 days. none
REQ-099-025 - The system MUST invalidate all sessions during security incidents. none
REQ-099-026 - The system MUST hash API keys with bcrypt before storage. none
REQ-099-027 - The system MUST support token revocation with immediate effect. none
REQ-099-028 - The system MUST maintain token blacklist in Redis. none
REQ-099-029 - The system MUST encrypt sensitive data fields with AES-256-GCM. none
REQ-099-030 - The system MUST support automatic key rotation (monthly for DEKs). none
REQ-099-031 - The system MUST enforce per-user rate limits. none
REQ-099-032 - The system MUST implement stricter limits on authentication endpoints. none
REQ-099-033 - The system MUST block accounts after 5 failed login attempts. none
REQ-099-034 - The system MUST implement progressive login delays. none
REQ-099-035 - The system MUST log all authentication events. none
REQ-099-036 - The system MUST log all authorization decisions. none
REQ-099-037 - The system MUST implement tamper-resistant audit logs using hash chains. none
REQ-099-038 - The system MUST maintain audit logs for 7 years. none
REQ-099-039 - The system MUST provide audit log verification capabilities. none
REQ-099-040 - The system MUST enforce password policies (12+ chars, complexity). none
REQ-099-041 - The system MUST detect common passwords and reject them. none
REQ-099-042 - The system MUST lock accounts after threshold failed attempts. none
REQ-099-043 - The system MUST support emergency token revocation. none
REQ-099-044 - The system MUST encrypt password hashes in storage. none
REQ-099-045 - The system MUST generate unique TOTP secrets for each user. none
REQ-099-046 - The system MUST generate backup codes for MFA recovery. none
REQ-099-047 - The system MUST prevent backup code reuse. none
REQ-099-048 - The system MUST require MFA verification after sensitive operations. none
REQ-099-049 - The system SHALL detect each of the conditions ERR-001 through ERR-030 listed above and SHALL respond with the HTTP status, error code and handling given for that condition. none
REQ-099-050 - Revoked tokens SHALL be stored in Redis under the key revoked:{token_hash}, where token_hash is the SHA-256 of the full token, with a TTL equal to the original token expiry; the stored record SHALL carry the revocation reason, the revoking user and the revocation timestamp. none
REQ-099-051 - Invalidating all sessions for a user SHALL delete every session held in that user's session set and SHALL remove each session id from the set. none
REQ-099-052 - TOTP setup SHALL generate a random base32 secret, SHALL return a provisioning QR code issued under the name Orchestrata Ultimate, and SHALL store the secret encrypted; TOTP verification SHALL check the submitted code against the stored secret. none
REQ-099-053 - The system SHALL generate 10 backup codes, each of 8 numeric digits, and SHALL accept any given backup code only once. none
REQ-099-054 - After 5 failed login attempts the account SHALL be locked for 1800 seconds (30 minutes) and an ACCOUNT_LOCKED security event SHALL be logged. none
REQ-099-055 - Authorization decisions SHALL be requested from PAM++ as can_perform(user, action, resource, context) with the request IP, timestamp and method carried in the context, and the PAM++ response SHALL supply the decision, its reason and the matched policy. none
REQ-099-056 - The system SHALL expose POST /api/v1/auth/login, accepting { email, password } and returning { access_token, refresh_token, expires_in }, and SHALL report ERR-001, ERR-006, ERR-017, ERR-018 and ERR-025 on failure. none
REQ-099-057 - The system SHALL expose POST /api/v1/auth/refresh, accepting { refresh_token } and returning { access_token, expires_in }, and SHALL report ERR-004 and ERR-030 on failure. none
REQ-099-058 - The system SHALL expose POST /api/v1/auth/logout, accepting { token } and returning { success: true }, and SHALL report ERR-005 on failure. none
REQ-099-059 - The system SHALL expose POST /api/v1/auth/api-keys, accepting { name, permissions, expires_in } and returning { id, key, prefix }, and SHALL report ERR-009 on failure. none
REQ-099-060 - The system SHALL expose POST /api/v1/auth/mfa/setup, accepting { method } of totp or sms and returning { secret, qr_code, backup_codes }, and SHALL report ERR-025 on failure. none
REQ-099-061 - The system SHALL expose POST /api/v1/auth/mfa/verify, accepting { code } and returning { verified }, and SHALL report ERR-014, ERR-015 and ERR-016 on failure. none
REQ-099-062 - The system SHALL expose POST /api/v1/auth/mfa/disable, accepting { password } and returning { success }, and SHALL report ERR-001 and ERR-017 on failure. none
REQ-099-063 - The system SHALL expose GET /api/v1/sessions, returning the caller's sessions, and SHALL report ERR-008 and ERR-009 on failure. none
REQ-099-064 - The system SHALL expose DELETE /api/v1/sessions/{session_id}, returning { success }, and SHALL report ERR-008 and ERR-010 on failure. none
REQ-099-065 - The system SHALL expose DELETE /api/v1/sessions, which deletes every session of the caller and returns { success }, and SHALL report ERR-008 and ERR-009 on failure. none
REQ-099-066 - The system SHALL expose POST /api/v1/auth/authorize, accepting { action, resource, context } and returning { allowed, reason, policy }, and SHALL report ERR-008, ERR-009, ERR-019 and ERR-020 on failure. none
REQ-099-201 - Authentication latency MUST be under 50ms for token validation none
REQ-099-202 - Authorization queries MUST complete within 100ms (PAM++ timeout: 5s) none
REQ-099-203 - Session creation MUST complete within 200ms none
REQ-099-204 - Token refresh MUST complete within 100ms none
REQ-099-205 - System MUST support 10,000 concurrent authenticated sessions none
REQ-099-206 - Authentication service MUST scale horizontally with load balancer none
REQ-099-207 - Session store MUST support Redis cluster for high availability none
REQ-099-208 - Token blacklist operations MUST complete within 10ms none
REQ-099-209 - Rate limiting MUST support distributed counters none
REQ-099-210 - Authentication service MUST achieve 99.9% uptime (SLA) none
REQ-099-211 - Maximum downtime for deployments MUST NOT exceed 5 minutes none
REQ-099-212 - Rate limiting MUST NOT cause false positives during traffic spikes none
REQ-099-213 - PAM++ unavailability MUST trigger fail-secure mode none
REQ-099-214 - All passwords MUST be hashed with bcrypt (cost factor 12+) none
REQ-099-215 - All API keys MUST be hashed with bcrypt before storage none
REQ-099-216 - Encryption at rest MUST use AES-256-GCM none
REQ-099-217 - TLS 1.3 REQUIRED for all connections none
REQ-099-218 - MFA MUST be available for all user roles none
REQ-099-219 - Audit logs MUST be tamper-resistant (hash chain) none
REQ-099-067 - The Authentication Service SHALL be a stateless REST API that handles API-key, OAuth 2.0 and session-token authentication, manages the JWT access and refresh token lifecycle, integrates with the TOTP and SMS MFA providers, and enforces rate limiting and account-lockout policies. none
REQ-099-068 - The Authorization Engine SHALL delegate every authorization decision to PAM++, SHALL cache policy decisions to reduce PAM++ queries, SHALL support RBAC with permission inheritance, and SHALL take request time, IP and user agent into account. none
REQ-099-069 - Token Management SHALL issue JWT access tokens valid for 1 hour and refresh tokens valid for 7 days, SHALL maintain a token blacklist for immediate revocation, and SHALL use Redis for distributed token validation. none
REQ-099-070 - The Session Store SHALL run on a Redis cluster for high availability, SHALL store active sessions with TTL-based expiry, SHALL support distributed session invalidation, and SHALL encrypt sensitive session data at rest. none
REQ-099-071 - Secrets Management SHALL integrate with HashiCorp Vault or AWS Secrets Manager, SHALL rotate data encryption keys automatically every month, SHALL support an HSM for master keys, and SHALL log every key access centrally. none
REQ-099-072 - Audit Logging SHALL store entries with hash chains for tamper resistance, SHALL keep 90 days of hot storage in Elasticsearch and 7 years of cold storage in S3 Glacier, and SHALL stream events to SIEM systems in real time. none
REQ-099-073 - Every request SHALL pass through the auth middleware, which SHALL validate the token and obtain a PAM++ authorization decision before the handler runs, and SHALL attach the user context to the request when the token is valid. none
REQ-099-074 - Login SHALL create a 24-hour session, issue a 1-hour access token and a 7-day refresh token; presenting a refresh token SHALL validate it, issue new tokens and invalidate the old refresh token. none
REQ-099-075 - An authorization request SHALL extract the user and the required permission, query PAM++, cache the decision and enforce it; a cached decision SHALL be returned without re-querying PAM++. none
REQ-099-076 - The system SHALL implement middleware that validates tokens before request handling, enforces PAM++ authorization policies, enforces per-user rate quotas, and logs all security events for audit. none
REQ-099-077 - The system SHALL implement a UserRepository for user database operations, a TokenRepository for token validation and storage, a SessionRepository for session lifecycle management, and an AuditRepository for audit-log writing and retrieval. none
REQ-099-078 - The system SHALL implement interchangeable strategies for authentication (API key, OAuth, session), encryption (AES-256-GCM across backends), secrets management (Vault, AWS, environment) and MFA (TOTP, SMS, U2F). none
REQ-099-079 - The system SHALL implement observers for security-event audit logging, token-revocation blacklist updates, failed-login account lockout, and policy-change cache invalidation. none
REQ-099-080 - The users table SHALL hold id, email (unique, not null), name, role, password_hash, mfa_enabled, mfa_secret_encrypted, account_locked, failed_login_attempts, created_at and last_login, indexed on email and role. none
REQ-099-081 - The api_keys table SHALL hold id, user_id (foreign key to users), name, key_hash, prefix, permissions, created_at, expires_at, last_used, revoked and revoked_at, indexed on user_id and prefix. none
REQ-099-082 - The sessions table SHALL hold id, user_id (foreign key to users), refresh_token_hash, access_token_hash, ip_address, user_agent, created_at, expires_at, revoked and revoked_at, indexed on user_id, refresh_token_hash and expires_at. none
REQ-099-083 - PAM++ decisions SHALL be cached in Redis under pam:decision:{user_id}:{permission}:{resource} with a 300-second TTL, and SHALL be invalidated on policy change or user role change. none
REQ-099-084 - Token validation results SHALL be cached in per-instance memory under `token:«redacted» for the token's remaining lifetime, so that validation does not require a Redis lookup on every request. none
REQ-099-085 - Rate-limit counters SHALL be held in Redis under ratelimit:{user_id}:{endpoint} as a sliding-window counter over a rolling window. none
REQ-099-086 - User permissions SHALL be cached in Redis under perms:{user_id} with a 3600-second TTL, and SHALL be invalidated on role change or on explicit invalidation. none
REQ-099-087 - The system SHALL apply defence in depth: WAF, DDoS protection and VPN requirement at the network layer; input validation, output encoding and CSRF protection at the application layer; encryption at rest and in transit at the data layer; and MFA, password policies and account lockout at the identity layer. none
REQ-099-088 - The system SHALL follow a zero-trust architecture: it SHALL authenticate and authorize every request, SHALL assume breach and monitor accordingly, and SHALL grant least-privilege access. none
REQ-099-089 - The system SHALL be secure by default: access SHALL be denied unless an explicit allow policy exists, configuration SHALL follow secure baselines, and the attack surface SHALL be kept minimal. none
REQ-099-090 - Data at rest SHALL be encrypted with AES-256-GCM under key rotation, data in transit SHALL use TLS 1.3 with perfect forward secrecy, keys SHALL be managed by an HSM or Vault with automatic rotation, and tokens SHALL be stored hashed with bcrypt at cost factor 12 or higher. none
REQ-099-220 - The system SHALL emit metrics for authentication success and failure rates, authorization decision latencies, token issuance and validation counts, rate-limit triggers and violations, and session creation and expiry rates. none
REQ-099-221 - Logs SHALL be structured JSON, SHALL carry correlation IDs for request tracing, SHALL record security events with an appropriate severity, and SHALL keep audit logs tamper-resistant. none
REQ-099-222 - The system SHALL alert on failed-login thresholds being exceeded, unusual authentication patterns, PAM++ service unavailability, token-blacklist failures, and audit-log tampering detection. none
REQ-099-223 - Dashboards SHALL present real-time authentication metrics, authorization decision analytics, the security incident timeline, and compliance status indicators. none
REQ-099-091 - Governance policies SHALL be defined in Prolog syntax, SHALL be evaluated in order of specificity, SHALL default to denying all access, and every governance decision SHALL be logged for audit. none
REQ-099-092 - The policy engine SHALL support Access Control Policies (ACP), Data Governance Policies (DGP) and Compliance Policies (CP). none
REQ-099-093 - When a user attempts an action, the auth middleware SHALL validate authentication, the authorization middleware SHALL query PAM++, PAM++ SHALL evaluate its rules against the request context, and the decision SHALL be returned with its policy ID before the action is allowed or denied. none
REQ-099-094 - The system SHALL implement the compliance controls listed above: SOC 2 CC6.1, CC6.2 and CC6.6, GDPR Article 32, PCI DSS 8.2, and NIST AC-2 and IA-5. none
REQ-099-095 - GitHub OAuth SHALL use the authorization URL https://github.com/login/oauth/authorize, the token URL https://github.com/login/oauth/access_token, the user-info URL https://api.github.com/user, and the scopes read:user and user:email. none
REQ-099-096 - Google OAuth SHALL use the authorization URL https://accounts.google.com/o/oauth2/v2/auth, the token URL https://oauth2.googleapis.com/token, the user-info URL https://www.googleapis.com/oauth2/v3/userinfo, and the scopes openid, email and profile. none
REQ-099-097 - GitLab OAuth SHALL use the authorization URL https://gitlab.com/oauth/authorize, the token URL https://gitlab.com/oauth/token, the user-info URL https://gitlab.com/api/v4/user, and the scopes read_user and api. none
REQ-099-098 - The HashiCorp Vault backend SHALL take its address from VAULT_ADDR, SHALL authenticate with the token in VAULT_TOKEN, SHALL use the KV v2 secrets engine, and SHALL rotate keys automatically every month. none
REQ-099-099 - The AWS Secrets Manager backend SHALL take a configurable region, SHALL authenticate with an IAM role, SHALL store secrets as JSON, and SHALL rotate keys with a Lambda function. none
REQ-099-100 - Session storage SHALL run on a Redis cluster of at least 3 master nodes, with AOF persistence every 1 second, TLS 1.3 transport, and Redis AUTH password protection. none
REQ-099-101 - Audit records SHALL be written as JSON with a hash chain, held in Elasticsearch hot storage for 90 days, and archived to S3 Glacier cold storage for 7 years. none
REQ-099-102 - Authentication SHALL be accepted only when users can authenticate with email and password, with API keys and via OAuth providers, session tokens expire after the configured duration, and refresh tokens allow re-authentication without a fresh login. none
REQ-099-103 - Authorization SHALL be accepted only when PAM++ queries return the correct decisions, RBAC enforces role-based permissions, resource-level permissions are enforced, and the default deny policy blocks unauthorized access. none
REQ-099-104 - MFA SHALL be accepted only when TOTP setup generates unique secrets, TOTP verification succeeds for valid codes, backup codes can be used for recovery, and account lockout triggers at the threshold. none
REQ-099-105 - Security SHALL be accepted only when passwords meet the complexity requirements, API keys are hashed before storage, data at rest is encrypted with AES-256-GCM, all connections use TLS 1.3, and token revocation takes effect immediately. none
REQ-099-106 - Audit SHALL be accepted only when all authentication events and authorization decisions are logged, audit logs are tamper-resistant, hash-chain verification works, and logs are retained for 7 years. none
REQ-099-107 - Rate limiting SHALL be accepted only when authentication endpoints carry stricter limits, general endpoints carry configurable limits, account lockout triggers after 5 failures, and progressive delays prevent brute-force attempts. none
REQ-099-108 - Compliance SHALL be accepted only when the SOC 2 controls, GDPR Article 32, PCI DSS 8.2 and NIST AC-2 and IA-5 requirements are met. none
REQ-099-224 - Components SHALL log all major operations at appropriate log levels, SHALL include correlation IDs for request tracing, SHALL log performance metrics for critical operations, and SHALL log errors with full context. none
REQ-099-225 - The system SHALL expose operation duration histograms, request and error rate counters, resource utilization gauges, and business metrics relevant to the domain. none
REQ-099-226 - The system SHALL propagate traces across component boundaries, SHALL attach domain-specific span attributes, and SHALL sample traces according to operational needs. none
REQ-099-227 - The system SHALL raise critical alerts on error-rate spikes, performance degradation, resource exhaustion, and business-metric anomalies. none
REQ-099-228 - The operational dashboard SHALL present real-time system health, performance trends, error analysis and resource monitoring. none
REQ-099-109 - The PAM++ client SHALL be configured with the PAM++ host, port, API-key authentication and a 5.0-second timeout, and SHALL authenticate a user by posting the user id and credentials to the PAM++ /auth endpoint with the API key as a bearer token. none
REQ-099-110 - On a PAM++ timeout the system SHALL log a PAM_TIMEOUT_ALLOW event and allow access; when PAM++ is unavailable the system SHALL deny access by raising PAMUnavailableError. none
REQ-099-111 - Per-endpoint rate limits SHALL be enforced as 5 requests per 300 seconds on /api/v1/auth/login, 10 per 60 seconds on /api/v1/auth/verify_mfa, 30 per 60 seconds on /api/v1/intent, and 60 per 60 seconds on /api/v1/agents/*. none
REQ-099-112 - Accounts SHALL be locked after 5 failed login attempts for 1800 seconds, and login delays SHALL progress from a 1-second base up to a 64-second maximum. none
REQ-099-113 - Each audit entry SHALL carry the previous entry's hash and a timestamp, SHALL be hashed with SHA-256 over its canonically-sorted JSON content, and SHALL be appended to immutable WORM storage. none
REQ-099-114 - Audit-chain verification SHALL recompute every entry's hash and SHALL raise a tamper error when an entry's hash does not match its content or its recorded previous hash does not match the preceding entry. none
REQ-099-115 - Passwords SHALL be at least 12 and at most 128 characters, SHALL contain uppercase, lowercase, numeric and special characters, and SHALL be rejected when they match a common password or contain the user's personal information. none
REQ-099-116 - The system SHALL support API-key authentication for CLI and scripts, OAuth 2.0 for the web UI, session tokens for persistent web-UI login, and service-account authentication for internal services. none
REQ-099-117 - An API key SHALL be presented as Authorization: Bearer <key>, SHALL carry the sk_ prefix, SHALL be at least 32 characters drawn from alphanumeric characters and underscore, and SHALL be generated from a cryptographically secure URL-safe random source. none
REQ-099-118 - The OAuth 2.0 flow SHALL redirect the user to the provider, SHALL accept the provider's callback code, SHALL exchange that code for a token, and SHALL then create a session and redirect the user back to the application. none
REQ-099-119 - The session token SHALL be a JWT expiring after a configurable 24 hours with a 7-day refresh token, and sessions SHALL be stored in Redis for distributed access and encrypted at rest. none
REQ-099-120 - The system SHALL provide the built-in roles admin (full system access), auditor (read-only access to audit logs), project_admin (manage project configuration), developer (read/write code, create tasks), viewer (read-only project access) and guest (minimal access to public projects). none
REQ-099-121 - Data at rest SHALL be encrypted: database fields with AES-256-GCM, file storage on an encrypted filesystem, and backups with a key from the key vault. none
REQ-099-122 - Data in transit SHALL be encrypted: all HTTP over TLS 1.3, all WebSocket traffic over WSS, and all internal traffic over mTLS. none
REQ-099-123 - The master key SHALL be held in an HSM or secure vault, data encryption keys SHALL be encrypted by the master key, and API keys SHALL be stored hashed with bcrypt. none
REQ-099-124 - The master key SHALL be rotated annually by manual action, data encryption keys SHALL be rotated monthly and automatically, and API keys SHALL be rotated on compromise or annually. none
REQ-099-125 - Secrets management SHALL support HashiCorp Vault and AWS Secrets Manager as backends, and environment variables SHALL be used as a secrets backend in development only. none
REQ-099-126 - The authentication middleware SHALL extract the token from the request header, SHALL validate it, and SHALL attach the resolved user to the request before the handler runs. none
REQ-099-127 - The authorization middleware SHALL determine the permission required by the route, SHALL check it against PAM++ for the request user and resource, and SHALL reject the request with the decision's reason when access is not allowed. none
REQ-099-128 - The rate-limiting middleware SHALL identify the requesting user, SHALL check that user's rate limit, and SHALL reject the request with a retry-after value when the limit is exceeded. none
REQ-099-129 - The audit log SHALL capture, for authentication the user, method, IP and result; for authorization the user, permission, resource and decision; for data access the user, resource and action; for data modification the user, resource, old value and new value; for configuration changes the user, setting, old value and new value; and for security events the event type, details and severity. none
REQ-099-130 - Each audit entry SHALL carry event_id, event_type, timestamp, the acting user's id and role, action, resource, decision, the request context (IP, user agent, method) and the governance policy id, rule id and match flag. none
REQ-099-131 - Audit records SHALL be searchable in hot storage for 90 days, archived for 7 years, and SHALL have personally identifiable information redacted after 1 year. none
REQ-099-132 - The security configuration SHALL accept the enabled authentication methods, a session expiry of 86400 seconds and refresh expiry of 604800 seconds, the OAuth 2.0 providers and credentials, an authorization block with pam++ as policy engine and deny as default policy, an encryption block with AES-256-GCM and a 30-day key rotation against the configured vault backend, a rate-limiting block with default and burst limits, and an audit block with 2555-day retention and 90-day hot storage. none
REQ-099-133 - The system SHALL read SECRET_KEY for the master encryption key, OAUTH_CLIENT_ID and OAUTH_CLIENT_SECRET for the OAuth application credentials, and VAULT_ADDR and VAULT_TOKEN for the HashiCorp Vault address and authentication token. none
REQ-099-134 - Authentication failures SHALL be reported as AUTH-001 invalid API key, AUTH-002 API key expired, AUTH-003 session expired and AUTH-004 OAuth failed, each with HTTP status 401. none
REQ-099-135 - Authorization failures SHALL be reported as AUTHZ-001 access denied with HTTP status 403, AUTHZ-002 governance blocked with HTTP status 451, and AUTHZ-003 insufficient permissions with HTTP status 403. none
REQ-099-136 - Every error response SHALL carry the error code, the message, the details (reason, resource and policy) and the request id. none
REQ-099-229 - The security test suite SHALL prove that authentication succeeds with valid credentials and fails with invalid ones, that authorization blocks unauthorized actions and allows authorized ones, that rate limiting triggers at the threshold, that audit logs capture all security events, that encryption at rest works, and that session expiry works. none
REQ-099-230 - The system SHALL prevent SQL injection, cross-site scripting, cross-site request forgery, path traversal and command injection, and penetration testing SHALL cover each of them. none
REQ-099-231 - The system SHALL conform to the OWASP Top 10, SOC 2 Type II, the GDPR data-handling requirements and the CCPA data-handling requirements. none
REQ-099-137 - Responses SHALL carry the security headers Strict-Transport-Security: max-age=31536000; includeSubDomains, Content-Security-Policy: default-src 'self', X-Content-Type-Options: nosniff, X-Frame-Options: DENY, X-XSS-Protection: 1; mode=block and Referrer-Policy: strict-origin-when-cross-origin. none
REQ-099-138 - Security incidents SHALL be classified and answered within the stated response times: critical (data breach or full system compromise) within 1 hour, high (unauthorized access or privilege escalation) within 4 hours, medium (policy violation or suspicious activity) within 24 hours, and low (minor security concern) within 7 days. none
REQ-099-139 - Incident response SHALL follow the steps detect, contain, eradicate, recover, document and review. none
REQ-099-140 - The framework SHALL depend on PyJWT >=2.8 for JWT handling, passlib >=1.7 for password hashing, cryptography >=41.0 for encryption, httpx >=0.25 for HTTP requests, and structlog >=24.0 for structured logging. none

Code that traces this spec

No src/ symbol cites a requirement of this spec.

Other tracked files

Full spec text

Verbatim from specs/099-security-auth-framework/spec.md; headings are pushed down two levels.

SPEC-099: Security & Auth Framework

Metadata


Overview

This specification defines the security and authentication framework for orchestrata-ultimate. It provides centralized authentication, encryption, session management, and integrates with PAM++ governance for authorization.


User Scenarios

US-001: User Authenticating with API Key

As a CLI user, I want to authenticate with an API key so I can access the system securely.

Acceptance Criteria:

REQ-099-001: The system SHALL allow a CLI user to authenticate with an API key. The key SHALL be generated with the permissions required for its use, SHALL be presented in the Authorization header, SHALL expire after a configurable time, and SHALL be revocable at any time.

US-002: Admin Enabling MFA

As a security admin, I want to enable MFA so I can require multi-factor authentication for all users.

Acceptance Criteria:

REQ-099-002: The system SHALL allow a security admin to enable multi-factor authentication. MFA SHALL support TOTP and SMS backup, SHALL generate backup codes, and SHALL be enforceable for all users or for specific roles.

US-003: User Session Management

As a web user, I want session tokens that expire automatically so my account stays secure.

Acceptance Criteria:

REQ-099-003: Login SHALL create a session carrying a JWT, the session SHALL expire after 24 hours, the refresh token SHALL be valid for 7 days, and logout SHALL invalidate the session.

US-004: Security Incident Response

As a security officer, I want to revoke all tokens immediately so I can respond to security incidents.

Acceptance Criteria:

REQ-099-004: A security officer SHALL be able to revoke all active sessions and invalidate all API keys, SHALL be able to block a user account, and every revocation action SHALL be written to the audit log.


Terminology

Term Definition
PAM++ Prolog Authorization Manager - policy engine for authorization decisions
JWT JSON Web Token - compact, URL-safe token format for claims
TOTP Time-based One-Time Password - RFC 6238 compliant MFA method
MFA Multi-Factor Authentication - requiring multiple verification methods
API Key Secret key for programmatic access to the system
Session Server-side user state after successful authentication
Refresh Token Long-lived token for obtaining new access tokens
Access Token Short-lived token for API authorization
WORM Write-Once Read-Many - tamper-resistant storage
HSM Hardware Security Module - physical device for key management
DEK Data Encryption Key - key used to encrypt data
RBAC Role-Based Access Control - authorization model

Data Models (JSON Schemas)

User
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["id", "email", "name", "role"],
  "properties": {
    "id": {
      "type": "string",
      "pattern": "^user_[a-zA-Z0-9]+$"
    },
    "email": {
      "type": "string",
      "format": "email"
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 100
    },
    "role": {
      "type": "string",
      "enum": ["admin", "auditor", "project_admin", "developer", "viewer", "guest"]
    },
    "projects": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "created_at": {
      "type": "string",
      "format": "date-time"
    },
    "last_login": {
      "type": "string",
      "format": "date-time"
    },
    "mfa_enabled": {
      "type": "boolean"
    },
    "mfa_secret": {
      "type": "string",
      "description": "TOTP secret (base32 encoded)"
    },
    "password_hash": {
      "type": "string",
      "description": "bcrypt hash"
    },
    "account_locked": {
      "type": "boolean"
    },
    "failed_login_attempts": {
      "type": "integer",
      "minimum": 0
    }
  }
}

REQ-099-005: The system SHALL represent a User conforming to the schema above: id, email, name and role SHALL be required; id SHALL match ^user_[a-zA-Z0-9]+$; role SHALL be one of admin, auditor, project_admin, developer, viewer or guest; and the record SHALL carry projects, created_at, last_login, mfa_enabled, mfa_secret (base32 TOTP secret), password_hash (bcrypt), account_locked and failed_login_attempts.

API Key
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["id", "user_id", "name", "prefix", "permissions"],
  "properties": {
    "id": {
      "type": "string",
      "pattern": "^key_[a-zA-Z0-9]+$"
    },
    "user_id": {
      "type": "string",
      "pattern": "^user_[a-zA-Z0-9]+$"
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 100
    },
    "prefix": {
      "type": "string",
      "pattern": "^sk_[a-zA-Z0-9]{8}$",
      "description": "First 12 chars of key for identification"
    },
    "permissions": {
      "type": "array",
      "items": {
        "type": "string",
        "enum": ["read", "write", "admin", "audit"]
      }
    },
    "created_at": {
      "type": "string",
      "format": "date-time"
    },
    "expires_at": {
      "type": "string",
      "format": "date-time"
    },
    "last_used": {
      "type": "string",
      "format": "date-time"
    },
    "revoked": {
      "type": "boolean"
    },
    "revoked_at": {
      "type": "string",
      "format": "date-time"
    }
  }
}

REQ-099-006: The system SHALL represent an API Key conforming to the schema above: id, user_id, name, prefix and permissions SHALL be required; id SHALL match ^key_[a-zA-Z0-9]+$; prefix SHALL match ^sk_[a-zA-Z0-9]{8}$; each permission SHALL be one of read, write, admin or audit; and the record SHALL carry created_at, expires_at, last_used, revoked and revoked_at.

Session
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["id", "user_id", "refresh_token", "expires_at"],
  "properties": {
    "id": {
      "type": "string",
      "pattern": "^sess_[a-zA-Z0-9]+$"
    },
    "user_id": {
      "type": "string",
      "pattern": "^user_[a-zA-Z0-9]+$"
    },
    "refresh_token": {
      "type": "string",
      "description": "JWT refresh token"
    },
    "access_token": {
      "type": "string",
      "description": "JWT access token (expires in 1 hour)"
    },
    "expires_at": {
      "type": "string",
      "format": "date-time"
    },
    "ip_address": {
      "type": "string",
      "format": "ipv4"
    },
    "user_agent": {
      "type": "string"
    },
    "created_at": {
      "type": "string",
      "format": "date-time"
    },
    "revoked": {
      "type": "boolean"
    },
    "revoked_at": {
      "type": "string",
      "format": "date-time"
    }
  }
}

REQ-099-007: The system SHALL represent a Session conforming to the schema above: id, user_id, refresh_token and expires_at SHALL be required; id SHALL match ^sess_[a-zA-Z0-9]+$; the access token SHALL be a JWT that expires in 1 hour; and the record SHALL carry ip_address, user_agent, created_at, revoked and revoked_at.

MFA Setup
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["secret", "backup_codes"],
  "properties": {
    "secret": {
      "type": "string",
      "description": "TOTP secret (base32 encoded)"
    },
    "qr_code": {
      "type": "string",
      "description": "Base64 encoded QR code image"
    },
    "backup_codes": {
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^[0-9]{8}$"
      }
    },
    "method": {
      "type": "string",
      "enum": ["totp", "sms", "u2f"]
    }
  }
}

REQ-099-008: The system SHALL represent an MFA setup conforming to the schema above: secret (base32 TOTP secret) and backup_codes SHALL be required; qr_code SHALL be a base64-encoded QR image; each backup code SHALL match ^[0-9]{8}$; and method SHALL be one of totp, sms or u2f.


Functional Requirements

Authentication

FR-001 — REQ-099-009: The system MUST support API key authentication for CLI and programmatic access.

FR-002 — REQ-099-010: The system MUST support OAuth 2.0 authentication for web UI access.

FR-003 — REQ-099-011: The system MUST support session-based authentication with JWT tokens.

FR-004 — REQ-099-012: The system MUST support MFA using TOTP (Time-based One-Time Password).

FR-005 — REQ-099-013: The system MUST support MFA using SMS backup codes.

FR-006 — REQ-099-014: The system MUST validate all authentication tokens before allowing access.

FR-007 — REQ-099-015: The system MUST expire authentication tokens after configurable duration.

Authorization

FR-008 — REQ-099-016: The system MUST query PAM++ for all authorization decisions.

FR-009 — REQ-099-017: The system MUST enforce RBAC (Role-Based Access Control) across all resources.

FR-010 — REQ-099-018: The system MUST support permission levels: global, project, resource, and action.

FR-011 — REQ-099-019: The system MUST deny access by default when no explicit allow policy exists.

FR-012 — REQ-099-020: The system MUST provide fine-grained permission control at the resource level.

Session Management

FR-013 — REQ-099-021: The system MUST create sessions upon successful authentication.

FR-014 — REQ-099-022: The system MUST invalidate sessions on logout.

FR-015 — REQ-099-023: The system MUST enforce session expiry (24 hours default).

FR-016 — REQ-099-024: The system MUST support refresh tokens valid for 7 days.

FR-017 — REQ-099-025: The system MUST invalidate all sessions during security incidents.

Token Security

FR-018 — REQ-099-026: The system MUST hash API keys with bcrypt before storage.

FR-019 — REQ-099-027: The system MUST support token revocation with immediate effect.

FR-020 — REQ-099-028: The system MUST maintain token blacklist in Redis.

FR-021 — REQ-099-029: The system MUST encrypt sensitive data fields with AES-256-GCM.

FR-022 — REQ-099-030: The system MUST support automatic key rotation (monthly for DEKs).

Rate Limiting

FR-023 — REQ-099-031: The system MUST enforce per-user rate limits.

FR-024 — REQ-099-032: The system MUST implement stricter limits on authentication endpoints.

FR-025 — REQ-099-033: The system MUST block accounts after 5 failed login attempts.

FR-026 — REQ-099-034: The system MUST implement progressive login delays.

Audit Logging

FR-027 — REQ-099-035: The system MUST log all authentication events.

FR-028 — REQ-099-036: The system MUST log all authorization decisions.

FR-029 — REQ-099-037: The system MUST implement tamper-resistant audit logs using hash chains.

FR-030 — REQ-099-038: The system MUST maintain audit logs for 7 years.

FR-031 — REQ-099-039: The system MUST provide audit log verification capabilities.

Account Security

FR-032 — REQ-099-040: The system MUST enforce password policies (12+ chars, complexity).

FR-033 — REQ-099-041: The system MUST detect common passwords and reject them.

FR-034 — REQ-099-042: The system MUST lock accounts after threshold failed attempts.

FR-035 — REQ-099-043: The system MUST support emergency token revocation.

FR-036 — REQ-099-044: The system MUST encrypt password hashes in storage.

MFA Security

FR-037 — REQ-099-045: The system MUST generate unique TOTP secrets for each user.

FR-038 — REQ-099-046: The system MUST generate backup codes for MFA recovery.

FR-039 — REQ-099-047: The system MUST prevent backup code reuse.

FR-040 — REQ-099-048: The system MUST require MFA verification after sensitive operations.


Error Conditions

ERR-ID Condition Handling
ERR-001 Invalid API key provided Return 401 with AUTH-001 error, log attempt
ERR-002 API key expired Return 401 with AUTH-002, prompt for key rotation
ERR-003 API key revoked Return 401 with AUTH-003, suggest generating new key
ERR-004 Session token expired Return 401 with AUTH-004, prompt re-authentication
ERR-005 Session token invalid Return 401 with AUTH-005, require fresh login
ERR-006 OAuth authentication failed Return 401 with AUTH-006, redirect to OAuth provider
ERR-007 OAuth token exchange failed Return 401 with AUTH-007, log OAuth error details
ERR-008 Access denied by PAM++ Return 403 with ERR-008, include policy reason
ERR-009 Insufficient permissions Return 403 with ERR-009, list required permissions
ERR-010 Resource not found Return 404 with ERR-010, verify resource identifier
ERR-011 Governance policy blocked action Return 451 with ERR-011, include governance policy ID
ERR-012 Rate limit exceeded Return 429 with ERR-012, include retry-after header
ERR-013 Account locked due to failed attempts Return 403 with ERR-013, show lockout duration
ERR-014 MFA verification failed Return 401 with ERR-014, allow retry with MFA
ERR-015 MFA code invalid or expired Return 401 with ERR-015, suggest using backup code
ERR-016 Backup code already used Return 401 with ERR-016, prompt for new backup code
ERR-017 Password does not meet policy Return 400 with ERR-017, list policy requirements
ERR-018 Common password detected Return 400 with ERR-018, suggest stronger password
ERR-019 PAM++ service unavailable Return 503 with ERR-019, use fallback deny policy
ERR-020 PAM++ query timeout Return 503 with ERR-020, log security event
ERR-021 Token blacklist check failed Deny access by default, log error
ERR-022 Encryption key retrieval failed Return 500 with ERR-022, alert security team
ERR-023 Audit log write failed Log to secondary, alert operations team
ERR-024 Audit chain tampering detected Alert security team, preserve logs for forensics
ERR-025 User account does not exist Return 404 with ERR-025, generic error message
ERR-026 User account disabled Return 403 with ERR-026, contact admin message
ERR-027 IP address blocked Return 403 with ERR-027, include block reason
ERR-028 Invalid JWT signature Return 401 with ERR-028, require re-authentication
ERR-029 JWT claim validation failed Return 401 with ERR-029, check token payload
ERR-030 Refresh token expired Return 401 with ERR-030, require fresh login

REQ-099-049: The system SHALL detect each of the conditions ERR-001 through ERR-030 listed above and SHALL respond with the HTTP status, error code and handling given for that condition.


Token Revocation

Token Blacklist

REQ-099-050: Revoked tokens SHALL be stored in Redis under the key revoked:{token_hash}, where token_hash is the SHA-256 of the full token, with a TTL equal to the original token expiry; the stored record SHALL carry the revocation reason, the revoking user and the revocation timestamp.

Revocation API
async def revoke_token(token: str, reason: str, user_id: str):
    """Revoke a token immediately."""
    token_hash = hashlib.sha256(token.encode()).hexdigest()
    await redis.setex(
        f"revoked:{token_hash}",
        ttl_seconds,
        json.dumps({
            "reason": reason,
            "revoked_by": user_id,
            "revoked_at": datetime.utcnow().isoformat()
        })
    )
Session Invalidation
async def invalidate_all_sessions(user_id: str):
    """Invalidate all active sessions for user."""
    session_ids = await redis.smembers(f"sessions:{user_id}")
    for session_id in session_ids:
        await redis.delete(f"session:{session_id}")
        await redis.srem(f"sessions:{user_id}", session_id)

REQ-099-051: Invalidating all sessions for a user SHALL delete every session held in that user's session set and SHALL remove each session id from the set.


MFA Implementation

TOTP (Time-based One-Time Password)
import pyotp
import qrcode

async def setup_totp(user_id: str):
    """Setup TOTP for user."""
    # Generate secret
    secret = «redacted»
    
    # Generate QR code
    provisioning_uri = pyotp.totp.TOTP(secret).provisioning_uri(
        name=user_id,
        issuer_name="Orchestrata Ultimate"
    )
    qr = qrcode.ProvisionQR(provisioning_uri)
    
    # Store secret (encrypted)
    await store_secret(user_id, encrypt(secret))
    
    return {
        "secret": secret,
        "qr_code": qr.to_base64()
    }

async def verify_totp(user_id: str, code: str) -> bool:
    """Verify TOTP code."""
    secret = await get_secret(user_id)
    totp = pyotp.TOTP(secret)
    return totp.verify(code)

REQ-099-052: TOTP setup SHALL generate a random base32 secret, SHALL return a provisioning QR code issued under the name Orchestrata Ultimate, and SHALL store the secret encrypted; TOTP verification SHALL check the submitted code against the stored secret.

Backup Codes
async def generate_backup_codes() -> List[str]:
    """Generate 10 backup codes."""
    return [str(random.randint(10000000, 99999999)) for _ in range(10)]

async def use_backup_code(user_id: str, code: str) -> bool:
    """Verify and mark backup code as used."""
    used = await redis.sismember(f"backup_codes:{user_id}", code)
    if not used:
        await redis.sadd(f"backup_codes:{user_id}", code)
        return True
    return False

REQ-099-053: The system SHALL generate 10 backup codes, each of 8 numeric digits, and SHALL accept any given backup code only once.

Account Lockout Policy
FAILED_ATTEMPTS_THRESHOLD = 5
LOCKOUT_DURATION = 1800  # 30 minutes

async def check_failed_login(user_id: str):
    """Check if account should be locked."""
    attempts = await redis.incr(f"failed:{user_id}")
    if attempts >= FAILED_ATTEMPTS_THRESHOLD:
        await redis.setex(f"locked:{user_id}", LOCKOUT_DURATION, "1")
        await log_security_event("ACCOUNT_LOCKED", user_id)

REQ-099-054: After 5 failed login attempts the account SHALL be locked for 1800 seconds (30 minutes) and an ACCOUNT_LOCKED security event SHALL be logged.


PAM++ Binding

Prolog Query
async def query_pam(user_id: str, action: str, resource: str, context: dict):
    """Query PAM++ for authorization decision."""
    # Build prolog query
    query = f"""
    can_perform(
        user:{user_id},
        action:{action},
        resource:{resource},
        context:{{
            ip:{context.get('ip')},
            time:{context.get('timestamp')},
            method:{context.get('method')}
        }}
    )
    """
    
    # Send to PAM++ engine
    result = await pam_client.query(query)
    
    return {
        "allowed": result.allowed,
        "reason": result.reason,
        "policy": result.policy
}

REQ-099-055: Authorization decisions SHALL be requested from PAM++ as can_perform(user, action, resource, context) with the request IP, timestamp and method carried in the context, and the PAM++ response SHALL supply the decision, its reason and the matched policy.


API Contracts

Authentication Endpoints

POST /api/v1/auth/login

REQ-099-056: The system SHALL expose POST /api/v1/auth/login, accepting { email, password } and returning { access_token, refresh_token, expires_in }, and SHALL report ERR-001, ERR-006, ERR-017, ERR-018 and ERR-025 on failure.

POST /api/v1/auth/refresh

REQ-099-057: The system SHALL expose POST /api/v1/auth/refresh, accepting { refresh_token } and returning { access_token, expires_in }, and SHALL report ERR-004 and ERR-030 on failure.

POST /api/v1/auth/logout

REQ-099-058: The system SHALL expose POST /api/v1/auth/logout, accepting { token } and returning { success: true }, and SHALL report ERR-005 on failure.

POST /api/v1/auth/api-keys

REQ-099-059: The system SHALL expose POST /api/v1/auth/api-keys, accepting { name, permissions, expires_in } and returning { id, key, prefix }, and SHALL report ERR-009 on failure.

MFA Endpoints

POST /api/v1/auth/mfa/setup

REQ-099-060: The system SHALL expose POST /api/v1/auth/mfa/setup, accepting { method } of totp or sms and returning { secret, qr_code, backup_codes }, and SHALL report ERR-025 on failure.

POST /api/v1/auth/mfa/verify

REQ-099-061: The system SHALL expose POST /api/v1/auth/mfa/verify, accepting { code } and returning { verified }, and SHALL report ERR-014, ERR-015 and ERR-016 on failure.

POST /api/v1/auth/mfa/disable

REQ-099-062: The system SHALL expose POST /api/v1/auth/mfa/disable, accepting { password } and returning { success }, and SHALL report ERR-001 and ERR-017 on failure.

Session Management Endpoints

GET /api/v1/sessions

REQ-099-063: The system SHALL expose GET /api/v1/sessions, returning the caller's sessions, and SHALL report ERR-008 and ERR-009 on failure.

DELETE /api/v1/sessions/{session_id}

REQ-099-064: The system SHALL expose DELETE /api/v1/sessions/{session_id}, returning { success }, and SHALL report ERR-008 and ERR-010 on failure.

DELETE /api/v1/sessions

REQ-099-065: The system SHALL expose DELETE /api/v1/sessions, which deletes every session of the caller and returns { success }, and SHALL report ERR-008 and ERR-009 on failure.

Authorization Endpoints

POST /api/v1/auth/authorize

REQ-099-066: The system SHALL expose POST /api/v1/auth/authorize, accepting { action, resource, context } and returning { allowed, reason, policy }, and SHALL report ERR-008, ERR-009, ERR-019 and ERR-020 on failure.


Non-Functional Requirements

Performance
Scalability
Availability
Security

Technical Design

System Architecture

The Security & Auth Framework follows a layered architecture with clear separation of concerns:

┌─────────────────────────────────────────────────────────────┐
│                    API Gateway / Load Balancer              │
└────────────────────────┬────────────────────────────────────┘
                         │
┌────────────────────────┴────────────────────────────────────┐
│                Auth Service (FastAPI)                       │
│  ┌───────────────┐  ┌──────────────┐  ┌─────────────────┐  │
│  │ Auth Handlers │  │ Middleware   │  │ Token Service   │  │
│  │  - Login      │  │ - Auth       │  │ - JWT           │  │
│  │  - OAuth      │  │ - AuthZ      │  │ - Refresh       │  │
│  │  - MFA        │  │ - Rate Limit │  │ - Blacklist     │  │
│  └───────────────┘  └──────────────┘  └─────────────────┘  │
└────────────────────────┬────────────────────────────────────┘
                         │
        ┌────────────────┴────────────────┐
        │                                 │
┌───────┴────────┐               ┌──────┴──────────┐
│  Data Layer    │               │  External       │
│  ┌──────────┐ │               │  ┌────────────┐  │
│  │ Redis    │ │               │  │ PAM++      │  │
│  │ - Session│ │               │  │ - AuthZ    │  │
│  │ - Tokens │ │               │  │ - Policy   │  │
│  └──────────┘ │               │  └────────────┘  │
│  ┌──────────┐ │               │  ┌────────────┐  │
│  │ Postgres │ │               │  │ OAuth      │  │
│  │ - Users  │ │               │  │ Providers  │  │
│  │ - Keys   │ │               │  └────────────┘  │
│  └──────────┘ │               │                  │
└───────────────┘               └──────────────────┘
Core Components

1. Authentication Service

REQ-099-067: The Authentication Service SHALL be a stateless REST API that handles API-key, OAuth 2.0 and session-token authentication, manages the JWT access and refresh token lifecycle, integrates with the TOTP and SMS MFA providers, and enforces rate limiting and account-lockout policies.

2. Authorization Engine

REQ-099-068: The Authorization Engine SHALL delegate every authorization decision to PAM++, SHALL cache policy decisions to reduce PAM++ queries, SHALL support RBAC with permission inheritance, and SHALL take request time, IP and user agent into account.

3. Token Management

REQ-099-069: Token Management SHALL issue JWT access tokens valid for 1 hour and refresh tokens valid for 7 days, SHALL maintain a token blacklist for immediate revocation, and SHALL use Redis for distributed token validation.

4. Session Store

REQ-099-070: The Session Store SHALL run on a Redis cluster for high availability, SHALL store active sessions with TTL-based expiry, SHALL support distributed session invalidation, and SHALL encrypt sensitive session data at rest.

5. Secrets Management

REQ-099-071: Secrets Management SHALL integrate with HashiCorp Vault or AWS Secrets Manager, SHALL rotate data encryption keys automatically every month, SHALL support an HSM for master keys, and SHALL log every key access centrally.

6. Audit Logging

REQ-099-072: Audit Logging SHALL store entries with hash chains for tamper resistance, SHALL keep 90 days of hot storage in Elasticsearch and 7 years of cold storage in S3 Glacier, and SHALL stream events to SIEM systems in real time.

Data Flow

Authentication Flow:

User Request → Auth Middleware → Validate Token → PAM++ AuthZ → Handler
                                              ↓ (if valid)
                                     Attach User Context

REQ-099-073: Every request SHALL pass through the auth middleware, which SHALL validate the token and obtain a PAM++ authorization decision before the handler runs, and SHALL attach the user context to the request when the token is valid.

Token Lifecycle:

Login → Create Session (24h) → Issue Access Token (1h) → Issue Refresh Token (7d)
                                                              ↓
                                                    Refresh Token Used
                                                              ↓
                                                    Validate & Issue New Tokens
                                                              ↓
                                                    Invalidate Old Refresh Token

REQ-099-074: Login SHALL create a 24-hour session, issue a 1-hour access token and a 7-day refresh token; presenting a refresh token SHALL validate it, issue new tokens and invalidate the old refresh token.

Authorization Flow:

Request → Extract User/Permission → Query PAM++ → Cache Decision → Enforce
                                                      ↓ (cached)
                                               Return Cached Result

REQ-099-075: An authorization request SHALL extract the user and the required permission, query PAM++, cache the decision and enforce it; a cached decision SHALL be returned without re-querying PAM++.

Design Patterns

1. Middleware Pattern

REQ-099-076: The system SHALL implement middleware that validates tokens before request handling, enforces PAM++ authorization policies, enforces per-user rate quotas, and logs all security events for audit.

2. Repository Pattern

REQ-099-077: The system SHALL implement a UserRepository for user database operations, a TokenRepository for token validation and storage, a SessionRepository for session lifecycle management, and an AuditRepository for audit-log writing and retrieval.

3. Strategy Pattern

REQ-099-078: The system SHALL implement interchangeable strategies for authentication (API key, OAuth, session), encryption (AES-256-GCM across backends), secrets management (Vault, AWS, environment) and MFA (TOTP, SMS, U2F).

4. Observer Pattern

REQ-099-079: The system SHALL implement observers for security-event audit logging, token-revocation blacklist updates, failed-login account lockout, and policy-change cache invalidation.

Database Schema

Users Table:

CREATE TABLE users (
    id VARCHAR(32) PRIMARY KEY,
    email VARCHAR(255) UNIQUE NOT NULL,
    name VARCHAR(100) NOT NULL,
    role VARCHAR(32) NOT NULL,
    password_hash VARCHAR(255),
    mfa_enabled BOOLEAN DEFAULT FALSE,
    mfa_secret_encrypted TEXT,
    account_locked BOOLEAN DEFAULT FALSE,
    failed_login_attempts INTEGER DEFAULT 0,
    created_at TIMESTAMP NOT NULL,
    last_login TIMESTAMP,
    INDEX idx_email (email),
    INDEX idx_role (role)
);

REQ-099-080: The users table SHALL hold id, email (unique, not null), name, role, password_hash, mfa_enabled, mfa_secret_encrypted, account_locked, failed_login_attempts, created_at and last_login, indexed on email and role.

API Keys Table:

CREATE TABLE api_keys (
    id VARCHAR(32) PRIMARY KEY,
    user_id VARCHAR(32) NOT NULL,
    name VARCHAR(100) NOT NULL,
    key_hash VARCHAR(255) NOT NULL,
    prefix VARCHAR(12) NOT NULL,
    permissions JSON NOT NULL,
    created_at TIMESTAMP NOT NULL,
    expires_at TIMESTAMP,
    last_used TIMESTAMP,
    revoked BOOLEAN DEFAULT FALSE,
    revoked_at TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id),
    INDEX idx_user_id (user_id),
    INDEX idx_prefix (prefix)
);

REQ-099-081: The api_keys table SHALL hold id, user_id (foreign key to users), name, key_hash, prefix, permissions, created_at, expires_at, last_used, revoked and revoked_at, indexed on user_id and prefix.

Sessions Table:

CREATE TABLE sessions (
    id VARCHAR(32) PRIMARY KEY,
    user_id VARCHAR(32) NOT NULL,
    refresh_token_hash VARCHAR(255) NOT NULL,
    access_token_hash VARCHAR(255),
    ip_address INET,
    user_agent TEXT,
    created_at TIMESTAMP NOT NULL,
    expires_at TIMESTAMP NOT NULL,
    revoked BOOLEAN DEFAULT FALSE,
    revoked_at TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id),
    INDEX idx_user_id (user_id),
    INDEX idx_refresh_token (refresh_token_hash),
    INDEX idx_expires_at (expires_at)
);

REQ-099-082: The sessions table SHALL hold id, user_id (foreign key to users), refresh_token_hash, access_token_hash, ip_address, user_agent, created_at, expires_at, revoked and revoked_at, indexed on user_id, refresh_token_hash and expires_at.

Caching Strategy

1. PAM++ Decision Cache

REQ-099-083: PAM++ decisions SHALL be cached in Redis under pam:decision:{user_id}:{permission}:{resource} with a 300-second TTL, and SHALL be invalidated on policy change or user role change.

2. Token Validation Cache

REQ-099-084: Token validation results SHALL be cached in per-instance memory under `token:«redacted» for the token's remaining lifetime, so that validation does not require a Redis lookup on every request.

3. Rate Limit Cache

REQ-099-085: Rate-limit counters SHALL be held in Redis under ratelimit:{user_id}:{endpoint} as a sliding-window counter over a rolling window.

4. User Permission Cache

REQ-099-086: User permissions SHALL be cached in Redis under perms:{user_id} with a 3600-second TTL, and SHALL be invalidated on role change or on explicit invalidation.

Security Controls

1. Defense in Depth

REQ-099-087: The system SHALL apply defence in depth: WAF, DDoS protection and VPN requirement at the network layer; input validation, output encoding and CSRF protection at the application layer; encryption at rest and in transit at the data layer; and MFA, password policies and account lockout at the identity layer.

2. Zero Trust Architecture

REQ-099-088: The system SHALL follow a zero-trust architecture: it SHALL authenticate and authorize every request, SHALL assume breach and monitor accordingly, and SHALL grant least-privilege access.

3. Secure by Default

REQ-099-089: The system SHALL be secure by default: access SHALL be denied unless an explicit allow policy exists, configuration SHALL follow secure baselines, and the attack surface SHALL be kept minimal.

4. Encryption Strategy

REQ-099-090: Data at rest SHALL be encrypted with AES-256-GCM under key rotation, data in transit SHALL use TLS 1.3 with perfect forward secrecy, keys SHALL be managed by an HSM or Vault with automatic rotation, and tokens SHALL be stored hashed with bcrypt at cost factor 12 or higher.

Monitoring & Observability

1. Metrics

REQ-099-220: The system SHALL emit metrics for authentication success and failure rates, authorization decision latencies, token issuance and validation counts, rate-limit triggers and violations, and session creation and expiry rates.

2. Logging

REQ-099-221: Logs SHALL be structured JSON, SHALL carry correlation IDs for request tracing, SHALL record security events with an appropriate severity, and SHALL keep audit logs tamper-resistant.

3. Alerting

REQ-099-222: The system SHALL alert on failed-login thresholds being exceeded, unusual authentication patterns, PAM++ service unavailability, token-blacklist failures, and audit-log tampering detection.

4. Dashboards

REQ-099-223: Dashboards SHALL present real-time authentication metrics, authorization decision analytics, the security incident timeline, and compliance status indicators.


Examples

Example 1: API Key Authentication
import requests

# Authenticate with API key
headers = {
    "Authorization": "Bearer sk_test_1234567890abcdef"
}
response = requests.get(
    "https://api.orchestrata.local/v1/users/me",
    headers=headers
)
print(response.json())
Example 2: JWT Session Token
import jwt

# Decode JWT token
token = «redacted»
payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
print(f"User: {payload['sub']}, Expires: {payload['exp']}")
Example 3: MFA TOTP Setup
import pyotp

# Generate TOTP secret
secret = «redacted»
totp = pyotp.TOTP(secret)

# Verify code
code = input("Enter MFA code: ")
print(totp.verify(code))  # True/False
Example 4: Rate Limit Handling
import time

def make_request_with_retry(url, headers, max_retries=3):
    for attempt in range(max_retries):
        response = requests.get(url, headers=headers)
        if response.status_code == 429:
            wait_time = int(response.headers["Retry-After"])
            print(f"Rate limited. Waiting {wait_time}s...")
            time.sleep(wait_time)
        else:
            return response
    raise Exception("Max retries exceeded")

Governance

PAM++ Policy Engine

The system integrates with PAM++ (Prolog Authorization Manager) for governance decisions:

Policy Structure:

REQ-099-091: Governance policies SHALL be defined in Prolog syntax, SHALL be evaluated in order of specificity, SHALL default to denying all access, and every governance decision SHALL be logged for audit.

Policy Categories:

REQ-099-092: The policy engine SHALL support Access Control Policies (ACP), Data Governance Policies (DGP) and Compliance Policies (CP).

Governance Flow:

  1. User attempts action
  2. Auth middleware validates authentication
  3. Authorization middleware queries PAM++
  4. PAM++ evaluates rules with context
  5. Decision returned with policy ID
  6. Action allowed or denied

REQ-099-093: When a user attempts an action, the auth middleware SHALL validate authentication, the authorization middleware SHALL query PAM++, PAM++ SHALL evaluate its rules against the request context, and the decision SHALL be returned with its policy ID before the action is allowed or denied.

Compliance Controls
Control ID Framework Requirement
CC6.1 SOC 2 Logical and physical access controls
CC6.2 SOC 2 User provisioning and deprovisioning
CC6.6 SOC 2 Password management and complexity
Art. 32 GDPR Security of processing measures
8.2 PCI DSS Strong authentication mechanisms
AC-2 NIST Account management lifecycle
IA-5 NIST Authenticator management

REQ-099-094: The system SHALL implement the compliance controls listed above: SOC 2 CC6.1, CC6.2 and CC6.6, GDPR Article 32, PCI DSS 8.2, and NIST AC-2 and IA-5.


Integration Points

External Authentication Providers

GitHub OAuth:

REQ-099-095: GitHub OAuth SHALL use the authorization URL https://github.com/login/oauth/authorize, the token URL https://github.com/login/oauth/access_token, the user-info URL https://api.github.com/user, and the scopes read:user and user:email.

Google OAuth:

REQ-099-096: Google OAuth SHALL use the authorization URL https://accounts.google.com/o/oauth2/v2/auth, the token URL https://oauth2.googleapis.com/token, the user-info URL https://www.googleapis.com/oauth2/v3/userinfo, and the scopes openid, email and profile.

GitLab OAuth:

REQ-099-097: GitLab OAuth SHALL use the authorization URL https://gitlab.com/oauth/authorize, the token URL https://gitlab.com/oauth/token, the user-info URL https://gitlab.com/api/v4/user, and the scopes read_user and api.

Secrets Management

HashiCorp Vault:

REQ-099-098: The HashiCorp Vault backend SHALL take its address from VAULT_ADDR, SHALL authenticate with the token in VAULT_TOKEN, SHALL use the KV v2 secrets engine, and SHALL rotate keys automatically every month.

AWS Secrets Manager:

REQ-099-099: The AWS Secrets Manager backend SHALL take a configurable region, SHALL authenticate with an IAM role, SHALL store secrets as JSON, and SHALL rotate keys with a Lambda function.

Session Storage

Redis Cluster:

REQ-099-100: Session storage SHALL run on a Redis cluster of at least 3 master nodes, with AOF persistence every 1 second, TLS 1.3 transport, and Redis AUTH password protection.

Audit Storage

Primary: Elasticsearch (hot storage - 90 days) Secondary: S3 Glacier (cold storage - 7 years) Format: JSON with hash chain

REQ-099-101: Audit records SHALL be written as JSON with a hash chain, held in Elasticsearch hot storage for 90 days, and archived to S3 Glacier cold storage for 7 years.


Success Criteria

Authentication

REQ-099-102: Authentication SHALL be accepted only when users can authenticate with email and password, with API keys and via OAuth providers, session tokens expire after the configured duration, and refresh tokens allow re-authentication without a fresh login.

Authorization

REQ-099-103: Authorization SHALL be accepted only when PAM++ queries return the correct decisions, RBAC enforces role-based permissions, resource-level permissions are enforced, and the default deny policy blocks unauthorized access.

MFA

REQ-099-104: MFA SHALL be accepted only when TOTP setup generates unique secrets, TOTP verification succeeds for valid codes, backup codes can be used for recovery, and account lockout triggers at the threshold.

Security

REQ-099-105: Security SHALL be accepted only when passwords meet the complexity requirements, API keys are hashed before storage, data at rest is encrypted with AES-256-GCM, all connections use TLS 1.3, and token revocation takes effect immediately.

Audit

REQ-099-106: Audit SHALL be accepted only when all authentication events and authorization decisions are logged, audit logs are tamper-resistant, hash-chain verification works, and logs are retained for 7 years.

Rate Limiting

REQ-099-107: Rate limiting SHALL be accepted only when authentication endpoints carry stricter limits, general endpoints carry configurable limits, account lockout triggers after 5 failures, and progressive delays prevent brute-force attempts.

Compliance

REQ-099-108: Compliance SHALL be accepted only when the SOC 2 controls, GDPR Article 32, PCI DSS 8.2 and NIST AC-2 and IA-5 requirements are met.


Observability

Logging Requirements
  1. Component Logging
    • Log all major operations with appropriate log levels
    • Include correlation IDs for request tracing
    • Log performance metrics for critical operations
    • Log errors with full context for debugging

REQ-099-224: Components SHALL log all major operations at appropriate log levels, SHALL include correlation IDs for request tracing, SHALL log performance metrics for critical operations, and SHALL log errors with full context.

Metrics Requirements
  1. Performance Metrics
    • Operation duration histograms
    • Request/error rate counters
    • Resource utilization gauges
    • Business metrics relevant to domain

REQ-099-225: The system SHALL expose operation duration histograms, request and error rate counters, resource utilization gauges, and business metrics relevant to the domain.

Tracing Requirements
  1. Distributed Tracing
    • Trace propagation across component boundaries
    • Span attributes for domain-specific context
    • Trace sampling based on operational needs

REQ-099-226: The system SHALL propagate traces across component boundaries, SHALL attach domain-specific span attributes, and SHALL sample traces according to operational needs.

Alerting Requirements
  1. Critical Alerts
    • Error rate spikes
    • Performance degradation
    • Resource exhaustion
    • Business metric anomalies

REQ-099-227: The system SHALL raise critical alerts on error-rate spikes, performance degradation, resource exhaustion, and business-metric anomalies.

Dashboard Requirements
  1. Operational Dashboard
    • Real-time system health
    • Performance trends
    • Error analysis
    • Resource monitoring

REQ-099-228: The operational dashboard SHALL present real-time system health, performance trends, error analysis and resource monitoring.


Visual Architecture

Class Diagram

Diagram source shown as text: Mermaid could not parse it (Error: Parse error on line 11:).

classDiagram-direction LR
    class GovernanceEngine {
        +__init__()
        #_load_default_policies(): dict[str, Any]
        +async check(action: str, context: dict[str, Any]): bool
        #async _check_edit_file(context: dict[str, Any]): bool
        #async _check_create_project(context: dict[str, Any]): bool
        #async _check_execute_command(context: dict[str, Any]): bool
    }
PAM++ Authentication
# PAM++ client configuration
PAM_CONFIG = {
    "host": "pam.orchestrata.local",
    "port": 8080,
    "auth": {
        "type": "api_key",
        "key": os.environ["PAM_API_KEY"]
    },
    "timeout": 5.0
}

async def authenticate_with_pam(user_id: str, credentials: dict):
    """Authenticate user with PAM++."""
    async with httpx.AsyncClient() as client:
        response = await client.post(
            f"http://{PAM_CONFIG['host']}:{PAM_CONFIG['port']}/auth",
            json={
                "user_id": user_id,
                "credentials": credentials
            },
            headers={"Authorization": f"Bearer {PAM_CONFIG['auth']['key']}"}
        )
        return response.json()

REQ-099-109: The PAM++ client SHALL be configured with the PAM++ host, port, API-key authentication and a 5.0-second timeout, and SHALL authenticate a user by posting the user id and credentials to the PAM++ /auth endpoint with the API key as a bearer token.

Error Handling
# PAM++ unavailable fallback
if pam_error:
    if error_type == "timeout":
        # Allow access, log event
        await log_event("PAM_TIMEOUT_ALLOW", user_id)
    elif error_type == "unavailable":
        # Deny access
        raise PAMUnavailableError("Authorization service unavailable")

REQ-099-110: On a PAM++ timeout the system SHALL log a PAM_TIMEOUT_ALLOW event and allow access; when PAM++ is unavailable the system SHALL deny access by raising PAMUnavailableError.


Rate Limiting Granularity

Per-Endpoint Limits
ENDPOINT_LIMITS = {
    "/api/v1/auth/login": {"requests": 5, "window": 300},
    "/api/v1/auth/verify_mfa": {"requests": 10, "window": 60},
    "/api/v1/intent": {"requests": 30, "window": 60},
    "/api/v1/agents/*": {"requests": 60, "window": 60}
}

REQ-099-111: Per-endpoint rate limits SHALL be enforced as 5 requests per 300 seconds on /api/v1/auth/login, 10 per 60 seconds on /api/v1/auth/verify_mfa, 30 per 60 seconds on /api/v1/intent, and 60 per 60 seconds on /api/v1/agents/*.

Account Lockout Policy
LOCKOUT_THRESHOLD = 5  # failed login attempts
LOCKOUT_DURATION = 1800  # 30 minutes

# Progressive delays
LOGIN_DELAY_BASE = 1  # 1 second
LOGIN_DELAY_MAX = 64  # 64 seconds

REQ-099-112: Accounts SHALL be locked after 5 failed login attempts for 1800 seconds, and login delays SHALL progress from a 1-second base up to a 64-second maximum.


Audit Log Tamper Resistance

Write-Once Read-Many (WORM)
import hashlib

async def write_audit_log(entry: dict):
    """Write audit log with tamper resistance."""
    # Add hash chain
    previous_hash = await get_last_audit_hash()
    entry["previous_hash"] = previous_hash
    entry["timestamp"] = datetime.utcnow().isoformat()
    
    # Calculate entry hash
    entry_content = json.dumps(entry, sort_keys=True)
    entry["hash"] = hashlib.sha256(entry_content.encode()).hexdigest()
    
    # Store in WORM storage (immutable)
    await storage.append("audit_log", entry)
    
    return entry["hash"]

REQ-099-113: Each audit entry SHALL carry the previous entry's hash and a timestamp, SHALL be hashed with SHA-256 over its canonically-sorted JSON content, and SHALL be appended to immutable WORM storage.

Hash Chain Verification
async def verify_audit_chain():
    """Verify integrity of audit log chain."""
    entries = await storage.read("audit_log")
    
    for i in range(1, len(entries)):
        current = entries[i]
        previous = entries[i - 1]
        
        # Verify hash chain
        computed_hash = hashlib.sha256(
            json.dumps(current, sort_keys=True).encode()
        ).hexdigest()
        
        if current["hash"] != computed_hash:
            raise AuditLogTamperError(f"Tamper detected at entry {i}")
        
        if current["previous_hash"] != previous["hash"]:
            raise AuditLogTamperError(f"Chain broken at entry {i}")

REQ-099-114: Audit-chain verification SHALL recompute every entry's hash and SHALL raise a tamper error when an entry's hash does not match its content or its recorded previous hash does not match the preceding entry.


Password Policy

Requirements
PASSWORD_POLICY = {
    "min_length": 12,
    "max_length": 128,
    "require_uppercase": True,
    "require_lowercase": True,
    "require_numbers": True,
    "require_special": True,
    "disallow_common": True,
    "disallow_personal": True  # Don't use email, name, etc.
}

REQ-099-115: Passwords SHALL be at least 12 and at most 128 characters, SHALL contain uppercase, lowercase, numeric and special characters, and SHALL be rejected when they match a common password or contain the user's personal information.

Validation
def validate_password(password: str, user_info: dict) -> bool:
    """Validate password against policy."""
    if len(password) < PASSWORD_POLICY["min_length"]:
        return False
    
    if not re.search(r'[A-Z]', password):
        return False
    
    if not re.search(r'[a-z]', password):
        return False
    
    if not re.search(r'[0-9]', password):
        return False
    
    if not re.search(r'[!@#$%^&*(),.?":{}|<>]', password):
        return False
    
    # Check against common passwords
    if password.lower() in COMMON_PASSWORDS:
        return False
    
    # Check against personal info
    for value in user_info.values():
        if isinstance(value, str) and value.lower() in password.lower():
            return False
    
    return True

Compliance Mapping

Control Implementation
SOC 2 CC6.1 - Logical Access PAM++ authorization, MFA
SOC 2 CC6.2 - User Provisioning User lifecycle management
SOC 2 CC6.6 - Password Policy Password validation, hashing
GDPR Art. 32 - Security Encryption at rest and in transit
PCI DSS 8.2 - Authentication Strong authentication, MFA
NIST AC-2 - Account Management Automated provisioning/deprovisioning
NIST IA-5 - Authenticator Management TOTP, backup codes, rotation

Authentication

Authentication Methods

Method Use Case Security Level
API Key CLI, scripts High
OAuth 2.0 Web UI High
Session Token Web UI (remember me) Medium
Service Account Internal services High

REQ-099-116: The system SHALL support API-key authentication for CLI and scripts, OAuth 2.0 for the web UI, session tokens for persistent web-UI login, and service-account authentication for internal services.

API Key Authentication

Header Format:

Authorization: Bearer sk_abc123def456

Key Format:

Key Generation:

def generate_api_key() -> str:
    return "sk_" + secrets.token_urlsafe(32)

REQ-099-117: An API key SHALL be presented as Authorization: Bearer <key>, SHALL carry the sk_ prefix, SHALL be at least 32 characters drawn from alphanumeric characters and underscore, and SHALL be generated from a cryptographically secure URL-safe random source.

OAuth 2.0 Integration

Supported Providers:

OAuth Flow:

  1. User clicks "Login with GitHub"
  2. Redirect to GitHub OAuth
  3. GitHub calls back with code
  4. Exchange code for token
  5. Create session, redirect to app

REQ-099-118: The OAuth 2.0 flow SHALL redirect the user to the provider, SHALL accept the provider's callback code, SHALL exchange that code for a token, and SHALL then create a session and redirect the user back to the application.

Session Management

Session Token:

Session Storage:

REQ-099-119: The session token SHALL be a JWT expiring after a configurable 24 hours with a 7-day refresh token, and sessions SHALL be stored in Redis for distributed access and encrypted at rest.


Authorization

PAM++ Integration

The system integrates with PAM++ (Prolog Authorization Manager) for authorization decisions.

Authorization Flow:

Request → Auth Middleware → PAM++ Query → Decision → Handler

PAM++ Query Structure:

can_perform(
    User: user_123,
    Action: edit_file,
    Resource: file:///project/src/main.py,
    Context: #{
        timestamp: now,
        ip: "192.168.1.1",
        method: post
    }
) -> Decision
Permission Levels
Level Scope Example
Global System-wide admin, auditor
Project Specific project project_admin, developer
Resource Specific resource file_owner
Action Specific action can_deploy
Roles

Built-in Roles:

REQ-099-120: The system SHALL provide the built-in roles admin (full system access), auditor (read-only access to audit logs), project_admin (manage project configuration), developer (read/write code, create tasks), viewer (read-only project access) and guest (minimal access to public projects).


Encryption

Data Encryption

At Rest:

REQ-099-121: Data at rest SHALL be encrypted: database fields with AES-256-GCM, file storage on an encrypted filesystem, and backups with a key from the key vault.

In Transit:

REQ-099-122: Data in transit SHALL be encrypted: all HTTP over TLS 1.3, all WebSocket traffic over WSS, and all internal traffic over mTLS.

Key Management

Key Types:

REQ-099-123: The master key SHALL be held in an HSM or secure vault, data encryption keys SHALL be encrypted by the master key, and API keys SHALL be stored hashed with bcrypt.

Key Rotation:

REQ-099-124: The master key SHALL be rotated annually by manual action, data encryption keys SHALL be rotated monthly and automatically, and API keys SHALL be rotated on compromise or annually.

Secrets Management

Supported Backends:

REQ-099-125: Secrets management SHALL support HashiCorp Vault and AWS Secrets Manager as backends, and environment variables SHALL be used as a secrets backend in development only.


Security Middleware

Authentication Middleware
class AuthMiddleware:
    """Authenticates requests and attaches user context."""
    
    async def __call__(self, request, handler):
        # Extract token from header
        token = «redacted»
        
        # Validate token
        user = await self.validate_token(token)
        
        # Attach user to request
        request.user = user
        
        # Continue to handler
        return await handler(request)

REQ-099-126: The authentication middleware SHALL extract the token from the request header, SHALL validate it, and SHALL attach the resolved user to the request before the handler runs.

Authorization Middleware
class AuthorizationMiddleware:
    """Enforces PAM++ authorization."""
    
    async def __call__(self, request, handler):
        # Get required permission from route
        permission = self.get_required_permission(request)
        
        # Check with PAM++
        decision = await self.pam.check(
            user=request.user,
            permission=permission,
            resource=request.path
        )
        
        if not decision.allowed:
            raise ForbiddenError(decision.reason)
        
        return await handler(request)

REQ-099-127: The authorization middleware SHALL determine the permission required by the route, SHALL check it against PAM++ for the request user and resource, and SHALL reject the request with the decision's reason when access is not allowed.

Rate Limiting Middleware
class RateLimitMiddleware:
    """Enforces per-user rate limits."""
    
    async def __call__(self, request, handler):
        # Get user identifier
        user_id = self.get_user_id(request)
        
        # Check rate limit
        if not await self.ratelimiter.check(user_id):
            raise RateLimitError(
                retry_after=self.ratelimiter.retry_after(user_id)
            )
        
        return await handler(request)

REQ-099-128: The rate-limiting middleware SHALL identify the requesting user, SHALL check that user's rate limit, and SHALL reject the request with a retry-after value when the limit is exceeded.


Audit Logging

Audit Events
Event Type Data Captured
Authentication User, method, IP, result
Authorization User, permission, resource, decision
Data Access User, resource, action
Data Modification User, resource, old_value, new_value
Configuration User, setting, old_value, new_value
Security Event type, details, severity

REQ-099-129: The audit log SHALL capture, for authentication the user, method, IP and result; for authorization the user, permission, resource and decision; for data access the user, resource and action; for data modification the user, resource, old value and new value; for configuration changes the user, setting, old value and new value; and for security events the event type, details and severity.

Audit Log Format
{
  "event_id": "evt_123456789",
  "event_type": "authorization",
  "timestamp": "2026-04-08T14:30:00Z",
  "user": {
    "id": "user_123",
    "role": "developer"
  },
  "action": "edit_file",
  "resource": "file:///project/src/main.py",
  "decision": "allow",
  "context": {
    "ip": "192.168.1.1",
    "user_agent": "curl/7.68.0",
    "method": "POST"
  },
  "governance": {
    "policy_id": "POL-001",
    "rule_id": "RULE-010",
    "matched": true
  }
}

REQ-099-130: Each audit entry SHALL carry event_id, event_type, timestamp, the acting user's id and role, action, resource, decision, the request context (IP, user agent, method) and the governance policy id, rule id and match flag.

Audit Retention

REQ-099-131: Audit records SHALL be searchable in hot storage for 90 days, archived for 7 years, and SHALL have personally identifiable information redacted after 1 year.


Security Configuration

Configuration Schema
{
  "security": {
    "authentication": {
      "methods": ["api_key", "oauth2"],
      "session": {
        "expiry_seconds": 86400,
        "refresh_expiry_seconds": 604800
      },
      "oauth2": {
        "providers": ["github", "google"],
        "client_id": "${OAUTH_CLIENT_ID}",
        "client_secret": "${OAUTH_CLIENT_SECRET}"
      }
    },
    "authorization": {
      "enabled": true,
      "policy_engine": "pam++",
      "default_policy": "deny"
    },
    "encryption": {
      "algorithm": "AES-256-GCM",
      "key_rotation_days": 30,
      "vault_backend": "hashicorp"
    },
    "rate_limiting": {
      "enabled": true,
      "default_limit": 60,
      "burst_limit": 10
    },
    "audit": {
      "enabled": true,
      "retention_days": 2555,
      "hot_storage_days": 90
    }
  }
}

REQ-099-132: The security configuration SHALL accept the enabled authentication methods, a session expiry of 86400 seconds and refresh expiry of 604800 seconds, the OAuth 2.0 providers and credentials, an authorization block with pam++ as policy engine and deny as default policy, an encryption block with AES-256-GCM and a 30-day key rotation against the configured vault backend, a rate-limiting block with default and burst limits, and an audit block with 2555-day retention and 90-day hot storage.

Environment Variables
Variable Description
SECRET_KEY Master encryption key
OAUTH_CLIENT_ID OAuth app client ID
OAUTH_CLIENT_SECRET OAuth app client secret
VAULT_ADDR HashiCorp Vault address
VAULT_TOKEN Vault authentication token

REQ-099-133: The system SHALL read SECRET_KEY for the master encryption key, OAUTH_CLIENT_ID and OAUTH_CLIENT_SECRET for the OAuth application credentials, and VAULT_ADDR and VAULT_TOKEN for the HashiCorp Vault address and authentication token.


Error Handling

Authentication Errors
Code Message HTTP Code
AUTH-001 Invalid API key 401
AUTH-002 API key expired 401
AUTH-003 Session expired 401
AUTH-004 OAuth failed 401

REQ-099-134: Authentication failures SHALL be reported as AUTH-001 invalid API key, AUTH-002 API key expired, AUTH-003 session expired and AUTH-004 OAuth failed, each with HTTP status 401.

Authorization Errors
Code Message HTTP Code
AUTHZ-001 Access denied 403
AUTHZ-002 Governance blocked 451
AUTHZ-003 Insufficient permissions 403

REQ-099-135: Authorization failures SHALL be reported as AUTHZ-001 access denied with HTTP status 403, AUTHZ-002 governance blocked with HTTP status 451, and AUTHZ-003 insufficient permissions with HTTP status 403.

Error Response Format
{
  "error": {
    "code": "AUTHZ-001",
    "message": "Access denied",
    "details": {
      "reason": "User role 'viewer' does not have 'edit' permission",
      "resource": "file:///project/src/main.py",
      "policy": "POL-001"
    },
    "request_id": "req_123456789"
  }
}

REQ-099-136: Every error response SHALL carry the error code, the message, the details (reason, resource and policy) and the request id.


Testing Requirements

Security Tests

REQ-099-229: The security test suite SHALL prove that authentication succeeds with valid credentials and fails with invalid ones, that authorization blocks unauthorized actions and allows authorized ones, that rate limiting triggers at the threshold, that audit logs capture all security events, that encryption at rest works, and that session expiry works.

Penetration Testing

REQ-099-230: The system SHALL prevent SQL injection, cross-site scripting, cross-site request forgery, path traversal and command injection, and penetration testing SHALL cover each of them.


Compliance

Standards

REQ-099-231: The system SHALL conform to the OWASP Top 10, SOC 2 Type II, the GDPR data-handling requirements and the CCPA data-handling requirements.

Security Headers
Strict-Transport-Security: max-age=31536000; includeSubDomains
Content-Security-Policy: default-src 'self'
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin

REQ-099-137: Responses SHALL carry the security headers Strict-Transport-Security: max-age=31536000; includeSubDomains, Content-Security-Policy: default-src 'self', X-Content-Type-Options: nosniff, X-Frame-Options: DENY, X-XSS-Protection: 1; mode=block and Referrer-Policy: strict-origin-when-cross-origin.


Incident Response

Security Incident Classification
Severity Description Response Time
Critical Data breach, full system compromise 1 hour
High Unauthorized access, privilege escalation 4 hours
Medium Policy violation, suspicious activity 24 hours
Low Minor security concern 7 days

REQ-099-138: Security incidents SHALL be classified and answered within the stated response times: critical (data breach or full system compromise) within 1 hour, high (unauthorized access or privilege escalation) within 4 hours, medium (policy violation or suspicious activity) within 24 hours, and low (minor security concern) within 7 days.

Incident Response Steps
  1. Detect: Identify security event
  2. Contain: Limit damage
  3. Eradicate: Remove threat
  4. Recover: Restore normal operation
  5. Document: Record incident details
  6. Review: Improve defenses

REQ-099-139: Incident response SHALL follow the steps detect, contain, eradicate, recover, document and review.


Dependencies

Dependency Version Purpose
PyJWT >=2.8 JWT handling
passlib >=1.7 Password hashing
cryptography >=41.0 Encryption
httpx >=0.25 HTTP client
structlog >=24.0 Structured logging

REQ-099-140: The framework SHALL depend on PyJWT >=2.8 for JWT handling, passlib >=1.7 for password hashing, cryptography >=41.0 for encryption, httpx >=0.25 for HTTP requests, and structlog >=24.0 for structured logging.


Data Models

User
{
  "user": {
    "id": "user_123",
    "email": "user@example.com",
    "name": "John Doe",
    "role": "developer",
    "projects": ["proj_001", "proj_002"],
    "created_at": "2026-01-01T00:00:00Z",
    "last_login": "2026-04-08T14:00:00Z",
    "mfa_enabled": true
  }
}
API Key
{
  "api_key": {
    "id": "key_abc123",
    "user_id": "user_123",
    "name": "Development",
    "prefix": "sk_abc",
    "permissions": ["read", "write"],
    "created_at": "2026-04-01T00:00:00Z",
    "expires_at": "2027-04-01T00:00:00Z",
    "last_used": "2026-04-08T14:00:00Z"
  }
}
Session
{
  "session": {
    "id": "sess_xyz789",
    "user_id": "user_123",
    "refresh_token": "rt_...",
    "expires_at": "2026-04-09T14:00:00Z",
    "ip_address": "192.168.1.1",
    "user_agent": "Mozilla/5.0...",
    "created_at": "2026-04-08T14:00:00Z"
  }
}