Answer round 3 of the domain review of the approval mark
mesh/delivery closed: a newer head of the same pull request
mesh/check pass de62fe58523a on c74546a16f78 | unit 43 run, 0 kept, 1 skipped | integration 43 run, 0 kept, 1 skipped | composition passed in 69s on 4…

The client's node prefix stays on its own keys, so the router's record is
still read where the router writes it; the remaining notes say where the
runner's version is read and what each limit costs.

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
2026-11-11 02:53:20 +01:00
parent bddf6ce95a
commit de62fe5852
@@ -81,7 +81,8 @@ file; a node where the file is readable beyond the operator's account is a findi
refused); or names in `needs-approval` one name that is both one of its tools and one of its events. A tool mark
is checked against `tools` where the manifest lists its tools; where only its bundle names them, the tool runner
checks each marked tool against the tools the bundle registers at load: a bundle whose marks name a tool it does not
register is not loaded, failing closed rather than serving unmarked what the manifest meant to mark, and that is its
register is not loaded, so no tool of that module is served on that node at all, failing closed rather than serving
unmarked what the manifest meant to mark, and that is its
finding `<node>.<module>.mark-unserved` (said as §16's), cleared when a bundle that serves it, or a manifest without
the mark, is loaded. Each refusal names the entry and the rule. *Why:* a mark
nothing enforces would be a call that runs unasked while saying it is guarded; ADR 0286 §43 had the controller
@@ -115,7 +116,10 @@ file; a node where the file is readable beyond the operator's account is a findi
subject of every module the runtime carries: `mesh.mod.<module>.tool.<tool>` and the same followed by `.*`; the
caller-named subject mesh-sdk's `process.Call` sends on first, `mesh.mod.<module>.call.<tool>.>`; and for a marked
verb `mesh.seat.<seat>.tool.<verb>`, the same followed by `.<node>`, and `mesh.seat.<seat>.call.<verb>.<node>.>`.
The bus's deny outranks its allow of `mesh.mod.<module>.tool.>` for each. Going back to an older tool runner on a
The bus's deny outranks its allow of `mesh.mod.<module>.tool.>` for each. The tool runner's version on a node is read from the
same assignment half revision, its entry for `node-tools` on that node (the module version placed there, design 47
G §175), against the version the node-engine's `running.<node>.node-tools` last said running (design 47 G §309);
readings that revision names from before that version ran are older. Going back to an older tool runner on a
node leaves the window until its readings update, in which the old deny or none stands; that window is accepted. `Permissions` gains `SubscribeDeny`, written into the user list as the server's
subscribe deny, as `PublishDeny` is for publishing. The withheld tools and verbs are named in the grants part's read
of that account (`mesh-grants.grants_user_list`, a field `withheld` with each subject and "its tool runner does not
@@ -153,8 +157,9 @@ file; a node where the file is readable beyond the operator's account is a findi
checked:* unit, two rows of §22's table.
10. **One ask, under the module's name.** Otherwise the runner asks through an `operatorchannelclient.Client` whose
`Module` is the marked module, whose `State` is the runner's state of §13, and whose new field `KeyPrefix`, which
the client in mesh-contracts gains and puts before every key it writes and reads (empty for every asker today), is
`<node>.`; unless an ask for the same act is
the client in mesh-contracts gains and puts before every key of its own `State` it writes and reads (empty for
every asker today), is `<node>.`; never before the router's record it reads through `Record` and `Where`, whose key
stays `<module>.<id>` in the seat state `asks`; unless an ask for the same act is
open there (§13's `act.` key), in which case it asks nothing new. The ask: `about` the act's digest; `who`
`operator`; `expires` 60 minutes after; no `on-expiry`; two options, `approve` (label Approve) and `decline` (label
Decline), both at level `approve`, each binding the act's digest; the headline "Run <tool> on <node>?",
@@ -195,8 +200,9 @@ file; a node where the file is readable beyond the operator's account is a findi
per-machine state on each account, and every module's per-machine keys keep their form; mesh-sdk's rebuild of it
rides in G's group. The cap is the bucket's, shared by every machine's keys. A write the bus refuses (the cap
reached, or any other) fails closed under §19 and is said in the answer; `mesh_approvals` reports the bucket's fill
against its cap. A run still unrecorded (§16) an hour before its key's 48 hours end is written in the runner's log
as an error naming the ask.
against its cap, saying that the fill and the cap are every machine's together. A run still unrecorded (§16) an hour before its key's 48 hours end is written in the runner's log
as an error naming the ask; this is written only while the runner runs, so a machine asleep through that hour keeps
only the `call-unanswered` history of §16, which is accepted.
*Why:* ADR 0286 §24, §30 kept the waiting call in the runner's record and claimed a warrant in the node's own file,
kept 48 hours, by one writer per node; the client built since keeps asks and marks a warrant acted on by
compare-and-set in a module's bus state (ADR 0259 §10, ADR 0627 §1), and a per-machine state (ADR 0595) is one
@@ -287,7 +293,11 @@ file; a node where the file is readable beyond the operator's account is a findi
gains `operator-channel` in `uses`. No other tool or verb is marked in this milestone. *Why:* the forge's own
refusal says these two acts are the operator's and waited for this mark (issue 417, 2026-10-28); a mark is on a
whole tool (ADR 0286 §1), so the acts move to a tool of their own, as ADR 0286 §48 splits a tool into an unmarked
and a marked form, and tightening a protection stays unasked; the operator, 2026-11-11: "Mark them in G". *How it
and a marked form, and tightening a protection stays unasked; the operator, 2026-11-11: "Mark them in G". The
principle: loosening a trunk's protection runs only on the operator's own warrant for that one act, never on a
session's word. Its bound: a process that reads the forge module's own credential speaks to the forge directly
and goes around it, the same known limit as issue 1966 note 193; the prepare reads that credential's mode and
owner on the forge's node with `<node>/node-reads.stat` and writes them in the milestone file. *How it
is checked:* the forge module's tool test: `set_full` refuses both acts naming the new tool; the new tool
performs each; and live, as the acceptance says.
@@ -299,7 +309,8 @@ file; a node where the file is readable beyond the operator's account is a findi
test that starts the runner against the real bus, with no store, with a fixture marked module: a call, the
operator's Approve written as the router's record, the call again, the run, the hand-act, `mesh_approvals`, and a
restart between the run and `warranted`'s answer. The client's `KeyPrefix` (§10) has a row in mesh-contracts'
client test: every key written and read carries it, and an empty prefix writes today's keys. *Why:* the operator's test budget (one whole test over many small
client test: every key of its own `State` written and read carries it, an empty prefix writes today's keys, and
with a prefix set `Where` still reads `<module>.<id>`. *Why:* the operator's test budget (one whole test over many small
ones). *How it is checked:* the check counts the module's tests against its budget.
23. **In G's delivery group, ordered by the module graph.** The members are pushed and checked in design 47 milestone
G's group, with design 34's milestone every-event. The orders are the module graph's: the indexer's manifest
@@ -322,7 +333,8 @@ file; a node where the file is readable beyond the operator's account is a findi
`operator-channel.asks`, and after the operator's Approve the same call runs once, a third identical call is refused
as already run, and `mesh-hand-acts.hand-acts` names the warranted act (§10, §12, §14 to §16, §21).
- **The forge's loosening is asked, and the protection is put back** (live, read by tool call): on a scratch repository
of the forge made for this acceptance, `acceptance-approval-mark`, with full protection on its trunk,
`acceptance-approval-mark`, created by the acceptance through the forge's `gitea_create_repo` and kept afterwards,
never deleted, with full protection set on its trunk by `gitea_branch_protection_set_full`,
`gitea_branch_protection_loosen` removing the trunk's protection answers "Not run" and asks on the phone; after the
Approve the same call runs once; then `gitea_branch_protection_set_full` sets the full protection again and
`gitea_branch_protection_get` reads it back as it was (§21).