Amend ADR 0085: the vault is a foundation module and holds the root secrets
Recorded on the record, dated, before anything shipped against the sentences that change. The vault is installed at genesis like the store and broker, one per mesh, and holds every secret a module has for itself sealed a second time to an operator key whose private half never enters the mesh — the break-glass path the first version left open, without a key one place holds. Design 24 says how; 07 and 21 say what genesis does not yet do; issue 071 names the fixed credentials the foundation is raised with today.
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
topic: what runs on it
|
||||
status: accepted
|
||||
date: 2026-09-20
|
||||
amended: 2026-09-20
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 02-DECISIONS/0031-the-control-plane-authenticates-nobody.md
|
||||
@@ -93,6 +94,51 @@ the vault offers recovery without it is left to the design as an open question.
|
||||
today bakes a password into its own composition must instead require it from the vault — a
|
||||
migration taken module by module, not a flag day.
|
||||
|
||||
## Amendment — 2026-09-20, before anything shipped
|
||||
|
||||
Recorded on the record itself rather than as a supersession, by its decider, on the day it was
|
||||
accepted and before any code was merged against the sentences that change. The original text above
|
||||
is left as written; this section says what it got wrong and what stands instead.
|
||||
|
||||
**What it got wrong.** The decision treated the vault as a provider like the store — optional, and
|
||||
one per node — and left the mesh's own root secrets outside it: the store's superuser, the broker's
|
||||
administrator, the controller's contexts, sealed to a node key and nothing else. Those are the
|
||||
secrets with no rotation and no recovery, and they are the ones a vault exists for. At genesis they
|
||||
are not even secret: the foundation raises its store and broker with fixed, well-known credentials
|
||||
and carries those into the mesh. Leaving that floor in place gave module secrets an owner and the
|
||||
root secrets none.
|
||||
|
||||
**What stands instead.**
|
||||
|
||||
- **The vault is a foundation module.** It is installed at genesis as part of the foundation
|
||||
([ADR 0078](0078-the-store-and-broker-are-modules.md) is the precedent: a foundation piece is
|
||||
still an ordinary module), not assigned later by a mesh that happens to want one. *"A mesh that
|
||||
wants no vault runs none"* is withdrawn. A mesh has root secrets, so a mesh has a vault.
|
||||
- **One per mesh, on the control-node.** *"The vault is node-scoped like every provider"* is
|
||||
withdrawn. Node scoping ([ADR 0084](0084-which-provider-serves-a-consumer.md)) exists because a
|
||||
store holds data a consumer is coupled to; the vault holds nothing a consumer is coupled to, and a
|
||||
second one would be a second place to lose. Consumers on other nodes reach it as they reach
|
||||
identity.
|
||||
- **The vault holds the mesh's root secrets under an operator-held key.** The controller mints and
|
||||
delivers exactly as before; in addition, every secret a module holds for itself is sealed a second
|
||||
time, to an **operator sealing key** whose private half never enters the mesh. The vault keeps
|
||||
those operator-sealed copies on its own disk, outside the store, and can hand them out — they are
|
||||
ciphertext to everything but the operator. This is the break-glass path the original text left
|
||||
open, and it does **not** reintroduce a key one place holds: the mesh holds blobs it cannot open,
|
||||
and the operator holds a key with nothing to open until given a blob. Recovery needs both.
|
||||
- **Genesis mints real root secrets and seals them to the operator key first**, so the fixed
|
||||
credentials the foundation is raised with are replaced before the mesh is handed over.
|
||||
|
||||
**Unchanged.** A module's own secret is a `secret` provision the controller mints and the vault
|
||||
records; the provisioned-pair path of [ADR 0048](0048-a-provider-creates-the-credential-the-mesh-minted.md)
|
||||
is untouched; the vault stores no plaintext, ever.
|
||||
|
||||
**What it costs.** An operator key is a thing a person must keep, and a mesh whose operator key is
|
||||
lost has root secrets that can be rotated but not recovered — the same standing as today, stated.
|
||||
Sealing every own secret twice is a column and a call. Genesis grows a step. A module's
|
||||
vault-provided secret (a pair credential) is not yet sealed to the operator key; that is the next
|
||||
increment, not this one.
|
||||
|
||||
## References
|
||||
|
||||
- [ADR 0031](0031-the-control-plane-authenticates-nobody.md) — identity is a module; this is the
|
||||
|
||||
Reference in New Issue
Block a user