62 lines
3.0 KiB
Markdown
62 lines
3.0 KiB
Markdown
---
|
|
topic: the tiers
|
|
status: accepted
|
|
date: 2026-09-21
|
|
deciders: jochen
|
|
reconstructed: false
|
|
extends: 02-DECISIONS/0085-a-secret-is-a-provision.md
|
|
---
|
|
|
|
# 92. An operator delivers a pair credential, and the mesh never replaces it
|
|
|
|
## Context
|
|
|
|
[ADR 0085](0085-a-secret-is-a-provision.md) names three species of secret and gives the vault
|
|
two of them: 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. Under 0085 a secret
|
|
from the vault is a pair credential between the consumer and the vault. The controller's one
|
|
command that takes a value from a person wrote only a module's own secret, sealed to one node.
|
|
Nothing could put a value into a pair, so the third species had no entry
|
|
([issue 070](../04-ISSUES/070-an-operator-cannot-deliver-a-pair-credential/00-report.md)), and
|
|
an operator's credential could be held only as an own secret — un-audited, un-rotatable, the
|
|
gap 0085 opened to close.
|
|
|
|
## Considered Options
|
|
|
|
1. **A new verb on the pair.** Rejected: `secret accept` already means "a value a person
|
|
supplied, sealed on the way in, plaintext discarded"; a second verb would mean the same.
|
|
2. **`secret accept` grows a provider end.** Adopted.
|
|
|
|
## Decision
|
|
|
|
`secret accept <node> <module> <name> --provider <node>` seals the supplied value to the
|
|
consumer's node, to the provider's node, and to the operator's key when the mesh has one, and
|
|
records the pair as `accepted`. Every pair credential now says where it came from: `made` or
|
|
`accepted`.
|
|
|
|
An accepted pair is never replaced by a made one. When a sealing key at either end changes, the
|
|
mesh cannot re-seal a value it does not hold, so the read is refused and names the remedy —
|
|
accept it again. `rotate` refuses an accepted pair for the same reason: the mesh cannot make its
|
|
replacement, and deleting it would have the next read mint one, delivered and reported as
|
|
applied while failing to authenticate somewhere else entirely. Rotating an accepted credential
|
|
is accepting a new value.
|
|
|
|
## Consequences
|
|
|
|
A credential for something outside the mesh lives in the vault's ledger with the others, sealed
|
|
to both ends and recoverable by the operator. What got harder: a mesh whose node keys change
|
|
cannot heal an accepted pair by itself; a person is asked. That is the honest shape — the value
|
|
was never the mesh's to make.
|
|
|
|
## How it is checked
|
|
|
|
An inventory test accepts a value into a pair, reads it back twice unchanged with origin
|
|
`accepted`, asserts `rotate` refuses it naming the remedy while a made pair still rotates;
|
|
another changes a node's key and asserts the read is refused, then accepts again and reads.
|
|
|
|
## References
|
|
|
|
- [issue 070](../04-ISSUES/070-an-operator-cannot-deliver-a-pair-credential/00-report.md), [issue 069](../04-ISSUES/069-one-secret-provision-yields-one-value/00-report.md)
|
|
- [ADR 0085](0085-a-secret-is-a-provision.md)
|
|
- [`03-DESIGN/01-to-be/24-the-secrets-vault.md`](../03-DESIGN/01-to-be/24-the-secrets-vault.md)
|