Configure versioned master keys
Version 1 continues to usePROVIDER_KEY_ENCRYPTION_KEY. Before each later rotation, deploy the next secret to every application and worker instance using the versioned name:
Initialize the external erasure ledger
The follow-up source supports an independently operated PostgreSQL ledger as well as the existing mounted-file backend. Hosted enablement still requires durable placement, operator bootstrap and deployment/recovery acceptance; source support does not establish that production is configured.PostgreSQL backend (candidate)
Provision a separate database and backup lifecycle using the operator DDL exported asPROVIDER_CREDENTIAL_ERASURE_POSTGRES_DDL in
src/lib/security/provider-credential-erasure-postgres.ts. This DDL is excluded
from application migrations. Retain the original independently generated UUID
as the ledger identity:
PROVIDER_CREDENTIAL_ERASURE_LEDGER_PATH for this backend. Production
remote connections require certificate and hostname verification; weak TLS
modes and conflicting connection options are rejected. The application database
cannot be used as its own external ledger. The external declaration and a
different URL alone do not prove independent storage or backups.
The operator provisions and bootstraps the ledger; the application ledger login
needs only SELECT and column-scoped UPDATE(document), without insertion,
deletion, truncation or schema administration. The database guard requires one
append and an unchanged history/identity; the shared codec verifies every
signature and chain head. The pinned UUID prevents accepting a replacement
signed genesis as the original ledger.
Use the existing erasure-ledger-init command below in a separately authorized
maintenance window. It obtains non-waiting shared locks over both application
credential-history tables while checking the first-boot preconditions. Active
writers cause refusal. Recheck the actual credential/history state while
writers remain fenced; never use a new empty ledger to replace lost history.
After bootstrap, deploy only the restricted ledger credential to applications
and restore workers. Keep bootstrap/migration credentials outside their runtime.
Mounted-file backend
Crypto-erasure evidence must survive a database restore. Configure a durable ledger path whose storage lifecycle is independent from application releases and database backups, plus an independent HMAC signing key:EXTERNAL=1 attestation. Every application replica and restore worker must see the same durable file with atomic create and rename semantics. Keep the signing key outside the database-backup lifecycle.
Provision and sign the empty ledger before the first application startup. This explicit command is the only path allowed to create the ledger and its separate signed .genesis identity marker. It refuses to bootstrap once any provider credential or encryption-key history exists. Repeating it against an intact empty ledger verifies the existing identity and never replaces it.
fsync support.
Inspect the current safe registry metadata before an operation. This output never includes wrapped keys, ciphertext, or fingerprints:
Rotate the active version
After the next versioned environment variable is available everywhere, rotate atomically:decrypt_only and creates exactly one new active version. Credential writes and rotations serialize on the organization, and the database rejects encryption under an inactive version. Reads of permitted historical credentials continue to work.
Re-encrypt historical credentials
Create a durable re-encryption run from adecrypt_only version to the active version:
Revoke or erase a historical version
Revocation immediately rejects application reads but preserves wrapped key material for a later, separately approved erasure:decrypt_only or revoked versions can be erased. A migrated legacy-derived version with remaining ciphertext must first be fully re-encrypted; this prevents presenting a status change as cryptographic destruction when the old key remains derivable.
The erase command first appends and fsyncs a signed, hash-chained external tombstone and only then clears database key material. If the process stops between those operations, credential access fails with PROVIDER_CREDENTIAL_ERASURE_REPLAY_REQUIRED. Replay is idempotent and clears material reintroduced by a pre-erasure database restore:
Restore procedure
Mount the original external ledger and signing key before starting any process against a restored database. Runerasure-replay explicitly as a restore gate, or let the application startup gate perform it, and require a successful result before enabling traffic. Verify that:
- every applicable tombstone has an
appliedreplay receipt; - the corresponding registry row is
erasedwith no key reference, fingerprint, or wrapped-key fields; - an unaffected organization’s credential remains readable; and
- a second replay reports zero newly applied entries.
Failure and audit behavior
Unknown, revoked, erased, missing-material, fingerprint-mismatch, and malformed-ciphertext failures use deterministic error codes. Rotation, each re-encryption batch, revocation, and erasure write append-only audit evidence containing identifiers, versions, counts, and safe error codes only. Ciphertext, wrapped data keys, master secrets, and provider secret values are never written to those events. Before removing a historical deployment secret, confirm that its re-encryption run is complete or that the version has been cryptographically erased in the live database. A backup taken before erasure can still contain the wrapped data key. Retain the external signed ledger for at least as long as any database backup can be restored, apply your backup-retention controls, and never make a backup-wide or regulated permanent-erasure claim until restore replay is part of the tested recovery procedure.Connections candidate save behavior
The unreleased Connections candidate saves direct keys withverifyAccess: false through the canonical provider-key API. This stores an encrypted credential without an upstream request; keyCheckStatus reports not_checked. Existing API callers that omit the option retain the metadata access probe. Format validation accepts OpenAI project and service-account keys as well as older key shapes. Neither format validation nor persistence proves account access.
Replacement remains owner-only and returns a new canonical key ID. The Connections view follows that ID; replaced records remain available as historical metadata and cannot be re-enabled. Current account and deployed-runtime verification remains separate from local tests.