64 lines
4.5 KiB
Markdown
64 lines
4.5 KiB
Markdown
# 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.
|