Bind old runners through the bus, say when the same call asks anew, and leave release unmarked until the controller's warrant passes the mark (review)
This commit is contained in:
+2
-1
@@ -281,7 +281,8 @@ met, and when. It carries no secret.
|
||||
> **The mechanism changed — 2026-10-10, by [ADR 0286](0286-a-tool-or-verb-marked-in-its-manifest-runs-only-on-the-operators-approval-of-that-one-call-with-its-exact-arguments.md).** A tool or verb marked `needs-approval` in its manifest now runs
|
||||
> only on a warrant for that one call, with its exact arguments, checked by the tool runner that serves it (or
|
||||
> by the controller, for its own verbs). For a marked act the warrant is the only way; for the others this
|
||||
> bullet stands. `mesh-delivery.release` is among the first marked.
|
||||
> bullet stands. `mesh-delivery.release` is not marked first: issue 417 tracks how the controller's own warrant
|
||||
> for it passes the mark.
|
||||
|
||||
### 7. Who the operator is on a channel: linking
|
||||
|
||||
|
||||
+28
-17
@@ -128,8 +128,11 @@ never from the bundle**, so a bundle cannot drop it. A module with a mark is com
|
||||
|
||||
**A runner that does not honour the mark is not issued a marked tool.** A runner declares that it honours it
|
||||
(`approval-mark/1`) when it joins; on a node whose runner does not, the controller withholds every marked tool
|
||||
and verb, and the runner's status names them. A node is never left serving a marked tool unasked because its
|
||||
runner is older than this record.
|
||||
and verb, and the runner's status names them. **The bus enforces it, not the runner**: the controller leaves each
|
||||
marked tool's and verb's subject out of the bus permissions it composes for that runner, so the bus refuses the
|
||||
runner's subscription and a call there finds no responder. Where a runner's grant names a module's subjects as a
|
||||
whole today, it names a marked tool's subject apart from the rest. A node is never left serving a marked tool
|
||||
unasked because its runner is older than this record.
|
||||
|
||||
### 2. The act that is approved
|
||||
|
||||
@@ -150,7 +153,8 @@ On a call to a marked tool with no approval for its act, the runner:
|
||||
goes to a phone; a marked tool takes its secrets another way), or whose arguments are more than 16 KiB;
|
||||
2. publishes **one ask** under the module's name, unless an open ask for the same act exists, in which case it
|
||||
asks nothing new;
|
||||
3. waits up to 5 seconds for the router's word, as ADR 0274 §5 (its note of 2026-10-10) has it, and answers the call.
|
||||
3. waits up to 5 seconds for the router's word (ADR 0274 §5's note of 2026-10-10 waits a few seconds; this record
|
||||
fixes it at 5), and answers the call.
|
||||
|
||||
**The ask:**
|
||||
|
||||
@@ -189,8 +193,13 @@ When a call to a marked tool comes and its act has an ask that was chosen, the r
|
||||
(`Option.Performs`): the same node, build and every argument;
|
||||
4. requires the call to come **within 30 minutes of the choice**;
|
||||
5. claims the ask as used in **the node's own file**, written whole and synced to the disk before it replaces
|
||||
the old one, and kept for 48 hours. A warrant claimed before is refused, so a call runs once however often it
|
||||
is made, and a warrant replayed into the bus runs nothing.
|
||||
the old one, and kept for 48 hours, by one writer per node, so two calls at the same moment cannot both claim
|
||||
it. A warrant claimed before is refused, so one approval runs one call however often it is made, and a
|
||||
warrant replayed into the bus runs nothing.
|
||||
|
||||
The runner always judges **the newest ask it keeps for that act**. After "already run", "expired" or "approved
|
||||
too long ago", the next identical call publishes a new ask, and the used claim stays: running the same act a
|
||||
second time takes a second approval.
|
||||
|
||||
Then it runs the call, answers with the tool's own answer and a line naming the approval ("run on the operator's
|
||||
approval via telegram at 19:21, ask <id>"), and asks the controller's `warranted` to record it in the hand-act
|
||||
@@ -202,10 +211,10 @@ runs nothing: every check above is against the router's record and the call actu
|
||||
### 5. What the caller is told
|
||||
|
||||
The call that does not run says so first, as an error, never as a result: "Not run: this needs the operator's
|
||||
approval. Asked on telegram at 19:21 (ask <id>, fingerprint …); make the same call again once it is approved,
|
||||
before 20:21." Then, for the same call made again: still waiting; declined (the same act is not asked again for
|
||||
10 minutes, and the call says so); expired; approved too long ago (asked again); already run; or refused, with
|
||||
the router's words. `operator-channel.asks` shows the same ask. No answer ever reads as done when nothing ran.
|
||||
approval. Asked on telegram at 19:21 (ask <id>, fingerprint …); make the same call again within 30 minutes of
|
||||
the approval; the ask expires at 20:21." Then, for the same call made again: still waiting; declined (the same
|
||||
act is not asked again for 10 minutes, and the call says so); expired, approved too long ago, or already run
|
||||
(each asks again, §4); or refused, with the router's words. `operator-channel.asks` shows the same ask. No answer ever reads as done when nothing ran.
|
||||
|
||||
### 6. Fail closed
|
||||
|
||||
@@ -227,14 +236,16 @@ The controller serves its own verbs and enforces the same mark on them, with the
|
||||
|
||||
- **`node-login-shell.execute`, on every node, in the seat's definition**, as ADR 0268 §4 decided, once the reads
|
||||
of ADR 0268 §5 that have no tool yet (reading or searching a file, looking up an account) have one on every
|
||||
node, tracked by issue 418. Until then the control-node keeps withholding it and the others serve it unmarked,
|
||||
node, tracked by issue 418 (owner: mesh-tools, or the module that owns each area). Until then the control-node keeps withholding it and the others serve it unmarked,
|
||||
as ADR 0268 has it. Whether the control-node then serves it again, under the mark, stays the operator's
|
||||
setting.
|
||||
- **`mesh-delivery.release`**, the glossary's "a person letting a held delivery go on". The controller's own
|
||||
Release on a condition already goes through an ask, so the operator sees no new kind of question.
|
||||
|
||||
The rest of research 039's candidates, and the split of `rofi_run` and `node-terminal-emulator.open` into a
|
||||
form that opens an entry or a window and a form that runs a command, which is marked, are tracked by issue 417.
|
||||
`mesh-delivery.release`, the glossary's "a person letting a held delivery go on", is not marked first. The
|
||||
controller's Release on a condition is already an ask, and the controller then calls `release` on its warrant;
|
||||
marked as it stands, that call would ask the operator a second time for the same act. How a warrant the
|
||||
controller holds passes the mark of a verb it calls, and then marking `release`, are tracked by issue 417
|
||||
(owners: mesh-controller, mesh-tools). The rest of research 039's candidates, and the split of `rofi_run` and `node-terminal-emulator.open` into a
|
||||
form that opens an entry or a window and a form that runs a command, which is marked, are tracked by issue 417
|
||||
(owners: mesh-catalog for the modules, mesh-controller for the seat).
|
||||
Each is a change to its module's manifest, reviewed like any other.
|
||||
|
||||
### 9. What this changes in the earlier records
|
||||
@@ -270,9 +281,9 @@ Each is a change to its module's manifest, reviewed like any other.
|
||||
| Rule | Checked by |
|
||||
|---|---|
|
||||
| A mark naming nothing served is refused; the mark reaches the runner from the membership | the controller's tests: a manifest marking an unknown tool is refused; a seat's mark reaches every holder's membership; the membership carries it whatever the bundle lists |
|
||||
| A runner that does not honour the mark is not issued a marked tool | the controller's test: a membership for a runner without `approval-mark/1` leaves out the marked tool and names it |
|
||||
| A runner that does not honour the mark cannot serve a marked tool | the controller's test: a membership for a runner without `approval-mark/1` leaves out the marked tool and names it; against a real bus, that runner's grant cannot subscribe the marked tool's subject, and a call there finds no responder |
|
||||
| The first call asks once and runs nothing | the runner's test: a marked tool's bundle is not called; one ask is published under the module's name, passing `Check`, Approve and Decline both at approve, each binding the act's digest; the same call again asks nothing new; the answer is an error saying "Not run" |
|
||||
| The same call runs once on Approve, and only that call | the runner's test against a real bus: after the router's record says Approve, the call runs once; again, it is refused as already run; with one argument changed, another build, another node, after 30 minutes, on Decline, at the level acknowledge, nobody choosing, another ask's warrant, or a record of the runner's pointing at another ask, nothing runs |
|
||||
| The same call runs once on Approve, and only that call | the runner's test against a real bus: after the router's record says Approve, the call runs once; again, it is refused as already run and a new ask is published; two calls at once run once; with one argument changed, another build, another node, after 30 minutes, on Decline, at the level acknowledge, nobody choosing, another ask's warrant, or a record of the runner's pointing at another ask, nothing runs |
|
||||
| A warrant replayed or a file lost runs nothing | the runner's test: a used claim kept across a restart; an unreadable file refuses every marked call |
|
||||
| Fail closed | the runner's test: no holder of the operator channel, the router's refusal, a fourth ask, a secret in an argument and more than 16 KiB are each refused, nothing asked or run where so stated, each said |
|
||||
| The digest is the same in both languages | the shared library's conformance vectors, run in Go and TypeScript |
|
||||
|
||||
@@ -32,8 +32,9 @@ mesh records rather than rolls out — and 62 tools from the rest.
|
||||
may call is every tool on the mesh; its account may publish nothing else and subscribes nothing.
|
||||
|
||||
No call is refused for want of a person's approval: a tool runner serves every call it is issued, whoever made
|
||||
it, and cannot tell an agent from the operator (ADR 0259 §6, issue 340). Only the agent module's instruction
|
||||
proposals and the controller's settings proposals wait for the operator's warrant, each in its own code.
|
||||
it, and cannot tell an agent from the operator (ADR 0259 §6, issue 340). An act waits for the operator's warrant
|
||||
only where its module asks first, in its own code: the agent module's instruction proposals, and the
|
||||
controller's settings proposals and the actions it offers on a condition.
|
||||
|
||||
## The mesh's own verbs
|
||||
|
||||
|
||||
@@ -450,7 +450,8 @@ said on the away channel, with its why.
|
||||
*Added 2026-10-10, [ADR 0286](../../02-DECISIONS/0286-a-tool-or-verb-marked-in-its-manifest-runs-only-on-the-operators-approval-of-that-one-call-with-its-exact-arguments.md).*
|
||||
A module's manifest marks a tool, or a seat verb it serves, as **`needs-approval`**; a seat's definition may mark
|
||||
a verb for every holder. The controller issues the mark in the runner's membership, never from the bundle, and
|
||||
withholds a marked tool from a runner that does not declare `approval-mark/1`.
|
||||
withholds a marked tool from a runner that does not declare `approval-mark/1`, by leaving its subject out of that
|
||||
runner's bus permissions.
|
||||
|
||||
```
|
||||
agent ──call──► tool runner (serving node) ──ask, under the module's name──► router ──► Telegram
|
||||
@@ -466,18 +467,23 @@ withholds a marked tool from a runner that does not declare `approval-mark/1`.
|
||||
with the shared library's `ActDigest` (in Go and TypeScript, one set of vectors).
|
||||
- **The first call asks and does nothing.** One ask per act (its `about` is the act's digest): "Run <tool> on
|
||||
<node>?", the tool's first line, every argument whole where it may leave the mesh or in its shape with
|
||||
‹path›, ‹address› or ‹withheld› and "Part shown", the fingerprint, and where the whole is read (the runner's
|
||||
‹path›, ‹address› or ‹withheld› and "Part shown" (whole when at most 2000 bytes and 40 lines, else the
|
||||
first 20 lines and 1200 bytes), the fingerprint, and where the whole is read (the runner's
|
||||
`approvals` on that node). Approve and Decline, both at approve; expiry 60 minutes; never a default. The call
|
||||
answers as an error: "Not run", with the ask's id and until when.
|
||||
answers as an error: "Not run", with the ask's id, that the call runs within 30 minutes of the approval, and
|
||||
when the ask expires.
|
||||
- **The same call again** runs once on Approve, read from the router's record, within 30 minutes of the choice,
|
||||
claimed in the node's own file (kept 48 hours); then `warranted` records the hand-act. Anything else is
|
||||
claimed in the node's own file (kept 48 hours, one writer per node); the runner judges the newest ask it keeps
|
||||
for the act, and after "already run", "expired" or "approved too long ago" the next identical call asks anew;
|
||||
then `warranted` records the hand-act. Anything else is
|
||||
refused and said: waiting, declined (not asked again for 10 minutes), expired, already run, or the router's
|
||||
refusal.
|
||||
- **Fail closed:** a secret's shape in an argument or more than 16 KiB of arguments, no operator channel, a
|
||||
fourth open ask, an unpublished ask, an unreadable router record, node file or mark: nothing runs.
|
||||
- **The controller** enforces the same mark on its own verbs, asking as `mesh-controller`.
|
||||
- **Marked first:** `node-login-shell.execute` on every node once the reads it carried have tools (issue 418),
|
||||
and `mesh-delivery.release`.
|
||||
- **Marked first:** `node-login-shell.execute` on every node once the reads it carried have tools (issue 418).
|
||||
`mesh-delivery.release` waits until a warrant the controller holds passes the mark of a verb it calls (issue
|
||||
417), so a Release on a condition is not asked twice.
|
||||
|
||||
### The hand-act
|
||||
|
||||
@@ -597,7 +603,7 @@ Each phase ends at its own *done when*. Owning repositories from [`repos.md`](..
|
||||
| **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; rehearsals: an approve and a destroy answered on the phone, with the hand-acts read |
|
||||
| **7 — A call that needs approval** (ADR 0286) | `needs-approval` in the manifest and the seat set, issued in the membership, withheld from a runner without `approval-mark/1` (controller); the act's digest in TypeScript beside Go, with shared vectors (shared library); the check, the ask, the runner's `approvals`, the node's used file and `warranted` (tool runner); the controller's own verbs; `execute` and `mesh-delivery.release` marked (catalogue, the controller's seat set) | mesh-controller, mesh-sdk, mesh-tools, mesh-catalog | a marked call on a node is asked on the phone, does nothing, runs once when made again after Approve, is refused the third time, and `hand-acts` shows the warrant |
|
||||
| **7 — A call that needs approval** (ADR 0286) | `needs-approval` in the manifest and the seat set, issued in the membership, withheld from a runner without `approval-mark/1` in its bus permissions (controller); the act's digest in TypeScript beside Go, with shared vectors (shared library); the check, the ask, the runner's `approvals`, the node's used file and `warranted` (tool runner); the controller's own verbs; `execute` marked (the controller's seat set) once issue 418's reads exist | mesh-controller, mesh-sdk, mesh-tools, mesh-catalog | a marked call on a node is asked on the phone, does nothing, runs once when made again after Approve, is refused the third time, and `hand-acts` shows the warrant |
|
||||
|
||||
**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
|
||||
|
||||
Reference in New Issue
Block a user