4.5 KiB
ADR-0052: Managed personal keys and recovery admission
Status: accepted design for P01; implementation qualification in progress.
Decision
The bounded personal-header-key provider is the supported RC interactive provider. Preserve
ADR-0049 deployment keys and the bootstrap administrator unchanged. Add administrator-managed
identities under managed:<slug> with a distinct mfopm_ plus 43 URL-safe-character credential
namespace. Existing deployment subjects cannot contain :; authentication of deployment keys
does not require a managed-identity database lookup. A managed key never falls back to deployment
or machine privileges. The existing header, role boundaries and memory-only Console remain.
This decision does not claim OIDC, SSO logout, cookie sessions or enterprise IAM.
Store only the SHA-256 digest of a random 256-bit key, never plaintext or recoverable ciphertext. No encryption root key or additional dependency is needed. Issue plaintext exactly once after commit. A lost response requires a new rotation. Bound expiry to 1–365 days, rotation overlap to 0–900 seconds, identities to 100, and displayed credential history to the latest ten records. History remains authoritative; retired keys cannot be restored by another rotation. Metadata exposes role, source, expiry, version, last use, activation and usability, never digests. Mutation reasons cannot contain ModelForge credential namespaces and validation errors omit rejected inputs.
Keep deployment identities read-only. Production startup still requires a secure deployment administrator/recovery anchor; this PR does not introduce managed-only bootstrap or automatic environment migration. First managed identity must be an administrator. A singleton transaction lock serializes every managed mutation; expected registry/identity versions reject stale requests. Under that lock recheck the initiating managed administrator's credential, role, activation and expiry. Once initialized, every successful transaction leaves an enabled administrator with an activated, unrevoked, unexpired key. Expiry can still cause future loss of managed administration; the deployment recovery anchor remains necessary. Audit and identity mutation commit atomically.
Recovery
managed_operator_state, managed_operator_identities and managed_operator_credentials are
AUTHORITATIVE. Migration 0027 introduces the exact initial singleton and empty identity/credential
tables. Older-schema restore permits only that exact empty introduction; same-schema restoration
preserves all authoritative metadata. Credential digests stay excluded from public fingerprints
under the established secret-column policy. Mechanical downgrade refuses existing identity history;
recover the verified pre-migration backup instead.
managed_operator_credential_activations is CURRENT_TRUTH admission state. Normal issue/rotation
adds an activation only for the new key. Authentication requires it in addition to authoritative
credential validity. Supported restore clears activations alongside other stale current truth;
the independent READY validation rejects any retained activation. This quarantines every restored
managed key, including keys revoked after the backup, without rewriting historical credentials
or permitting fingerprint drift. Interrupted restore targets remain isolated and must not serve.
After supported recovery, an external deployment administrator rotates an enabled managed
administrator or creates a new administrator to restore admission. The new key alone gains
activation; old keys remain quarantined even during requested overlap. Reconciliation never
rehydrates activations automatically. A raw pg_restore bypassing ModelForge reconciliation and
READY validation is not a supported recovery procedure and must not be attached to the serving API.
Evidence boundary
Pre-body managed authentication uses the existing bounded thread-pool/session pattern and returns a typed 503 on database failure. No cached successful credential can override revocation. Already-authorized ordinary requests may finish; managed administration additionally rechecks its initiator while holding the mutation lock. Tests must cover real PostgreSQL cross-admin races, rotation/revoke CAS, last-admin protection, migration downgrade/recovery, restored admission quarantine, source namespace separation, audit rollback, and Console one-time secret handling. Local SQLite tests are not PostgreSQL qualification. Exact-head managed and browser gates remain required before this ADR's implementation is marked verified.