Files

3.1 KiB

status, opened, located-in, fixed-by, amended-design
status opened located-in fixed-by amended-design
resolved 2026-09-20
mesh-controller internal/inventory (secret)
mesh-controller cmd/mesh-controller (secret accept)
ADR 0092; mesh-controller feat/multiple-fixes (secret accept --provider; origin on the pair; remake and rotate refused) 03-DESIGN/01-to-be/24-the-secrets-vault.md

An operator cannot deliver a pair credential, so the vault's third species has no entry

Symptom, as observed

ADR 0085 names three species of secret and gives the vault two: a module's own secret, which the mesh mints, and an operator-delivered secret — a credential for something outside the mesh, which only a person can supply. The design (24) says the vault "takes custody of one an operator delivered".

Under 0085 a secret from the vault is a pair credential between the consumer and the vault. The controller has one command that takes a value from a person — secret accept — and it writes only a module's own secret: one node, one module, one name, sealed to that node's key alone. There is no command that accepts a value into a pair: sealed to the consumer's node and to the vault's node, recorded as accepted so a later push does not replace it with a minted one.

The primitive exists. The sealing package's Accept takes a value and two keys, and the licence adapters already use it to carry an operator's token to both ends of a licence. Nothing exposes it for an ordinary provision.

So today an operator-delivered secret can be held in only one of two wrong ways: as an own secret (un-audited, un-rotatable — the gap 0085 opened to close), or not at all.

Why it matters beyond this instance

  • The vault is one third short of its decision until this exists, and the third that is missing is the one with a real leak history — external keys are the secrets that end up in transcripts and env files.
  • The made/accepted distinction is only recorded for own secrets. A pair credential has no origin column, so even once a value can be accepted into a pair, rotate would mint over it — generating "32 random bytes where a working credential was", the exact fault secret accept was written to prevent for own secrets. Rotating an accepted pair credential must refuse, or must ask for the replacement value, and neither is designed.
  • The consumer's login is derived, and an external service did not derive it. An accepted external key has no as the far side knows; a pair credential assumes both ends agree on one. For the vault this is harmless (the vault creates nothing under that login), but the model leaks through in what the consumer is told.

Open questions

  • Is this secret accept <consumer-node> <module> secret --from … growing a provider end, or a new verb on the pair?
  • Does an accepted pair credential refuse rotate, or does rotate become "accept a new value and deliver it" for that pair?
  • Should the origin (made / accepted) become a fact of every pair credential, so the vault's ledger can show which of its secrets a person supplied?