Encryption key lifecycle status
Included from Basic tier
The payloads of the v2 SystemService encryption key lifecycle verbs
(admin-gated; opschain admin encryption status / reencrypt):
GetEncryptionStatus — the census: the configured key ring, the key
registry (EncryptionKeyRecord), one EncryptedColumnStatus per
encrypted-at-rest column with its EncryptionKeyCount rows, what is
pending, the referenced keys this server lacks, and the last
EncryptionReencryptRun.
ReencryptAtRest — the re-encryption run, answering its
EncryptionReencryptRun with one EncryptedColumnOutcome per column
touched.
A key id, wherever it appears below, is the leading 64 bits of SHA-256
over the derived AES key (16 hex characters): it names the (primary key,
salt) pair without revealing either. No payload here ever carries a key or
a decrypted value — counts and ids only.
The v2 OpenAPI document declares these schemas; the resource-field coverage
gate holds this page to them.
Status payload (GetEncryptionStatus)
| Field | Type | Meaning |
|---|
backend | string | postgres or sqlite. |
current_key_id | string | The key every write seals under (OPSCHAIN_PRIMARY_KEY + OPSCHAIN_KEY_DERIVATION_SALT). |
configured_key_ids | array | The ring this server holds: the current key first, then OPSCHAIN_PREVIOUS_KEYS in order. |
keys | array | The key registry, EncryptionKeyRecord entries below, oldest first. |
columns | array | One EncryptedColumnStatus per encrypted-at-rest column, in inventory order. |
pending | int | Envelopes not sealed under the current key (legacy envelopes included) — what a re-encryption run would rewrite. |
missing_key_ids | array | Key ids referenced by stored envelopes, or registered and not retired, that this server's ring lacks. The CLI exits 1 while any exist; re-encryption refuses. |
last_run | object | The most recent EncryptionReencryptRun. Absent when no run has happened. |
keys entries (EncryptionKeyRecord)
| Field | Type | Meaning |
|---|
key_id | string | The key id. |
first_seen_at | timestamp | When a server first registered the key as its current key against this database. |
last_seen_at | timestamp | The last boot that registered it as current. |
retired_at | timestamp | When a re-encryption run verified nothing references the key any more. Absent while the key is active; a key re-introduced as current is un-retired. |
retired_by | string | The id of the re-encryption run that retired it ("" while active). |
current | bool | True for this server's current key. |
configured | bool | True when this server's ring carries the key (current or previous). |
columns entries (EncryptedColumnStatus)
| Field | Type | Meaning |
|---|
table | string | The table. |
column | string | The column. |
envelopes | int | Encryption envelopes in the column; plaintext rows are not counted. |
current | int | Envelopes sealed under the current key. |
legacy | int | Envelopes with no key reference — written before key references existed, or by the Rails application; decrypted by trying each configured key. |
pending | int | Envelopes a re-encryption run would rewrite (everything not under the current key). |
by_key | array | Counts per referenced key id, EncryptionKeyCount entries below. |
by_key entries (EncryptionKeyCount)
| Field | Type | Meaning |
|---|
key_id | string | The referenced key id. |
envelopes | int | Envelopes referencing it in this column. |
configured | bool | False when this server's ring lacks the key — the column cannot be re-encrypted until it is listed in OPSCHAIN_PREVIOUS_KEYS. |
Run payload (ReencryptAtRest, and last_run above — EncryptionReencryptRun)
| Field | Type | Meaning |
|---|
id | string | The run id (the progress row's key; cited by retired_by). |
target_key_id | string | The key the run seals everything under — the current key when it opened. |
status | string | running, partial, completed, completed_with_failures or failed — vocabulary below. |
started_at | timestamp | When the run opened. |
updated_at | timestamp | The last batch's commit (the progress row is updated after every batch). |
finished_at | timestamp | When a full pass completed. Absent while partial, failed or running. |
converted | int | Envelopes rewritten under the target key, across every invocation of the run. |
failed | int | Envelopes the latest pass could not decrypt under any configured key — the rows still pending, not a running sum. |
skipped | int | Rows that changed under the run between read and write and were left for the next pass. |
resumed | int | How many invocations resumed the run after a partial or failed stop. |
columns | array | One EncryptedColumnOutcome per column the run touched, below. |
retired_key_ids | array | The keys the run retired on its clean completion ([] otherwise). |
error | string | The statement error that stopped a failed run. Absent otherwise. |
columns entries (EncryptedColumnOutcome)
| Field | Type | Meaning |
|---|
table | string | The table. |
column | string | The column. |
converted | int | Envelopes rewritten in this column. |
failed | int | Envelopes in this column the latest pass could not decrypt. |
skipped | int | Rows in this column that changed under the run. |
Vocabularies (verbatim)
- Run statuses:
running (a batch loop holds it), partial (a row
limit stopped it; the next call resumes), completed (a full pass found
nothing left; superseded keys retired), completed_with_failures
(failed rows remain; no key is retired), failed (a statement error;
the next call resumes).
- Events: every
ReencryptAtRest call records api:encryption:reencrypt
with the run id, target key id, status, counts and retired key ids.
- Refusals (
failed_precondition, named): no encryption keys configured;
an envelope references a key this server lacks (<table>.<column> holds N envelope(s) under key <id>); a run is already in progress elsewhere
in the estate.
What changes this
OPSCHAIN_PRIMARY_KEY / OPSCHAIN_KEY_DERIVATION_SALT set the current
key; OPSCHAIN_PREVIOUS_KEYS adds the rotated-out keys the server still
decrypts; every boot registers the current key and refuses when a
registered, unretired key is missing from the ring (opschain docs storage, "Key references and rotation").
Related pages
opschain docs cli/admin-encryption — the verbs.
opschain docs storage — the keyset and the boot gate.