5.6 KiB
status, opened, located-in, fixed-by, amended-design
| status | opened | located-in | fixed-by | amended-design | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| resolved | 2026-10-01 |
|
mesh-controller PR 183 (`secret rotate`, the `taken` word on an own secret, `rotate` on the controller's seat with two shapes); the staged form for an applied secret stays open below |
|
180 — A module's own secret cannot be rotated, and nothing rotates from the console
What was observed
Filed first in the forge's tracker on this repository (its issue 231, 2026-09-30), after a module's
API token was printed by accident on the home server and the only way to change it was to generate
a value by hand and secret accept it. The report said there was no rotation at all. That was half
right: rotate <provision> has existed for a pair credential since design 13, pushing both ends
together; what did not exist was any rotation of a module's own secret — a token, an application
secret, an administrator — and any way to ask for either through the console
(ADR 0152).
Why this is here
ADR 0114 decided how a single party's credential rotates: in place, in one of two forms. Read at start — the vault delivers the new value as current and the party is started again. Applied — the party's own code applies the value to a backend that takes it once, so the new value must be staged beside the current one until the party confirms it. Neither form was built, and nothing said which form a given secret needed. That last gap is the dangerous one: issue 179 is what a value looks like when the mesh believes it was taken and the software never read it. A rotation that made that happen on purpose would be worse than no rotation.
Resolved, 2026-10-01 — the read-at-start form, and the verb
An own secret says how it is taken. In a definition, "own-secrets": {"api-token": {"path": …, "taken": "at-start"}} says the module reads the file when it starts; "taken": "applied" says its
own code applies the value to a backend; a path alone says neither. A definition that says neither
is not rotated by the mesh, and the refusal names the word to write.
secret rotate <node> <module> <name> makes the secret anew the way the first mint did, seals it
to the machine and to the operator, and sends the machine, so the module starts again on the new
value, under the same restart-on that any changed file triggers. Said in the log with who asked and
when, never the value. An applied secret is refused by name, until the staged form exists. A value
given to the mesh rather than made by it is refused as ADR 0113
says, with the way out: change it where it lives, then accept the new value.
rotate is a verb on the controller's seat (ADR 0154),
with the two shapes the mesh has: a pair credential by provision and consuming machine, or an own
secret by machine, module and name. The console can ask for either.
Nothing in the catalogue says taken yet: the word ships one release ahead of its first use, and the
first definitions to say it follow once this controller runs.
How it is checked: the manifest form and its refusals; the rotation against a raised store — rotates a secret taken at start, refuses an applied one, an undeclared one, an accepted one and an unknown name, each in its own words; the verb's two shapes; and, live, a secret rotated through the console on a module that reads it at start, the module restarted, and the module working.
Done live, 2026-10-01 10:13 UTC: the search module on the home server, the first definition to say
taken: at-start whose value the mesh had made. Asked through the console; the controller said it was
rotated and sent the machine; twenty-seven seconds later the secret file carried a new write time, the
server container had restarted on it, and the module answered. The two secrets filed in the forge's
report, the automation module's token and admin password, were refused: both had been accepted by hand
during adoption, and that refusal is the one ADR 0113 asks for — something outside the mesh may hold
an accepted value, so replacing it is a person's act. Modules whose source is pinned to a commit are
not rebuilt by a merge; their new definition was registered by asking for a build of main through the
console, which since issue 176
registers what it hears.
Open — the applied form
The staged rotation ADR 0114 decided for an applied secret is not built: the vault delivering the new value beside the current one, the module's own code switching the backend and confirming, and only then the new value current. It needs a word in the module's protocol for confirm, and it is the form the identity provider's administrator and every database's superuser need. The request's second half — re-issuing a pair credential through the provider's own code rather than by re-minting and pushing — is the same shape from the provider's side, and sits with it.