# CASAN Control Plane Status: production-capable packaged authentication and trust configuration; external infrastructure remains operator-provisioned. ## Deployment modes ### Local development - Default bind: `127.0.0.1`. - `CASAN_CP_AUTH_MODE=local` is allowed only on loopback and outside production. - Local actor headers are explicitly development identity and are not a production authentication claim. ### Networked or production - `CASAN_CP_AUTH_MODE=jwt` is mandatory. - Production requires RS256 verification, a mounted public key, exact issuer and audience, and a clock skew from 0 through 300 seconds. - Missing or invalid configuration refuses startup before NestJS listens. - HS256 is retained only for deterministic non-production tests. ## Packaged identity boundary ```text Browser -> enterprise OIDC -> oauth2-proxy session -> Nginx auth_request removes X-CASAN-* and forwarded identity headers forwards signed Bearer access token -> NestJS AuthProvider verifies RS256 signature, iss, aud, sub, exp, nbf and iat -> VerifiedClaims -> CASAN RBAC role mapping and scoped request identity ``` Nginx is a TLS/session boundary, not the identity authority for the API. The API ignores caller-supplied identity assertions and derives actor, role, tenant and project only after token verification. ## Authentication implementation `backend/src/common/auth-provider.ts` defines: - `AuthProvider` and `JwtAuthProvider`. - Typed `VerifiedClaims` and `AuthenticationDecision`. - RS256/HS256 signature verification using Node's standard crypto APIs. - Issuer, audience, expiry, not-before, issued-at and bounded-skew checks. - Safe tenant/project syntax validation. - Structured authentication audit evidence without raw tokens. - Middleware that overwrites request identity only from verified claims. `auth-context.ts` refuses direct header use in JWT mode unless the middleware has marked the identity verified. Existing RBAC services then map verified groups and continue to produce governance/authorization evidence. ## Production configuration Required runtime variables: ```text CASAN_PROFILE=prod CASAN_CP_AUTH_MODE=jwt CASAN_CP_JWT_ISSUER=https://... CASAN_CP_JWT_AUDIENCE=... CASAN_CP_JWT_PUBLIC_KEY_FILE=/run/casan-idp/idp-public.pem CASAN_CP_JWT_ROLE_CLAIM=groups CASAN_CP_JWT_TENANT_CLAIM=casan_tenant CASAN_CP_JWT_PROJECT_CLAIM=casan_project CASAN_CP_JWT_CLOCK_SKEW_SECONDS=60 ``` The host path is configured as `CASAN_CP_IDP_PUBLIC_KEY` and mounted read-only. oauth2-proxy must set xauthrequest output and pass the access token. Images for API, UI and oauth2-proxy must be digest-pinned. `production-preflight.sh` validates: - TLS hostname, expiry and matching private key. - IdP public key readability and RSA public-key format. - HTTPS OIDC issuer, secure cookies and token forwarding. - Matching oauth2-proxy client ID and API audience. - Matching issuer and bounded JWT clock skew. - External Vault/KMS signing and S3 Object Lock provider selection. - Live short-lived non-root Vault token lookup. - A real Object Lock COMPLIANCE anchor write. - Digest-pinned images and valid Compose/Nginx configuration. ## Authentication evidence Each production authentication decision appends a JSONL record under `CASAN_STATE_ROOT/logs/auth/decisions.jsonl` with category, policy, decision, reason, actor, issuer, scope and request method/path. Tokens and secrets are never written. A failure to authenticate returns HTTP 401 with a stable reason code; it is not converted to viewer access. ## Local production-like smoke `docker-compose.control-panel.local.yml` uses the same bearer-token path. The smoke script generates an ephemeral RSA keypair, mounts the private key into the mock IdP and the public key into the API, and enables token forwarding. This validates the boundary without treating the mock IdP as production. ## Residual limitations - Public-key rotation currently requires replacing the mounted key and restarting the API; automated JWKS discovery and rollover are not present. - Enterprise IdP, managed TLS, Vault and S3 are not provisioned by the repo. - Local tests validate crypto and provider contracts, but do not prove a real tenant's claim mapping, token lifecycle, network policy or key rotation. - The Control Plane is production-capable for this packaged deployment model; it is not yet a universal multi-runtime scheduler or supervisor.