Expand description
cratefield-secrets — the secrets store (issue #39,
docs/SECRETS-DESIGN.md, ADR 0102).
Envelope encryption over the Database port, in two tiers. Global
secrets (tenant connection strings, platform keys) live in the control
database; tenant secrets live in that tenant’s database and nowhere
else. Each store holds its own wrapped data key, which the KMS unwraps
and never stores (§3 of the design: a database dump is ciphertext plus
a blob nobody outside the KMS can open).
Every ciphertext is bound to its row by the AEAD’s additional data: store, name, version and key id, length-prefixed (§5). A row copied to another database, renamed, rolled back a version, or repointed at another key fails to decrypt rather than quietly succeeding.
What this crate deliberately does not do: rotation (#42) and the
append-only audit log (#41). Audit is the seam the latter fills;
until then every access is logged through tracing with no value in
it.
Re-exports§
pub use audit::Anchor;pub use audit::ChainAudit;pub use audit::chain_sink;pub use audit::verify;
Modules§
- audit
- The append-only, tamper-evident audit chain (issue #41).
Structs§
- Actor
- Who is asking. Every method takes one because the audit log needs one and there is no anonymous access to a secret.
- Audit
Event - What the audit log records. No value, ever.
- Harness
Only - Proof the caller is the harness itself and not a module. Only the
harness can construct one, so
Secrets::globalis unreachable from module code however public it looks: a module has no way to make the argument. - Rewrap
Report - What a re-wrap did, or would do.
- Rotation
Report - What a rotation did, or would do with
plan. - Secret
Bytes - A secret’s bytes. Zeroised on drop, prints as
[redacted], and implements neitherDisplay,SerializenorClone: a secret that can be formatted, serialised or copied is a secret that ends up in a log line, a JSON body, or a buffer nobody cleared. - Secret
Meta - What
listreturns: names and versions, never values. - Secret
Store - One store: one database, one
StoreId, one data key. - Secrets
- Owns the KMS and the audit sink; hands out per-store handles.
- Tracing
Audit - The default audit sink until #41 lands: one structured
tracingline per access, with no value in it.
Enums§
- Access
- One access, as the audit log will store it.
- Secrets
Error - StoreId
- Which store a secret belongs to. Part of the AAD, so it is also what stops a row being useful anywhere else.
Constants§
- CIPHER
- The AEAD this crate seals with, recorded on every key row so a store can never mix ciphers within one key id (design §4).
- POSTGRES_
MIGRATIONS - SQLITE_
MIGRATIONS - The store’s schema, per dialect, applied the same way a module’s is.
The tables are portable; only the append-only trigger differs, which
is what
Migrations’ two sets are for (ADR 0004).
Traits§
- Audit
- Where the append-only audit log (#41) attaches. Every store method calls this before returning, on success and on failure, so a refused read is recorded as loudly as a successful one.
Functions§
- aad
- The additional authenticated data every ciphertext is sealed with
(
docs/SECRETS-DESIGN.md§5): a domain-separation prefix, then each field with an explicit little-endian length prefix so the encoding is injective and no two distinct contexts can share an AAD. - migrations
- The store’s schema, per dialect, applied the same way a module’s is
(see
SQLITE_MIGRATIONSfor why the sets are public).
Type Aliases§
- Version
- A secret’s version. Monotonic per name, starting at 1.