Merge pull request 'ADR 0277: a trusted setting is proposed through a verb and set on the operator's warrant, and a module's own secret is asked for and typed at the desk' (#278) from decisions/0277-a-trusted-setting-is-proposed-and-set-on-the-operators-warrant into main

This commit was merged in pull request #278.
This commit is contained in:
2026-10-10 12:50:19 +00:00
9 changed files with 328 additions and 10 deletions
+7 -1
View File
@@ -279,7 +279,9 @@ and the operator act. **Recorded by** the controller's `identity` and `licences`
- **proof** — what an authorising answer carries: a verified sender, a one-time code, a security key's
touch (ADR 0234). How much proof a kind of ask needs is its **assurance level**.
- **controller's terminal** — a command line the controller runs as typed by its operator, not asked through a
verb, so a change that is the terminal's alone is taken (issue 339, issue 340). In the controller's code it is a
verb, so a change that is the terminal's alone is taken (issue 339, issue 340) — or, since
[ADR 0277](../02-DECISIONS/0277-a-trusted-setting-is-proposed-through-a-verb-and-set-on-the-operators-warrant-and-a-modules-own-secret-is-asked-for-and-typed-at-the-desk.md),
proposed through a verb and set on the operator's warrant. In the controller's code it is a
line run without `MESH_VERB`. The operator reaches it with `mesh-cli` from their own account on a node where no
agent can run as that account: the control-node, and a node whose agents run under an account of their own
([ADR 0272](../02-DECISIONS/0272-the-operator-reaches-the-controller-with-mesh-cli-on-every-node-and-a-node-is-the-terminal-only-where-no-agent-runs-as-its-operator.md)).
@@ -501,6 +503,10 @@ asking, never the act. **Decided by** ADR 0152, 0175, 0234, 0259, 0272.
- **warrant** — the router's record that a person chose one option of one ask: the ask, the option,
who chose (the operator, as a channel kind's identity), through which channel, the proofs and when,
published for that asker alone. The only thing an asker acts on (ADR 0259).
- **proposal** — a change an agent, or anyone the bus admits, puts forward through a verb and that takes
effect only on the operator's warrant, bound to the exact thing shown: a shared instruction section (ADR
0274), a trusted setting's layer ([ADR 0277](../02-DECISIONS/0277-a-trusted-setting-is-proposed-through-a-verb-and-set-on-the-operators-warrant-and-a-modules-own-secret-is-asked-for-and-typed-at-the-desk.md)).
A proposal changes nothing by itself; declined, expired or refused, it is discarded.
- **operator message / input** — what arrives on `intake`, once the router has checked the sender
against its own list of the operator's identities: a **trusted** one is an operator message,
addressed to an agent by `@name` or thread or else to the **responder** (`@mesh`, the router's own
@@ -508,6 +508,13 @@ with the router not knowing its own machine, it approved. Now:
machine's launcher, carried by that machine's runtime, may answer its prompt; for any other module's
secret that remains the accepted risk of a desk where agents run as the operator.
> **The mechanism changed — 2026-10-10, by [ADR 0277](0277-a-trusted-setting-is-proposed-through-a-verb-and-set-on-the-operators-warrant-and-a-modules-own-secret-is-asked-for-and-typed-at-the-desk.md).** The same prompt is opened by the
> controller's `secret-ask` verb from anywhere on the mesh, with the desk the module's machine unless named,
> and `give` composes its line. It is bounded (one open ask per secret, three an hour, read from the store
> before the prompt opens) and the prompt names who asked, from the bus's word on the caller alone. What
> stands: the value is typed at the desk, sealed to the one call, never in an argument, a log or an event;
> a trusted party's secret is still the terminal's.
**Where an ask can be answered is said by the router**, from the channels that qualify: "Answer on
Telegram, or from the mesh MCP server." The asker's words never name a channel.
@@ -262,6 +262,11 @@ here:
which seals to the machine that uses the secret, never to a key the caller chooses. **The `token` verb is
refused too**, because it handed the joining token to its caller. Enrolling a machine is now done at the
controller's terminal, by the operator;
> **The mechanism changed — 2026-10-10, by [ADR 0277](0277-a-trusted-setting-is-proposed-through-a-verb-and-set-on-the-operators-warrant-and-a-modules-own-secret-is-asked-for-and-typed-at-the-desk.md).** Beside `secret rotate`, one other
> `secret` line is run through a verb: `secret ask <node> <module> <name> [--at <desk>]`, which carries no
> value and answers none — the operator types it at the desk's hidden prompt. And `settings proposals`
> joins the generic verb's reads; `settings propose` is the settings verb's. Everything else stands.
- `claude_code_add_api_key` read a caller's file as the operator, sealed it away and deleted it. It now takes
only a file under the agent's own home, reached through no symbolic link, read as the agent, at most 4 KiB,
holding an Anthropic API key. The licence manager refuses a key of another shape too;
@@ -0,0 +1,260 @@
---
topic: what runs on it
status: accepted
date: 2026-10-10
deciders: jochen
reconstructed: false
extends: 02-DECISIONS/0274-an-agent-proposes-a-shared-instruction-section-and-every-node-takes-it-only-on-the-operators-warrant-which-it-proves-itself.md
---
# 277. A trusted setting is proposed through a verb and set on the operator's warrant, and a module's own secret is asked for and typed at the desk
## Context
[Issue 339](../04-ISSUES/339-a-verb-can-place-a-directory-at-the-machines-own/00-report.md) found that any caller
of the controller's `settings` verb could have the node-engine hand a system directory to an account of the
caller's choice, and its fix made every **trusted setting** the controller's terminal's alone: `places` and
`accesses`, every key a provider serves, every setting a trusted file asks for, and the whole layer of a module
with a trusted mergeable file ([issue 340](../04-ISSUES/340-an-agent-can-plant-a-hook-in-every-agent-session-on-the-mesh/00-report.md)).
The controller refuses them through any verb: "set at the controller's terminal only … whoever may call a verb
includes agents". A module's own secret issued outside the mesh is given the same way: `secret accept` at the
terminal, or the desk prompt the `give` verb opens ([ADR 0259](0259-an-ask-is-a-message-on-the-bus-any-channel-answers-it-and-the-asker-acts-on-a-warrant.md)
§10, step 7).
That was right for the hole it closed and wrong for the operator's day. On 2026-10-10 the operator said: "you
should modify the settings yourself, I don't want to run manual commands on novox". The case at hand: the
`mounts` module's `sources` on the gaming machine's client, a trusted setting (a mount point on the machine,
asked for by a trusted file), and its `smb-credentials`, a secret issued outside the mesh. Each was a line the
agent could only hand the operator to type at the control node.
[ADR 0274](0274-an-agent-proposes-a-shared-instruction-section-and-every-node-takes-it-only-on-the-operators-warrant-which-it-proves-itself.md)
established the pattern that removes the terminal from the loop without giving the decision to an agent: an
agent **proposes**, the operator **approves** on a channel that proves who answered (Telegram, placed where no
agent can become root), and the act is performed on the **warrant** — the router's record of the choice, bound
to the exact thing shown. The controller already acts on warrants for its own conditions (Release, Stop,
Restart, a rehearsal), claims each once, and holds the act to the digest the option bound.
The record was searched first ("settings propose warrant", "trusted setting approve", "secret ask desk
prompt"): nothing beside ADR 0274, issue 339's rule, ADR 0259 §10 and the operator's direction.
**Measured in the controller's code on 2026-10-10.** The `settings set` command is the one place a layer is
written; the terminal rule is keyed on the verb named in the process's environment. The `asked` bucket on the
bus is written by the controller alone, so a record there, unlike the agent module's `proposals` state (ADR
0274 §3), proves who kept it. A layer carries when it was set and not who set it. The router's content rule
refuses a path, an address or a secret's shape in any ask's words, and `sources` holds both a path and an
address. The desk's prompt (`node-launcher.secret`) is written by the launcher from the module's, the secret's
and the machine's names, says the controller asks, and takes no words of the caller's; the bus lets only the
controller ask it. Nothing bounded how often it could be asked.
### Against GENESIS
- **Failure must be loud.** A proposal nothing can carry to the operator is refused at once, in words, never
left waiting for an answer that cannot come.
- **The mesh owns the truth.** The layer is the mesh's record, set by the controller on a warrant it checked,
never a value an agent wrote; who approved it is kept beside it.
- **Effect — "when something genuinely needs a decision, you are asked, with the context".** The operator reads
the module, the machine and the exact change on their phone, and taps.
## Considered Options
### Who may set a trusted setting
1. **The controller's terminal alone** (issue 339's rule). Safe, and kept as one of two ways. Alone, every
placement and every mount is a trip to the control node, and an agent can only describe what to type.
2. **Let verbs set trusted settings outright**, trusting the caller. Rejected: an agent would then decide what
root mounts and owns on a machine, which is the hole issue 339 closed.
3. **An agent proposes through a verb; the operator approves on a channel that proves who answered; the
controller sets the layer on the warrant.** Chosen, beside 1.
### Who performs the set
1. **The verb's process, on hearing the warrant.** Rejected: a verb's process is short-lived and does not hear
the router's word; the serving controller is the asker that holds its asks and claims each once.
2. **The serving controller, in-process, as `settings set` at the terminal does.** Chosen. The same judgement
(the module's definition, a line break, a port per machine, a removal meant or refused), the same history,
the same words.
### What the operator reads
1. **The exact values, always.** Rejected: the router's content rule refuses a path, an address or a secret's
shape in any message that leaves the mesh, and a mount's source is both a path and an address.
2. **A fingerprint only.** Rejected: nobody approves what they cannot read.
3. **Every key with its exact new value where every word may leave the mesh; where not, the value in its own
shape with the part that may not leave replaced by a marker (‹address›, ‹path›, ‹withheld›), the layer's
fingerprint, and where the whole is read.** Chosen. "recalbox=smb://host/share@/mnt/recalbox" is shown as
"recalbox=‹address›@‹path›", and `settings proposals <id>` shows it whole, with the same fingerprint.
### Where the record of the set is kept
1. **A seat event of the controller's own**, beside the hand-act log. Rejected for now: nothing consumes it, and
the installer's first user list in the node-engine's repository names every controller event one by one, so
it would cost a node-engine change and rollout for a fact without a reader.
2. **The hand-act log (on the bus), the layer's own record of who approved it, and the router's edit of the
ask on every channel to its outcome.** Chosen. The warrant is recorded under the verb `warrant`, which the
hand-act log counts as a person's decision; `settings` says "approved by the operator via telegram at …".
### How a module's own secret is asked for
1. **Through a verb's argument, or on Telegram.** Rejected: a verb's caller may be an agent, and a value typed
on Telegram passes a bot's server. A secret's value is typed where no agent and no outside party reads it.
2. **The desk prompt, as `give` opens it, asked for by a verb from anywhere, bounded, naming who asked.**
Chosen. The value is typed at the desk, sealed to the one call, sealed again to the module's machine, and
never in an argument, a log or an event.
## Decision
### 1. A trusted setting may be proposed through a verb, by anyone the bus admits
The controller's `settings` verb gains three arguments: `propose` (with `values`, or `clear`, and `replace` as
for a set), `proposals` and `proposal`. The command lines are `settings propose <module> <values | --clear>
[--node <node>] [--replace]` and `settings proposals [<id>]`, the operator's as `nox settings propose …`. A
proposal is for any key, the trusted ones included; `settings set` through a verb still refuses a trusted
setting (issue 339), and its refusal now names the proposal as the way.
A proposal **changes nothing**. It is kept in the controller's own asks on the bus (the `asked` bucket, which
the controller alone writes), with the module, the machine, the values whole, whether the layer is cleared or
a removal meant, the layer as it stood when proposed, who proposed it (the bus's word on the caller) and when,
and the digests of the values and of the layer they replace. It is judged as `settings set` judges before the
operator is asked, so no ask is raised for a layer the mesh would refuse, and a removal not marked `--replace`
is refused as [ADR 0217](0217-no-change-to-a-machine-takes-effect-unseen.md) refuses it at the terminal.
### 2. The ask
One ask per proposal, published under the controller's name on the `operator-channel` seat:
- **headline**: "Set mounts on shanks?" ("Clear …?", "… on the whole mesh?"), shortened when the names make
it longer than the router allows;
- **explanation**: the module and the machine; who proposed it and when; then the change against the layer as
it stands — "+ key: value" added, "~ key: value (was: old)" changed, "- key (was: old)" removed, and the
count of keys unchanged — each value exact where every word of it may leave the mesh, else in its shape
with ‹address›, ‹path› or ‹withheld› in place of what may not; the layer's **fingerprint** (the first 24
hexadecimal digits of its digest, in groups of four); when a part is not shown, where the whole is read
(`settings proposals <id>`, through the mesh MCP server or `mesh-cli`), whose fingerprint must be the one on
the phone; and that, approved, the layer is set at once and the machine takes it at its next push;
- **two options, Approve and Decline, both at the level approve**, as the controller's rehearsal asks, so only a
channel that proves who answered carries either. Each binds the digest of its act: the proposal's id, the
answer, the module, the machine, the digest of the exact values, the digest of the layer they replace,
whether the removal is meant, whether it is a clear, who proposed it and when;
- **expiry**: a day less ten minutes after it was proposed; at expiry the proposal is discarded. An ask that
authorises never defaults (ADR 0259);
- **about**: the module and the machine, so a newer proposal for the same layer replaces an older one still
open, and the older is discarded.
### 3. The serving controller sets the layer on the warrant, and on nothing else
The controller acts on the warrant as on any other of its asks (ADR 0259 §6): only for an ask it holds, only
on a warrant whose ask digest is the one it kept, claimed once by compare-and-set so a warrant heard twice, or
replayed, changes nothing; only for an option the ask offered, at that option's level, before the ask expired.
Then, before anything is set:
1. the act about to be performed must be the one the chosen option bound, and **the values kept in the
record must digest to the digest in that act**: a record whose values, or whose layer-as-it-stood, changed
after the ask is refused and nothing is set;
2. the layer must still be the one the operator was shown the change against (to-be 46 §10, step 7): a layer
changed since, at the terminal or on another warrant, refuses the act, and the proposal is made again;
3. the layer is set, or cleared, exactly as `settings set` and `settings clear` do at the terminal, with the
same judgement and the same history kept, and **who approved it is kept beside the layer**: "approved by
the operator, as telegram identity …, via telegram (user id verified) at …, ask <id>, proposed by <who>".
`settings` says it back, so a layer the operator approved on their phone is told from one typed; a layer
set at the terminal says so, and one set through a verb names the verb.
On Decline nothing is set and the proposal is recorded as declined; on expiry, a cancel, a replacement or
the router's refusal nothing is set and the proposal is recorded as ended. Either way the warrant, or the
end, is recorded in the hand-act log under the verb `warrant`, a person's decision and never a repair, with
who chose, through which channel and with which proofs. **The push afterwards stays a separate act**, as it
is for a layer set at the terminal: the proposal's answer says `push <node>`.
### 4. Fail closed
A proposal is refused at once, in words, naming the terminal's line instead, when no module holding the
operator channel is assigned, when the bus does not yet hold the controller's grant to ask, when the ask could
not be published, or when the ask's words would carry what may not leave the mesh and the change could not be
shown without it. Published, the verb waits a few seconds for the router's word: a refusal (no channel can
carry an approval) is said to the caller, and the proposal is recorded as ended. The router caps open asks at
three per asker, the controller's conditions among them; a proposal that would be the fourth is refused before
it is asked, and the same change proposed twice is refused naming the first.
### 5. A module's own secret is asked for, and typed at the desk
The controller gains the verb **`secret-ask`** (`secret ask <node> <module> <name> [--at <desk>]`): the operator
is asked for the module's own secret in the desk's hidden prompt, on the module's machine or the one `at`
names, exactly as the `give` verb has it since ADR 0259 §10 — `give` now composes the same line. The value is
typed at the desk, sealed to the one call's key before it leaves that machine, opened in the controller, sealed
to the module's machine as `secret accept` seals it, and forgotten: **never in a verb's argument, never on a
channel, never in a log, an answer or an event**. It is refused, before anybody is asked to type, for a secret
the mesh issues itself (the module's bus account, one the mesh may make) and for a module that runs as an
account of its own, whose value is typed at the controller's terminal (ADR 0259 §10, N1-give).
**Bounded, and the prompt names who asked.** Every ask is recorded in the store before the prompt opens, with
who asked (the bus's word on the caller), the secret, the machine, the desk and how it ended: one open ask per
secret, and three an hour, read from that record, so an agent cannot keep a prompt in front of the operator
until they type. The prompt names the module, the secret, the machine and who asked: the caller as the bus
named it, cut to a name's characters by the controller and refused by the launcher in any other shape, never a
word the caller chose. Given, the value is recorded in the hand-act log with who asked, and announced on every
channel as every given secret is.
### 6. What this changes in the earlier records
- **Issue 339's rule** ("set at the controller's terminal only, never through a verb") gains a second way: a
trusted setting is set at the terminal, or on the operator's warrant. The refusal through a verb stands and
names the proposal.
- **ADR 0259 §10, step 7** (the desk prompt opened by `give`): the same prompt is opened by `secret-ask` from
anywhere, bounded, naming who asked; `give` composes its line.
- **ADR 0266** (every `secret` subcommand but `rotate` refused through a verb): `secret ask` is the one other
line a verb runs, carrying no value and answering none.
- **ADR 0217 §1** stands: a proposal that removes a key is refused unless `--replace` says the removal is
meant, and the removal is in the ask's words.
- **ADR 0262** stands: `settings` shows every value and where it came from, and now who set the layer.
## Consequences
- An agent sets a trusted setting with one call and one tap on the operator's phone, and asks for a secret
with one call and the operator's typing at their desk. No line is typed at the control node for either.
- No caller of a verb can set a trusted setting: what it writes is a proposal, and the controller sets the
layer only on a warrant bound to the exact values the operator was shown.
- **What got harder:**
- every trusted setting is a question to the operator, among at most three open asks of the controller's;
- a value with a path or an address is read in part on the phone and whole with `settings proposals`;
- a layer changed between the proposal and the approval refuses the act, and the proposal is made again;
- a secret is asked for at most three times an hour, and a prompt the operator did not start now names who
did start it, so they decline it;
- the store gains a column on the settings layers (migration 0090) and a table of secret asks (migration 0091).
## How it is checked
| Rule | Checked by |
|---|---|
| A proposal changes nothing, and asks at the level approve with the exact change | the controller's test: the ask passes the SDK's check, offers Approve and Decline both at the level approve, each binding an act digest; the explanation carries each key with its value or its shape, the layer's fingerprint and the "was" of a changed key, and passes the content rule; the kept record is the controller's own, and no layer is set (`TestAProposalAsksAtTheLevelApproveWithTheExactChange`, `TestAClearIsProposedAndShowsWhatItRemoves`) |
| What the phone is shown keeps a value's shape and passes the content rule | `TestAValueIsShownInItsShapeAndPassesTheContentRule` |
| A layer the mesh would refuse, or a silent removal, is not asked | `TestAProposalTheMeshWouldRefuseIsNotAsked` |
| The layer is set once, on the operator's approval, with who approved it; a replay changes nothing | `TestTheLayerIsSetOnceOnTheOperatorsApproval`: the warrant heard twice sets once, no verb is called, the hand-act reads `warrant` with the answer and the values' digest, and counts as a person's decision |
| Decline, expiry, cancel, replacement and the router's refusal discard | `TestDeclineExpiryAndRefusalDiscardAProposal`, each outcome, and an approval after the end refused |
| The warrant binds the exact values | `TestAWarrantSetsOnlyTheExactValuesTheOperatorWasShown`: the values or the layer-as-it-stood changed in the record, the action's digest changed, another ask's digest, the level acknowledge, after expiry, nobody chose, another asker's — each sets nothing |
| Set on the real store as at the terminal, judged, the history kept, who approved it said, a stale proposal refused | `TestSetOnAWarrantJudgesTheLayerAndKeepsWhoApprovedIt`: the layer set and `settings show` says who approved it; the same proposal again refused for a changed layer; a removal not meant refused; a line break refused; a clear keeps who cleared it with the history |
| A layer says who set it, at the terminal and through a verb | `TestALayerSaysWhoSetIt` |
| Fail closed | `TestAProposalFailsClosedWhenNothingCanCarryIt`: no router, no grant, a publish that fails, the router's refusal — each refused in words naming the terminal's line, nothing kept or marked unsent |
| Bounded | `TestAProposalIsBounded` (the same change twice; a fourth open ask), `TestOpenProposalsCountTowardTheAsksHeldOpen` |
| A trusted setting through the settings verb is still refused, naming the proposal | `TestATrustedSettingThroughAVerbNamesTheProposal`, and issue 339's tests unchanged |
| The verb composes propose, proposals and proposal; the generic command proposes nothing | `TestTheSettingsVerbComposesProposeAndProposals` |
| The secret's value is never in an argument, a log or an event | `TestASecretGivenAtTheDeskIsSealedAndSaidNowhere` (unchanged), `TestASecretAskIsNeverASecretRead` (a value on the line, a file, recover and export each refused) |
| The prompt names who asked from the bus's word alone, in a name's characters | `TestThePromptNamesWhoAskedFromTheBussWordAlone`; the launcher's `TestThePromptIsWrittenHereFromNamesAndSaysTheControllerAsks` (a caller's name taken, a sentence refused) |
| One open ask per secret, three an hour, and every end recorded | `TestASecretAskIsBoundedAndItsEndRecorded`, and on the store `TestASecretAskIsOneAtATimeAndFewAnHour` |
| The `give` and `secret-ask` verbs run the one desk line, and no other `secret` line passes a verb | `TestTheGiveVerbRunsTheDeskPathAndTheControllerMayAskTheDesk`, `TestOnlyTheGiveLinePassesTheTerminalRuleForSecrets` |
| Live, after rollout | an agent proposes `sources` for mounts on the gaming machine's client; the operator's phone shows "Set mounts on <node>?" with the key, its value in shape, the fingerprint, Approve and Decline; after Approve `settings` shows the layer with "approved by the operator … via telegram", and `hand-acts` shows the warrant. An agent asks for `smb-credentials` there; a prompt on that desk names mounts, the secret and who asked; the operator types; the secret is sealed to that machine's mounts |
## References
- [ADR 0274](0274-an-agent-proposes-a-shared-instruction-section-and-every-node-takes-it-only-on-the-operators-warrant-which-it-proves-itself.md)
— the pattern this record extends to settings and secrets
- [ADR 0259](0259-an-ask-is-a-message-on-the-bus-any-channel-answers-it-and-the-asker-acts-on-a-warrant.md) — the ask,
the warrant, and the desk prompt (§10)
- [Issue 339](../04-ISSUES/339-a-verb-can-place-a-directory-at-the-machines-own/00-report.md) — the rule this
record widens
- [ADR 0217](0217-no-change-to-a-machine-takes-effect-unseen.md), [ADR 0262](0262-a-preference-has-a-default-in-its-manifest-and-the-operators-own-value-has-none.md)
— a layer replaced whole, and what `settings` says
- [ADR 0266](0266-on-the-control-node-agents-run-under-an-account-of-their-own-that-cannot-become-root-without-a-person.md)
— the terminal-only commands
- [to-be 44](../03-DESIGN/01-to-be/44-no-change-takes-effect-unseen.md) §1, [to-be 52](../03-DESIGN/01-to-be/52-shares-and-mounts.md)
§2, [to-be 46](../03-DESIGN/01-to-be/46-the-conversation-with-the-operator.md) §10 — the designs amended
- mesh-controller `cmd/mesh-controller/proposals.go`, `desk_secret.go`, `internal/inventory/secret_ask.go`,
migrations 0090 and 0091; mesh-catalog `modules/rofi` (the prompt names who asked)
@@ -7,8 +7,9 @@ code:
- mesh-controller examples/postgres-provisioner
- mesh-controller internal/inventory/given.go
- mesh-controller cmd/mesh-controller/given.go
updated: 2026-10-06
updated: 2026-10-10
decisions:
- 02-DECISIONS/0277-a-trusted-setting-is-proposed-through-a-verb-and-set-on-the-operators-warrant-and-a-modules-own-secret-is-asked-for-and-typed-at-the-desk.md
- 02-DECISIONS/0001-mesh-brokers-nodes-host-agents-think.md
- 02-DECISIONS/0009-modules-and-the-graph.md
- 02-DECISIONS/0085-a-secret-is-a-provision.md
@@ -179,3 +180,10 @@ named and its age; the last is replaced when a person asks `secret rotate`. A pa
delivers is unchanged ([ADR 0092](../../02-DECISIONS/0092-an-operator-delivers-a-pair-credential.md)).
*How it is checked:* the tests ADR 0228 names, and a live `rotate` of a given at-start secret through
the mesh MCP server.
*Amended 2026-10-10 by [ADR 0277](../../02-DECISIONS/0277-a-trusted-setting-is-proposed-through-a-verb-and-set-on-the-operators-warrant-and-a-modules-own-secret-is-asked-for-and-typed-at-the-desk.md).* An outside party's value is also **asked for**: the
controller's `secret-ask` verb, from anywhere on the mesh, opens the desk's hidden prompt on the module's
machine (or the one named), naming the module, the secret and who asked; the operator types the value there,
sealed to the one call and then to the machine, never in an argument, a log or an event. One open ask per
secret, three an hour; refused for a secret the mesh makes itself and for a module running as an account of its
own, whose value stays the terminal's.
@@ -2,9 +2,10 @@
layer: to-be
status: in-progress
code:
- mesh-controller: cmd/mesh-controller/unseen.go, cmd/mesh-controller/push.go (--all, --move, the hold), cmd/mesh-controller/held_back.go (the hold in a named push's cascade), cmd/mesh-controller/plan.go (--diff), cmd/mesh-controller/modules.go (settings show, --replace), cmd/mesh-controller/seatverbs.go and internal/catalogue/verbs.go (the verbs' arguments), internal/inventory/unseen.go, internal/inventory/catalogue.go (the history kept on set and clear), internal/inventory/migrations/0078-what-a-change-replaces.sql
updated: 2026-10-08
- mesh-controller: cmd/mesh-controller/unseen.go, cmd/mesh-controller/push.go (--all, --move, the hold), cmd/mesh-controller/held_back.go (the hold in a named push's cascade), cmd/mesh-controller/plan.go (--diff), cmd/mesh-controller/modules.go (settings show, --replace), cmd/mesh-controller/seatverbs.go and internal/catalogue/verbs.go (the verbs' arguments), internal/inventory/unseen.go, internal/inventory/catalogue.go (the history kept on set and clear), internal/inventory/migrations/0078-what-a-change-replaces.sql, cmd/mesh-controller/proposals.go and internal/inventory/migrations/0090-a-layer-says-who-set-it.sql (a proposal set on a warrant, who set a layer)
updated: 2026-10-10
decisions:
- 02-DECISIONS/0277-a-trusted-setting-is-proposed-through-a-verb-and-set-on-the-operators-warrant-and-a-modules-own-secret-is-asked-for-and-typed-at-the-desk.md
- 02-DECISIONS/0217-no-change-to-a-machine-takes-effect-unseen.md
- 02-DECISIONS/0030-data-outlives-the-mesh-that-declared-it.md
---
@@ -29,6 +30,21 @@ That stays. Around it:
- **Keeping the previous layer.** Each set and each clear records the layer it replaced and when, so
the previous value is read back with `settings show --history`, not from a backup.
*Amended 2026-10-10 by [ADR 0277](../../02-DECISIONS/0277-a-trusted-setting-is-proposed-through-a-verb-and-set-on-the-operators-warrant-and-a-modules-own-secret-is-asked-for-and-typed-at-the-desk.md).*
- **Who set it is kept with the layer.** A layer says who set it: at the controller's terminal by whom,
through which verb, or approved by the operator on which channel and when (ask id, proposed by whom).
`settings show` says it after the layer; the history copy keeps it.
- **A trusted setting is proposed and set on a warrant.** `settings propose <module> <values | --clear>
[--node] [--replace]` (the verb's `propose`) keeps a proposal in the controller's own asks and asks the
operator on a channel that proves who answers: the module, the machine, every key with its exact new value
(in its shape where a path or an address may not leave the mesh), the "was" of a changed key, the removed
keys, and the layer's fingerprint. Nothing changes until Approve, on which the serving controller sets the
layer as a set at the terminal would — judged the same, the removal meant or refused the same, the history
kept — only when the record's values still digest to what the option bound and the layer is still the one
shown. Decline, expiry or the router's refusal discard it. `settings proposals [<id>]` lists them and shows
one whole. The push afterwards is a separate act.
## 2. A push says what it will change
- **What was sent is kept.** Each send records a summary of the declaration it sent the machine, beside
@@ -2,8 +2,9 @@
layer: to-be
status: designed
code: []
updated: 2026-10-08
updated: 2026-10-10
decisions:
- 02-DECISIONS/0277-a-trusted-setting-is-proposed-through-a-verb-and-set-on-the-operators-warrant-and-a-modules-own-secret-is-asked-for-and-typed-at-the-desk.md
- 02-DECISIONS/0259-an-ask-is-a-message-on-the-bus-any-channel-answers-it-and-the-asker-acts-on-a-warrant.md
- 02-DECISIONS/0253-a-condition-says-itself-to-the-operator-in-plain-words-beside-its-summary.md
- 02-DECISIONS/0234-the-mesh-holds-a-conversation-with-its-operator.md
@@ -380,6 +381,7 @@ the factors are the router's state.
| approve or reject a waiting retirement set (`retire approve` / `retire reject`) | approve |
| confirm a kept binding moves (`pin`, while `binding-kept` names it) | approve |
| end a stuck plan; send a machine its declaration by hand; reset a bus consumer; retry a healer | approve |
| set or clear a trusted setting an agent proposed (`settings propose`, [ADR 0277](../../02-DECISIONS/0277-a-trusted-setting-is-proposed-through-a-verb-and-set-on-the-operators-warrant-and-a-modules-own-secret-is-asked-for-and-typed-at-the-desk.md)) — bound to the exact values shown; the push stays a separate act | approve |
| silence a condition | acknowledge |
| delete a retired consumer's data, one or by age (`cleanup delete`) | destroy |
| change the operator's identities, the away channel, or a factor's enrolment | destroy |
+13 -5
View File
@@ -5,8 +5,9 @@ code:
- mesh-controller internal/catalogue (the seats node-nfs-server and node-mounts)
- mesh-catalog modules/nfs-server
- mesh-catalog modules/mounts
updated: 2026-10-08
updated: 2026-10-10
decisions:
- 02-DECISIONS/0277-a-trusted-setting-is-proposed-through-a-verb-and-set-on-the-operators-warrant-and-a-modules-own-secret-is-asked-for-and-typed-at-the-desk.md
- 02-DECISIONS/0263-a-share-is-a-provision-a-node-mounts-it-on-demand-and-only-nodes-that-ask-get-it.md
- 02-DECISIONS/0051-shared-data-is-the-operators.md
- 02-DECISIONS/0092-an-operator-delivers-a-pair-credential.md
@@ -103,8 +104,14 @@ The glossary holds the three words.
`name=disk:<uuid>@<mountpoint>`, each optionally `:ro`. `none` (the default) is none.
- **Its secret `smb-credentials`.** One section per SMB source, `[name]` with `username=` and
`password=`, issued outside the mesh and given with `secret accept <node> mounts smb-credentials
--from <file>`. The process writes one credentials file per source, readable by root only. A source
--from <file>` at the controller's terminal — or asked for by an agent with the controller's `secret-ask`
verb, on which a hidden prompt opens at that machine's desk naming the module, the secret and who asked,
and the operator types it there ([ADR 0277](../../02-DECISIONS/0277-a-trusted-setting-is-proposed-through-a-verb-and-set-on-the-operators-warrant-and-a-modules-own-secret-is-asked-for-and-typed-at-the-desk.md)). The process writes one credentials file per source, readable by root only. A source
with no section is said with that remedy and is not mounted.
- **Its settings are trusted settings** (a trusted file asks for them), so a verb may not set them outright:
an agent proposes them (`settings propose mounts … --node <node>`) and the operator approves on their
phone, where the ask shows each source in its shape ("recalbox=‹address›@‹path›") and the layer's
fingerprint; the layer is set on the warrant and pushed after (ADR 0277).
- **What it refuses.** A mount point at, under or above any data the mesh keeps on this machine (the
controller's `data` verb, asked over the bus; until it is read nothing new is set up), a system path,
a mount point where something else is mounted or a folder that is not empty, and a share this machine
@@ -206,9 +213,10 @@ folders, none refused for a reason not understood.
export goes; the mesh's stays. *Undo:* `zfs set sharenfs=<the old value>` by a person, recorded as a
hand-act.
7. **The downloads**, the same way: read-only first, then read-write.
8. **The gaming device**: the operator gives `smb-credentials` with `secret accept`; the source is added
to `sources`; `node-mounts.list` says it `absent` while the device is off, and it mounts on access
when it is on. Then its fstab line is adopted.
8. **The gaming device**: an agent asks for `smb-credentials` with `secret-ask`, and the operator types it at
that machine's desk (or gives it with `secret accept` at the terminal); the agent proposes the source in
`sources`, and the operator approves it on their phone; `node-mounts.list` says it `absent` while the
device is off, and it mounts on access when it is on. Then its fstab line is adopted.
9. **The laptop**, read-only, granted read-only on the home server.
**Root.** Both modules' tools act as root through `sudo -n`, and the `sudo` module grants the operator
@@ -36,6 +36,12 @@ break adds a line of the caller's own to such a file.
## Why it is an issue
> **The mechanism changed — 2026-10-10, by [ADR 0277](../../02-DECISIONS/0277-a-trusted-setting-is-proposed-through-a-verb-and-set-on-the-operators-warrant-and-a-modules-own-secret-is-asked-for-and-typed-at-the-desk.md).** The fix below made every trusted
> setting the controller's terminal's alone. That stands as one of two ways: a trusted setting is now also
> **proposed** through the `settings` verb by anyone the bus admits and **set by the controller only on the
> operator's warrant**, answered on a channel that proves who answered, bound to the exact values shown. The
> refusal through a verb stands, and names the proposal.
These settings were made for the operator. They say where an adopted machine keeps a module's data. But
the mesh has one way to write any setting, the `settings` verb, and whoever may call a verb includes every
agent session on a machine that runs the mesh MCP server. The generic `command` verb reaches the same