What one Encryptor.Ecto.KeyStore.shred/3 destroyed, and when it took
effect.
A shred is irreversible, and encryptor's enc-ADR-0005 asks the operator
to record what was destroyed in the change record (P3 step 1: "Record the
count and the version numbers"). This struct is that record, returned by
the call that performed the delete, so a host certifies from what the store
actually removed rather than from what it asked for (ADR-0007 decision 4).
| Field | |
|---|---|
:vault | the vault whose key store was shredded |
:procedure | :scope for enc-ADR-0005's P3 (every version) or :version for its P4 (one version) |
:scope_ref | Encryptor.Envelope.scope_ref/2 of the selector: the value in the table's tenant_ref column. Never the selector itself |
:versions | the versions whose rows were deleted, ascending. Under P3 this includes a version provisioned while the shred ran, when its re-check found one |
:remaining | the versions still live for the scope after the delete, ascending. [] after P3, which is what P3's re-check found; after P4, the versions the shred read under its lock, less the one it deleted |
:table, :prefix | where the rows were deleted from, as the key store is configured |
:deleted_at | when the delete committed, UTC |
:drained_at | when every vault serving the scope has stopped decrypting under a deleted version from a cache entry made before the delete committed: :deleted_at plus the vault's cache max_age, or :deleted_at for a vault with cache: false. Not a hard bound: Encryptor.Ecto.KeyStore.shred/3 says which entry can outlive it |
:drain | :waited when the call returned at or after :drained_at, :skipped when the caller asked it not to wait |
:drained_at is the moment enc-ADR-0005's P3 step 3 and P4 step 2 are
complete for a host that waits rather than restarts, and it holds for every
node only when every node runs the vault with the same max_age, which is
what one vault module's configuration gives. A host that restarts its vaults
instead completes the drain at the restart, and a record with
drain: :skipped says the call did not wait for it.
The selector is deliberately not a field. A shred record is written into a change log that outlives the scope, and the scope reference is the value the key store keys the scope's rows by without publishing the host's identifier beside them.
Summary
Types
@type procedure() :: :scope | :version
Which of enc-ADR-0005's two destroying procedures ran.
@type t() :: %Encryptor.Ecto.KeyStore.Shred{ deleted_at: DateTime.t(), drain: :waited | :skipped, drained_at: DateTime.t(), prefix: String.t() | nil, procedure: procedure(), remaining: [pos_integer()], scope_ref: String.t(), table: String.t(), vault: module(), versions: [pos_integer(), ...] }