security
    New
    2026-04-13

    Authentication & Security

    OIDC/PKCE authentication, SCIM 2.0 provisioning, RBAC roles, IP allowlists, Fernet encryption, key rotation, and cryptographic audit chain.

    oidc
    pkce
    scim
    rbac
    ip-allowlist
    encryption
    audit

    OIDC / OAuth 2.0 PKCE

    No passwords are stored in the platform database. Authentication uses OpenID Connect with PKCE. The backend validates the RS256 JWT against the IdP's JWKS endpoint — the JWKS is cached per-issuer with configurable TTL. Multiple IdPs (Okta, Azure AD, Auth0, Ping) can be registered via POST /api/v1/idp/configs and the login page automatically renders one SSO button per active config.

    Personal Access Tokens

    For CI/CD, scripts, and SDK usage. Tokens are stored as hashed values — the plaintext is only shown once at creation time.

    bash
    curl -X POST /api/v1/auth/tokens \
      -H "Authorization: Bearer $OIDC_JWT" \
      -d '{ "name": "CI pipeline", "expires_in_days": 90 }'
    # Returns { "token": "sk-sovereign-..." } — store immediately

    SCIM 2.0 Provisioning

    Automated user and group provisioning from your IdP's SCIM connector (RFC 7644). SCIM DELETE is a soft-delete — users are set to status=revoked to preserve audit log foreign key integrity.

    EndpointDescription
    `GET /api/scim/v2/Users`List users (filterable)
    `POST /api/scim/v2/Users`Provision a new user
    `PUT /api/scim/v2/Users/{id}`Full replace
    `PATCH /api/scim/v2/Users/{id}`Partial update
    `DELETE /api/scim/v2/Users/{id}`Soft-delete (status → revoked)
    `GET /api/scim/v2/Groups`List workspaces as SCIM groups

    Role-Based Access Control

    Roles are embedded in JWT claims. Multiple roles per user are supported — passing multiple roles means "any of these roles is sufficient".

    RolePermissions
    `admin`All operations — user management, key rotation, IdP config
    `ops`Deploy models, approve HITL, manage clusters, configure IP allowlist
    `legal`Approve/reject GitOps manifests and HITL requests, view compliance reports
    `dev`Create/read models, run agents, view audit log

    IP Allowlist

    Per-workspace CIDR-based access control. Fail-closed: if enabled but empty, all requests are blocked. Health, SCIM, and API docs paths bypass the allowlist. Set TRUST_PROXY=true to derive real IP from X-Forwarded-For behind a load balancer.

    bash
    1# Enable policy
    2curl -X PUT /api/v1/workspaces/{id}/ip-policy -d '{ "enabled": true }'
    3
    4# Add CIDR
    5curl -X POST /api/v1/workspaces/{id}/ip-allowlist \
    6  -d '{ "cidr": "10.0.0.0/8", "description": "Corporate VPN" }'

    Encryption & Key Rotation

    Sensitive configuration values (API keys, tool auth configs) are encrypted using Fernet (AES-128-CBC + HMAC-SHA256). The key is resolved at runtime from env, vault, aws_kms, or azure_keyvault. Key rotation: set SECRET_ENCRYPTION_KEY_PREV to the old key, call POST /api/v1/admin/rotate-keys to invalidate the in-process cache, run the re-encryption migration, then remove the _PREV variable.

    Cryptographic Audit Chain

    Every state-changing operation writes an AuditEntry with SHA-256 hash chaining. Each entry records previous_hash, creating a tamper-evident chain. The audit log has no DELETE or UPDATE endpoint — PostgreSQL row-level security additionally prevents the application role from deleting audit rows.

    bash
    curl -X POST /api/v1/audit/verify/{entry_id} \
      -H "Authorization: Bearer $TOKEN"
    # Returns { "valid": true, "chain_length": 847, "genesis_reached": true }
    Edit this page on GitHub