Design 24 flips to in-progress with mesh-catalog as its owner (playbook 04). Starting the build surfaced two gaps the decision did not settle: a module requiring `secret` receives exactly one value (069), and no command can accept an operator's value into a consumer↔vault pair (070). Both opened as issues rather than improvised around. Also fills fixed-by on 067 and 068, which the cycle check refused as resolved with no reference.
2.9 KiB
status, opened, located-in, fixed-by, amended-design
| status | opened | located-in | fixed-by | amended-design | |
|---|---|---|---|---|---|
| open | 2026-09-20 |
|
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/accepteddistinction is only recorded for own secrets. A pair credential has no origin column, so even once a value can be accepted into a pair,rotatewould mint over it — generating "32 random bytes where a working credential was", the exact faultsecret acceptwas 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
asthe 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 doesrotatebecome "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?