Skip to main content
EvalGate’s model-backed workflows use bring your own provider key (BYOK). EvalGate encrypts each organization’s provider credentials with a versioned data-encryption key. The data key is wrapped by a deployment master key, and every credential row records the exact encryption-key version required to read it. Provider credential replacement versions remain separate from these encryption-key versions. This guide applies to self-hosted operators with database migration and runtime-secret access. Run these commands from the same release and environment as the application.

Configure versioned master keys

Version 1 continues to use PROVIDER_KEY_ENCRYPTION_KEY. Before each later rotation, deploy the next secret to every application and worker instance using the versioned name:
Use independent random values of at least 32 characters. Do not replace or remove a historical environment value while credentials still depend on that version. EvalGate resolves the persisted version directly and never guesses through a “current/previous” key list.

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 as PROVIDER_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:
Unset 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:
The path must be absolute. Production rejects a path inside the application workspace and requires the 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.
A missing genesis marker, missing ledger, identity mismatch, truncation, modification, incorrect signature, or unreadable ledger fails closed. In production the application startup gate stops before traffic is served; provider credential reads and writes also reject the unavailable ledger. Never rerun initialization to replace lost or unmounted storage—restore the original ledger and genesis marker instead. The production file backend requires successful file and directory sync and is rejected on Windows, where durable directory sync cannot be established. Windows remains suitable for development and functional tests, but production erasure durability must be proved on a Linux storage adapter with durable atomic rename and directory 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:
Rotation changes the previous version to 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 a decrypt_only version to the active version:
The command returns a run ID. Process one bounded batch at a time; rerun the same command after an interruption:
Each committed batch advances a persisted cursor and audit record. Active-key rotation, revocation, and erasure are blocked while a run is active, so the target cannot change between resumed batches.

Revoke or erase a historical version

Revocation immediately rejects application reads but preserves wrapped key material for a later, separately approved erasure:
Crypto-erasure is final. It deletes the wrapped data key while retaining provider, credential name, encryption version, timestamps, and audit evidence. Supply the exact confirmation value shown below:
Only 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:
Normal production startup performs the same replay before serving traffic. A receipt and safe audit event are committed for each applied tombstone. Tombstones for versions absent from an older backup remain reserved, so a later rotation never reuses an erased version number.

Restore procedure

Mount the original external ledger and signing key before starting any process against a restored database. Run erasure-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 applied replay receipt;
  • the corresponding registry row is erased with no key reference, fingerprint, or wrapped-key fields;
  • an unaffected organization’s credential remains readable; and
  • a second replay reports zero newly applied entries.
If the ledger or signing key is unavailable, do not bypass the gate or initialize a replacement. Restore the original external evidence first.

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 with verifyAccess: 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.