ADR 0259: a rehearsal, not a drill; the announcement at the terminal checked; the operator's steps with nox, and the standard-input gap said
This commit is contained in:
@@ -389,6 +389,10 @@ becomes a message). **Decided by** ADR 0227, 0231, 0240, 0252.
|
||||
its **budget**, its back-off and its brake. A healer may not withdraw, delete or recreate data.
|
||||
- **drill** — something broken on purpose to see the mesh raise and clear its condition; a drill is
|
||||
never counted as a repair.
|
||||
- **rehearsal** — a question the operator starts at the controller's terminal (`rehearse`) and answers on a
|
||||
channel, to see an answer travel the whole way: its approval performs nothing and is recorded as the
|
||||
operator's decision ([ADR 0259](../02-DECISIONS/0259-an-ask-is-a-message-on-the-bus-any-channel-answers-it-and-the-asker-acts-on-a-warrant.md)).
|
||||
Not a drill: nothing is broken.
|
||||
- **hand-act** — a repair a person made by hand, recorded so the mesh knows it happened.
|
||||
- **witness** — what rolls a core component back when its new build does not become healthy: never the
|
||||
component itself (to-be 45 §8).
|
||||
|
||||
+5
-3
@@ -497,7 +497,8 @@ with the router not knowing its own machine, it approved. Now:
|
||||
the call's key, and the channel the operator's answers are proven on became the agent's. Now the secret of
|
||||
a module running as an account of its own (the router, Telegram, the desk channel) is refused at the desk
|
||||
before anybody is asked, naming the line to type at the controller's terminal instead —
|
||||
`mesh-controller secret accept <node> telegram telegram-token`, read without echo. There it is announced
|
||||
`nox secret accept <node> telegram telegram-token` (`nox` is `mesh-cli`'s alias; on the control-node,
|
||||
from the operator's own account, it is the controller's terminal, ADR 0272). There it is announced
|
||||
on every channel, the one being replaced among them (it still runs on its old token until the next push),
|
||||
**before** it is kept, and not kept when that announcement fails. A grant test holds that only the desk
|
||||
machine's launcher, carried by that machine's runtime, may answer its prompt; for any other module's
|
||||
@@ -532,7 +533,7 @@ Telegram, or from the mesh MCP server." The asker's words never name a channel.
|
||||
|
||||
| Rule | Checked by |
|
||||
|---|---|
|
||||
| An asker publishes asks only under its own name, and hears only its own warrants | controller grant tests: a module using `operator-channel` is granted `accept.ask.<itself>` and `event.decided.<itself>`, no wildcard; a live drill publishing under another name is refused by the server |
|
||||
| An asker publishes asks only under its own name, and hears only its own warrants | controller grant tests: a module using `operator-channel` is granted `accept.ask.<itself>` and `event.decided.<itself>`, no wildcard; the lab's proof `asks` publishing under another name on a real bus is refused by the server |
|
||||
| Only the router publishes a warrant | controller grant test: `event.decided.*` is in no principal's publish list but the holder's |
|
||||
| A channel publishes only its own kind's answers, links and proofs | controller grant tests over a kinded claim; a second claim of a kind is refused |
|
||||
| A code is never on a stream | controller test: no stream's subjects cover `mesh.seat.*.proof.>` |
|
||||
@@ -557,12 +558,13 @@ Telegram, or from the mesh MCP server." The asker's words never name a channel.
|
||||
| Only the serving controller answers `root-free`; a machine waiting for its first setuid search is not root-free | controller grant test `TestOnlyTheServingControllerMayAnswerRootFree` (one answerer); `TestAMachineWaitingForItsFirstSetuidSearchIsNotRootFree`; `TestRootNotFreeIsQuietWhileTheFirstSearchRunsAndKeyedApartFromDA` |
|
||||
| A desk unlink in the first hour bars nothing; root lifts any bar (N1-router) | router tests `TestAnUnlinkFromTheDeskInTheFirstHourBarsNothing`, `TestBreakGlassLiftsABarOnRelinking` |
|
||||
| A trusted party's secret is never given at a desk; only the desk machine's launcher answers its prompt (N1-give) | controller tests `TestATrustedPartysSecretIsNeverTakenAtADesk`, `TestOnlyTheDeskMachinesLauncherMayAnswerItsPrompt` |
|
||||
| At the controller's terminal, a trusted party's secret is announced on every channel before it is kept, and not kept when the announcement fails; a machine the mesh does not know is refused before anybody types (N1-give) | controller tests `TestATrustedPartysSecretGivenAtTheTerminalIsAnnouncedBeforeItIsKept` (fails when the announcement before keeping is removed), `TestAGiveNamingAMachineTheMeshDoesNotKnowAsksNobody` |
|
||||
| A silence never takes an approval back (M1) | controller test `TestAnAcknowledgementNeverSharesAnAskWithAnApproval`, with the condition silenced as the controller silences it |
|
||||
| The router never waits on the controller while holding its work | router test `TestTheRootFreeWordIsNotAskedWhileTheWorkIsHeld` |
|
||||
| The self-check counts the login shell only where `execute` is served, and what it cannot measure fails | controller probe tests (`TestTheLoginShellCountsOnlyWhereExecuteIsServed`, the unmeasured case) |
|
||||
| The whole flow, before anyone uses it | the lab's proof `asks` (mesh-lab): a real bus with the controller's composed grants, the router and the Telegram channel in runtimes of their own accounts, a fake Telegram API — approve acted once, decline, expiry, a replayed tap, a tap from another account, a forged warrant, an ask under another name, an ask from a module that may not ask |
|
||||
| The controller holds no channel code | review; the controller's module imports no channel package |
|
||||
| End to end | live acceptance after rollout (mesh-lab `asks/live-acceptance.sh`): the controller's `drill`, started at its terminal alone, approved on the phone, acted on once and performing nothing; the hand-act reads `warrant drill drill=approve`, by "the operator, as telegram identity …", via "telegram (telegram), user id verified", proofs P1 |
|
||||
| End to end | live acceptance after rollout (mesh-lab `asks/live-acceptance.sh`): a **rehearsal** (`rehearse`), started at the controller's terminal alone, approved on the phone, acted on once and performing nothing; the hand-act reads `warrant rehearsal rehearsal=approve`, by "the operator, as telegram identity …", via "telegram (telegram), user id verified", proofs P1 |
|
||||
| An answer from another account is refused and the operator is told which account tried | router test (`TestEveryAnswerThatIsNotTheOperatorsIsRefusedAndSaid`); the lab's proof |
|
||||
| A message carrying an ask's answers is never folded into a digest | router test (`TestAnAsksMessageWithOneAnswerIsNotFoldedIntoADigest`); the lab's proof, where it was found |
|
||||
|
||||
|
||||
@@ -559,7 +559,30 @@ Each phase ends at its own *done when*. Owning repositories from [`repos.md`](..
|
||||
| **4 — Asks, and operator messages** | `ask`, `ask cancel`, `asks`, `answer`; the events; kinds, life, limits, batching, history; escalation; addressing, the register of agents with kept messages, the responder; the untrusted-input rule in every agent module's instructions (§5) | mesh-catalog | the router tests of ADR 0234 pass; live: an agent's question answered at the desk, and with the desk locked, on the phone; `@mesh status` answered; a message to a stopped agent kept and said |
|
||||
| **5a — Asks on the bus** (ADR 0259) | the kinded bench, caller-named verbs, `proof` subjects and the records users read (controller); a bundle's seat traffic, compare-and-set state and its own account (tool runner); the asker's and channel's types (shared library); the router's asks, tokens, identities, judging, warrants, expiry and linking with its hour (messenger); `telegram` and `desk-channel`; the controller asking for its conditions' actions and acting on warrants | mesh-controller, mesh-tools, mesh-sdk, mesh-catalog | a held delivery released from the phone; the hand-act reads "the operator, via telegram, user id verified"; a desk Silence goes through an ask |
|
||||
| **5 — Authorise, with TOTP** | `authorises` in the verb table; the router's checks for the code; direct calls refused, break-glass; `retire approve` takes `expect`; the hand-act fields; the TOTP seed as the router's state, enrolled at a terminal with ten recovery codes; `factor recover`, `factor status`, the local-only break-glass enrolment; no P2 tier before recovery codes exist; optional key enrolment; the self-check probe for the away channel; agents' grants lose the authorising verbs | mesh-controller; mesh-catalog (agents' grants, the desk's code prompt) | one controller test per refusal passes; at the desk, approve needs a code; a recovery drill re-enrols with a recovery code, and is announced |
|
||||
| **6 — Telegram live** | the `telegram` module (built in 5a) with replies and forced-reply codes, under its own account on the control node; the operator's two bots configured; the watcher assigned off the control node; the dead-man ping | mesh-catalog | the self-check says the away channel carries every tier; live drills: an approve and a destroy on a test condition answered on the phone, with the hand-acts read |
|
||||
| **6 — Telegram live** | the `telegram` module (built in 5a) with replies and forced-reply codes, under its own account on the control node; the operator's two bots configured; the watcher assigned off the control node; the dead-man ping | mesh-catalog | the self-check says the away channel carries every tier; rehearsals: an approve and a destroy answered on the phone, with the hand-acts read |
|
||||
|
||||
**Switching phase 5a on: the operator's steps, in order** (amended 2026-10-09, ADR 0259). Each line is typed with
|
||||
`nox` (`mesh-cli`) on the control-node, from the operator's own account, which is the controller's terminal
|
||||
(ADR 0272):
|
||||
|
||||
1. The pull requests merge in their order, each after its checks pass on the merge result; nothing is assigned
|
||||
by the merges.
|
||||
2. The agent account (ADR 0266) runs on the control-node and the login shell's `execute` is withheld there
|
||||
(ADR 0268): until both hold, the self-check's `agent-root` or `root-not-free` stays open and Telegram only
|
||||
acknowledges.
|
||||
3. `messenger`, `telegram` and `desk-channel` are assigned to the control-node (`desktop-machines` set on
|
||||
`desk-channel` in the same step), and the control-node is pushed.
|
||||
4. A bot is made with Telegram's BotFather, and its token is given at the controller's terminal:
|
||||
`nox secret accept <control-node> telegram telegram-token`. It is announced on every channel before it is
|
||||
kept. Then the control-node is pushed again, so the channel holds it.
|
||||
5. The operator sends `/start` to the bot from their own account, in a private chat, and sends back the six digits
|
||||
the desk shows. Nobody configures a chat id: the router's identity list is written by linking alone.
|
||||
6. An hour later, `live-acceptance.sh` (mesh-lab `asks/`) runs a rehearsal: a question on the phone, approved
|
||||
there, read back from the hand-act log.
|
||||
|
||||
Until `mesh-cli` carries standard input (ADR 0272, a later step), step 4's line cannot read the token from the
|
||||
terminal; it is given with `--from` a file the controller's own account reads and nobody else does, removed
|
||||
right after.
|
||||
|
||||
**Not touched:** the node engine (`mesh-host` repository). Presence comes from the screen-lock seat's
|
||||
holder, not the engine; if a later measure shows the engine must relay it, that is a change here.
|
||||
|
||||
Reference in New Issue
Block a user