Part of hq ADR 0272 (proposed, hq PR #243) and issue 343: the controller's terminal has no command (zsh: command not found: mesh-controller on the control-node, 2026-10-09).
What.
link.ServeCLI: the serving controller answers mesh.control.*.cli (queue group mesh-cli, so one of two controllers answers during a handover). Only node N's engine may publish mesh.control.N.cli, so the node is the bus server's fact; the account is the kernel's, as the engine read it. Each answer is cut to one bus message and says so.
judgeCLI (ADR 0272 §4): N's operator account (node record account) on the control-node (the one node the mesh-controller module is assigned to) is the terminal; the same account on any other node is an ordinary call; any other account, root included, an unknown node, a node with no operator account, is refused. Two or more control-nodes: nobody is the terminal.
The terminal runs the line as every verb's line runs (a fresh process of this binary, /proc/self/exe, so the running build even after an upgrade moved the file), with this process's environment and no MESH_VERB, even if the serving process carried one. An ordinary call first meets the generic command verb's refusals, now one function (refusedAsTheGenericCommand) for both routes, and runs with MESH_VERB=mesh-cli, so every terminal-only refusal applies with its reason. serve, api and board are never run. No stdin.
Caller recorded as <account> through mesh-cli on <node>. commandEnvironment is shared by runVerb and this.
The terminal-only refusals and the usage now name mesh-cli on the control-node.
Trust today (said plainly). On the control-node, agents still run as the operator account until ADR 0266 is switched on, so an agent there can reach the terminal through mesh-cli. That equals today's trust: those agents hold passwordless sudo and could run this binary as root with the unit's environment. It is no wider. Once ADR 0266 moves them to agent, agent is refused here. On every other node the operator account is never the terminal, because agents run as it. That boundary is ADR 0266's, not this PR's. No node names an agent account yet (ADR 0266 unbuilt), so phase 2 (another node as terminal) is not here.
Tests.TestMeshCLIIsTheTerminalOnlyForTheControlNodesOperator (the judge, seven cases), TestTheTerminalRunsWithoutAVerbAndAnOrdinaryCallNamesMeshCLI (runs the test binary as the command and reads the MESH_VERB/MESH_CALLER it got, with MESH_VERB leaked into the parent), TestAnOrdinaryCallMeetsTheCommandVerbsRefusals (settings set refused, servers never run, a refused line runs nothing), link tests for the field names (same list as mesh-host's), the subject, and the cut. merge-check.sh passes locally (race, full suite).
Merge order. Third: mesh-sdk, mesh-host, this, mesh-catalog. No SDK dependency here (the bus request is this repo's own link code).
Do not merge before the operator accepts ADR 0272.
Part of hq ADR 0272 (proposed, hq PR #243) and issue 343: the controller's terminal has no command (`zsh: command not found: mesh-controller` on the control-node, 2026-10-09).
**What.**
- `link.ServeCLI`: the serving controller answers `mesh.control.*.cli` (queue group `mesh-cli`, so one of two controllers answers during a handover). Only node N's engine may publish `mesh.control.N.cli`, so the node is the bus server's fact; the account is the kernel's, as the engine read it. Each answer is cut to one bus message and says so.
- `judgeCLI` (ADR 0272 §4): N's operator account (node record `account`) on the control-node (the one node the `mesh-controller` module is assigned to) is **the terminal**; the same account on any other node is an **ordinary call**; any other account, root included, an unknown node, a node with no operator account, is **refused**. Two or more control-nodes: nobody is the terminal.
- The terminal runs the line as every verb's line runs (a fresh process of this binary, `/proc/self/exe`, so the running build even after an upgrade moved the file), with this process's environment and **no `MESH_VERB`**, even if the serving process carried one. An ordinary call first meets the generic `command` verb's refusals, now one function (`refusedAsTheGenericCommand`) for both routes, and runs with `MESH_VERB=mesh-cli`, so every terminal-only refusal applies with its reason. `serve`, `api` and `board` are never run. No stdin.
- Caller recorded as `<account> through mesh-cli on <node>`. `commandEnvironment` is shared by `runVerb` and this.
- The terminal-only refusals and the usage now name `mesh-cli` on the control-node.
**Trust today (said plainly).** On the control-node, agents still run as the operator account until ADR 0266 is switched on, so an agent there can reach the terminal through mesh-cli. That equals today's trust: those agents hold passwordless sudo and could run this binary as root with the unit's environment. It is no wider. Once ADR 0266 moves them to `agent`, `agent` is refused here. On every other node the operator account is never the terminal, because agents run as it. That boundary is ADR 0266's, not this PR's. No node names an agent account yet (ADR 0266 unbuilt), so phase 2 (another node as terminal) is not here.
**Tests.** `TestMeshCLIIsTheTerminalOnlyForTheControlNodesOperator` (the judge, seven cases), `TestTheTerminalRunsWithoutAVerbAndAnOrdinaryCallNamesMeshCLI` (runs the test binary as the command and reads the MESH_VERB/MESH_CALLER it got, with MESH_VERB leaked into the parent), `TestAnOrdinaryCallMeetsTheCommandVerbsRefusals` (settings set refused, servers never run, a refused line runs nothing), link tests for the field names (same list as mesh-host's), the subject, and the cut. `merge-check.sh` passes locally (race, full suite).
**Merge order.** Third: mesh-sdk, mesh-host, this, mesh-catalog. No SDK dependency here (the bus request is this repo's own link code).
Do not merge before the operator accepts ADR 0272.
mesh/merge-gate pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step; every machine composes with the change as it…
The records send the operator to "the controller's terminal", and nothing
reached it (hq issue 343). The serving controller now answers each node's
mesh.control.<node>.cli, where only that node's engine may publish, with the
account the engine read from the kernel. A line from the control-node's
operator account runs as the terminal: a fresh process of this binary with
no MESH_VERB, whatever the serving process carries. The same account on any
other node, where agents may run as it, is an ordinary call: the generic
command verb's refusals (one function now, so the two routes cannot drift)
and MESH_VERB=mesh-cli, so a terminal-only change is refused with its
reason. Any other account, root included, runs nothing. Servers are never
run, and an answer over one bus message is cut and says so.
The terminal-only refusals and the usage now name mesh-cli on the
control-node as the way to the terminal.
build-agent keeps data (ADR 0233): what it holds is backed up before it moves
route-proxy provides route: its consumers are sent again after it
route-proxy keeps data (ADR 0233): what it holds is backed up before it moves
Transitions
2026-10-09 11:10 (new) → proposed (announced): novox/mesh-controller#176's head announced
2026-10-09 11:16 proposed → checked (checked): the verdict names this commit
2026-10-09 11:16 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
2026-10-09 11:48 ready → held (hold): something holds it for a person: its group's composed check did not pass for the heads that merged, or it merged and no walk was opened for it
2026-10-09 11:59 held → covered (covered): covered: a later merge that contains it was delivered: novox/mesh-controller@14ab2ddd9b (merged as 63e85b25 into main, walk plan-1791545949083465120): build-agent, mesh-controller, route-proxy
The commit's note under refs/notes/mesh-plan keeps every transition: git log --notes=mesh-plan.
<!-- mesh-delivery:view -->
**Delivery** `novox/mesh-controller@ea1d3ed96d3c` — **covered** since 2026-10-09T11:59:24Z
**Delivery plan** — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
- tier 0: mesh-controller
- tier 1: build-agent
- tier 2: route-proxy
- ace: receives build-agent, route-proxy
- g14: receives build-agent
- novox: receives mesh-controller, build-agent, route-proxy
- shanks: receives build-agent
- build-agent keeps data (ADR 0233): what it holds is backed up before it moves
- route-proxy provides route: its consumers are sent again after it
- route-proxy keeps data (ADR 0233): what it holds is backed up before it moves
**Transitions**
- 2026-10-09 11:10 (new) → proposed (announced): novox/mesh-controller#176's head announced
- 2026-10-09 11:16 proposed → checked (checked): the verdict names this commit
- 2026-10-09 11:16 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
- 2026-10-09 11:48 ready → held (hold): something holds it for a person: its group's composed check did not pass for the heads that merged, or it merged and no walk was opened for it
- 2026-10-09 11:59 held → covered (covered): covered: a later merge that contains it was delivered: novox/mesh-controller@14ab2ddd9b49 (merged as 63e85b25 into main, walk plan-1791545949083465120): build-agent, mesh-controller, route-proxy
The commit's note under `refs/notes/mesh-plan` keeps every transition: `git log --notes=mesh-plan`.
build-agent keeps data (ADR 0233): what it holds is backed up before it moves
route-proxy provides route: its consumers are sent again after it
route-proxy keeps data (ADR 0233): what it holds is backed up before it moves
Run by the build seat on ace as build-1791540771427111646 (builds --log build-1791540771427111646).
--- the gate: build-agent, mesh-controller, route-proxy
mesh-controller: ok, 52 tool(s); WARNING: controller stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 0
1 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-09T08:07:39Z says they run
composing every machine as the mesh is
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
composing every machine with the change
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
merge gate: PASS — every machine composes with the change as it did without (4 of 4 compose)
judged by controller development build against the facts of 2026-10-09T08:07:39Z
machines:
- a machine (f35): composes
- holds mesh-dns-resolver (idt): composes
- holds git, holds mesh-artifact-store, holds mesh-broker, holds mesh-catalog, holds mesh-delivery, holds mesh-dns-resolver, holds mesh-store, holds mesh-vault, holds npm-package-registry, the control node, the hub (ygcyr): composes
- a machine (yvbpsm): composes
a merge would rebuild 3 module(s) in 3 tier(s): build-agent, mesh-controller, route-proxy
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.032s
ok github.com/novox/mesh-controller/cmd/mesh-controller 173.381s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.013s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.019s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.016s
ok github.com/novox/mesh-controller/examples/route-proxy 1.113s
ok github.com/novox/mesh-controller/internal/artifacts 1.044s
ok github.com/novox/mesh-controller/internal/broker 2.529s
ok github.com/novox/mesh-controller/internal/builder 1.818s
ok github.com/novox/mesh-controller/internal/catalogue 4.441s
ok github.com/novox/mesh-controller/internal/conditions 2.416s
ok github.com/novox/mesh-controller/internal/envfile 1.058s
ok github.com/novox/mesh-controller/internal/facts 1.061s
ok github.com/novox/mesh-controller/internal/identity 4.148s
ok github.com/novox/mesh-controller/internal/inventory 71.241s
ok github.com/novox/mesh-controller/internal/lease 17.703s
ok github.com/novox/mesh-controller/internal/licences 3.795s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.056s
ok github.com/novox/mesh-controller/internal/link 50.715s
ok github.com/novox/mesh-controller/internal/lint 1.989s
ok github.com/novox/mesh-controller/internal/outward 1.085s
ok github.com/novox/mesh-controller/internal/overlay 1.071s
ok github.com/novox/mesh-controller/internal/secrets 1.456s
ok github.com/novox/mesh-controller/internal/store 3.309s
ok github.com/novox/mesh-controller/internal/testbus 1.239s
ok github.com/novox/mesh-controller/internal/token 1.015s
**Merge check** at `b1897a34`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller, route-proxy)
- `mesh/repo-check`: **PASS** — its merge-check.sh passed
**Delivery plan** — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
- tier 0: mesh-controller
- tier 1: build-agent
- tier 2: route-proxy
- ace: receives build-agent, route-proxy
- g14: receives build-agent
- novox: receives mesh-controller, build-agent, route-proxy
- shanks: receives build-agent
- build-agent keeps data (ADR 0233): what it holds is backed up before it moves
- route-proxy provides route: its consumers are sent again after it
- route-proxy keeps data (ADR 0233): what it holds is backed up before it moves
Run by the build seat on ace as `build-1791540771427111646` (`builds --log build-1791540771427111646`).
```
--- the gate: build-agent, mesh-controller, route-proxy
mesh-controller: ok, 52 tool(s); WARNING: controller stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 0
1 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-09T08:07:39Z says they run
composing every machine as the mesh is
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
composing every machine with the change
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
merge gate: PASS — every machine composes with the change as it did without (4 of 4 compose)
judged by controller development build against the facts of 2026-10-09T08:07:39Z
machines:
- a machine (f35): composes
- holds mesh-dns-resolver (idt): composes
- holds git, holds mesh-artifact-store, holds mesh-broker, holds mesh-catalog, holds mesh-delivery, holds mesh-dns-resolver, holds mesh-store, holds mesh-vault, holds npm-package-registry, the control node, the hub (ygcyr): composes
- a machine (yvbpsm): composes
a merge would rebuild 3 module(s) in 3 tier(s): build-agent, mesh-controller, route-proxy
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.032s
ok github.com/novox/mesh-controller/cmd/mesh-controller 173.381s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.013s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.019s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.016s
ok github.com/novox/mesh-controller/examples/route-proxy 1.113s
ok github.com/novox/mesh-controller/internal/artifacts 1.044s
ok github.com/novox/mesh-controller/internal/broker 2.529s
ok github.com/novox/mesh-controller/internal/builder 1.818s
ok github.com/novox/mesh-controller/internal/catalogue 4.441s
ok github.com/novox/mesh-controller/internal/conditions 2.416s
ok github.com/novox/mesh-controller/internal/envfile 1.058s
ok github.com/novox/mesh-controller/internal/facts 1.061s
ok github.com/novox/mesh-controller/internal/identity 4.148s
ok github.com/novox/mesh-controller/internal/inventory 71.241s
ok github.com/novox/mesh-controller/internal/lease 17.703s
ok github.com/novox/mesh-controller/internal/licences 3.795s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.056s
ok github.com/novox/mesh-controller/internal/link 50.715s
ok github.com/novox/mesh-controller/internal/lint 1.989s
ok github.com/novox/mesh-controller/internal/outward 1.085s
ok github.com/novox/mesh-controller/internal/overlay 1.071s
ok github.com/novox/mesh-controller/internal/secrets 1.456s
ok github.com/novox/mesh-controller/internal/store 3.309s
ok github.com/novox/mesh-controller/internal/testbus 1.239s
ok github.com/novox/mesh-controller/internal/token 1.015s
```
mesh/merge-gate pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step; every machine composes with the change as it…
- A line ran past the bus's one-minute window for an answer and its answer
was refused; mesh-cli then said nothing ran of a line that had. Every
line is now a call (calls.go): answered within AnswerWithin that it is
running, with its call, and followed by the same account on the same
node until it ends. Its record keeps the command word only, and its
answer stays in the memory of the controller that ran it — never on the
bus, never in `calls`, which answers anyone who may call the seat. Each
line is said in the journal with its call, who asked where, and how.
- Lines running at once are bounded (8); one over is answered busy.
- An ordinary `settings` line is composed as the settings verb composes
its own and meets that verb's refusals, the terminal-only keys among
them, instead of the generic command's blanket refusal.
- The controller's module is assigned and unassigned at the terminal only:
where it runs is the control-node, whose operator is the terminal.
- mesh.control.*.cli is in the writers table as the machine's own.
build-agent keeps data (ADR 0233): what it holds is backed up before it moves
route-proxy provides route: its consumers are sent again after it
route-proxy keeps data (ADR 0233): what it holds is backed up before it moves
Run by the build seat on shanks as build-1791542967107494234 (builds --log build-1791542967107494234).
--- the gate: build-agent, mesh-controller, route-proxy
mesh-controller: ok, 52 tool(s); WARNING: controller stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 0
1 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-09T08:07:39Z says they run
composing every machine as the mesh is
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
composing every machine with the change
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
merge gate: PASS — every machine composes with the change as it did without (4 of 4 compose)
judged by controller development build against the facts of 2026-10-09T08:07:39Z
machines:
- a machine (f35): composes
- holds mesh-dns-resolver (idt): composes
- holds git, holds mesh-artifact-store, holds mesh-broker, holds mesh-catalog, holds mesh-delivery, holds mesh-dns-resolver, holds mesh-store, holds mesh-vault, holds npm-package-registry, the control node, the hub (ygcyr): composes
- a machine (yvbpsm): composes
a merge would rebuild 3 module(s) in 3 tier(s): build-agent, mesh-controller, route-proxy
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.038s
ok github.com/novox/mesh-controller/cmd/mesh-controller 202.568s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.037s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.065s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.048s
ok github.com/novox/mesh-controller/examples/route-proxy 1.232s
ok github.com/novox/mesh-controller/internal/artifacts 1.085s
ok github.com/novox/mesh-controller/internal/broker 2.775s
ok github.com/novox/mesh-controller/internal/builder 2.022s
ok github.com/novox/mesh-controller/internal/catalogue 4.992s
ok github.com/novox/mesh-controller/internal/conditions 2.587s
ok github.com/novox/mesh-controller/internal/envfile 1.066s
ok github.com/novox/mesh-controller/internal/facts 1.069s
ok github.com/novox/mesh-controller/internal/identity 4.809s
ok github.com/novox/mesh-controller/internal/inventory 86.654s
ok github.com/novox/mesh-controller/internal/lease 17.689s
ok github.com/novox/mesh-controller/internal/licences 4.375s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.059s
ok github.com/novox/mesh-controller/internal/link 53.729s
ok github.com/novox/mesh-controller/internal/lint 2.217s
ok github.com/novox/mesh-controller/internal/outward 1.093s
ok github.com/novox/mesh-controller/internal/overlay 1.072s
ok github.com/novox/mesh-controller/internal/secrets 1.549s
ok github.com/novox/mesh-controller/internal/store 3.549s
ok github.com/novox/mesh-controller/internal/testbus 1.246s
ok github.com/novox/mesh-controller/internal/token 1.014s
**Merge check** at `0c47f485`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller, route-proxy)
- `mesh/repo-check`: **PASS** — its merge-check.sh passed
**Delivery plan** — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
- tier 0: mesh-controller
- tier 1: build-agent
- tier 2: route-proxy
- ace: receives build-agent, route-proxy
- g14: receives build-agent
- novox: receives mesh-controller, build-agent, route-proxy
- shanks: receives build-agent
- build-agent keeps data (ADR 0233): what it holds is backed up before it moves
- route-proxy provides route: its consumers are sent again after it
- route-proxy keeps data (ADR 0233): what it holds is backed up before it moves
Run by the build seat on shanks as `build-1791542967107494234` (`builds --log build-1791542967107494234`).
```
--- the gate: build-agent, mesh-controller, route-proxy
mesh-controller: ok, 52 tool(s); WARNING: controller stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 0
1 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-09T08:07:39Z says they run
composing every machine as the mesh is
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
composing every machine with the change
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
merge gate: PASS — every machine composes with the change as it did without (4 of 4 compose)
judged by controller development build against the facts of 2026-10-09T08:07:39Z
machines:
- a machine (f35): composes
- holds mesh-dns-resolver (idt): composes
- holds git, holds mesh-artifact-store, holds mesh-broker, holds mesh-catalog, holds mesh-delivery, holds mesh-dns-resolver, holds mesh-store, holds mesh-vault, holds npm-package-registry, the control node, the hub (ygcyr): composes
- a machine (yvbpsm): composes
a merge would rebuild 3 module(s) in 3 tier(s): build-agent, mesh-controller, route-proxy
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.038s
ok github.com/novox/mesh-controller/cmd/mesh-controller 202.568s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.037s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.065s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.048s
ok github.com/novox/mesh-controller/examples/route-proxy 1.232s
ok github.com/novox/mesh-controller/internal/artifacts 1.085s
ok github.com/novox/mesh-controller/internal/broker 2.775s
ok github.com/novox/mesh-controller/internal/builder 2.022s
ok github.com/novox/mesh-controller/internal/catalogue 4.992s
ok github.com/novox/mesh-controller/internal/conditions 2.587s
ok github.com/novox/mesh-controller/internal/envfile 1.066s
ok github.com/novox/mesh-controller/internal/facts 1.069s
ok github.com/novox/mesh-controller/internal/identity 4.809s
ok github.com/novox/mesh-controller/internal/inventory 86.654s
ok github.com/novox/mesh-controller/internal/lease 17.689s
ok github.com/novox/mesh-controller/internal/licences 4.375s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.059s
ok github.com/novox/mesh-controller/internal/link 53.729s
ok github.com/novox/mesh-controller/internal/lint 2.217s
ok github.com/novox/mesh-controller/internal/outward 1.093s
ok github.com/novox/mesh-controller/internal/overlay 1.072s
ok github.com/novox/mesh-controller/internal/secrets 1.549s
ok github.com/novox/mesh-controller/internal/store 3.549s
ok github.com/novox/mesh-controller/internal/testbus 1.246s
ok github.com/novox/mesh-controller/internal/token 1.014s
```
mesh/merge-gate pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step; every machine composes with the change as it…
mesh/delivery covered: a later merge that contains it was delivered: novox/mesh-controller@14ab2ddd9b49 (merged as 63e85b25 into main, walk plan-17915459…
- The generic command verb only reads now (commandReads) and terminal-only
commands are refused through any verb (terminalOnly). mesh-cli's
ordinary line made neither check: `node account`, `token issue` and
`secret export` from another node would have run. It now meets both, in
the one function the command verb shares.
- The serving controller marks itself and its children never the terminal
(ADR 0266); a line mesh-cli runs as the terminal drops that mark and
carries MESH_CLI_TERMINAL, so it reads as the terminal it is.
- Two withholding tests searched the answer's text while JSON writes bytes
as base64, so they held nothing. They search both now, each proved by
disabling what it guards (Shown, the bus withholding, `calls` via Get).
- The control-node refusal is tested through the assign and unassign acts.
build-agent keeps data (ADR 0233): what it holds is backed up before it moves
route-proxy provides route: its consumers are sent again after it
route-proxy keeps data (ADR 0233): what it holds is backed up before it moves
Run by the build seat on shanks as build-1791544213706660746 (builds --log build-1791544213706660746).
--- the gate: build-agent, mesh-controller, route-proxy
mesh-controller: ok, 52 tool(s); WARNING: controller stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 0
1 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-09T11:09:37Z says they run
composing every machine as the mesh is
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
composing every machine with the change
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
merge gate: PASS — every machine composes with the change as it did without (4 of 4 compose)
judged by controller development build against the facts of 2026-10-09T11:09:37Z
machines:
- a machine (f35): composes
- holds mesh-dns-resolver (idt): composes
- holds git, holds mesh-artifact-store, holds mesh-broker, holds mesh-catalog, holds mesh-delivery, holds mesh-dns-resolver, holds mesh-store, holds mesh-vault, holds npm-package-registry, the control node, the hub (ygcyr): composes
- a machine (yvbpsm): composes
a merge would rebuild 3 module(s) in 3 tier(s): build-agent, mesh-controller, route-proxy
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.034s
ok github.com/novox/mesh-controller/cmd/mesh-controller 208.388s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.055s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.063s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.048s
ok github.com/novox/mesh-controller/examples/route-proxy 1.283s
ok github.com/novox/mesh-controller/internal/artifacts 1.093s
ok github.com/novox/mesh-controller/internal/broker 2.773s
ok github.com/novox/mesh-controller/internal/builder 2.003s
ok github.com/novox/mesh-controller/internal/catalogue 4.943s
ok github.com/novox/mesh-controller/internal/conditions 2.577s
ok github.com/novox/mesh-controller/internal/envfile 1.056s
ok github.com/novox/mesh-controller/internal/facts 1.064s
ok github.com/novox/mesh-controller/internal/identity 4.825s
ok github.com/novox/mesh-controller/internal/inventory 85.867s
ok github.com/novox/mesh-controller/internal/lease 17.707s
ok github.com/novox/mesh-controller/internal/licences 4.400s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.034s
ok github.com/novox/mesh-controller/internal/link 53.669s
ok github.com/novox/mesh-controller/internal/lint 2.207s
ok github.com/novox/mesh-controller/internal/outward 1.090s
ok github.com/novox/mesh-controller/internal/overlay 1.080s
ok github.com/novox/mesh-controller/internal/secrets 1.547s
ok github.com/novox/mesh-controller/internal/store 3.556s
ok github.com/novox/mesh-controller/internal/testbus 1.265s
ok github.com/novox/mesh-controller/internal/token 1.014s
**Merge check** at `ea1d3ed9`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller, route-proxy)
- `mesh/repo-check`: **PASS** — its merge-check.sh passed
**Delivery plan** — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
- tier 0: mesh-controller
- tier 1: build-agent
- tier 2: route-proxy
- ace: receives build-agent, route-proxy
- g14: receives build-agent
- novox: receives mesh-controller, build-agent, route-proxy
- shanks: receives build-agent
- build-agent keeps data (ADR 0233): what it holds is backed up before it moves
- route-proxy provides route: its consumers are sent again after it
- route-proxy keeps data (ADR 0233): what it holds is backed up before it moves
Run by the build seat on shanks as `build-1791544213706660746` (`builds --log build-1791544213706660746`).
```
--- the gate: build-agent, mesh-controller, route-proxy
mesh-controller: ok, 52 tool(s); WARNING: controller stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 0
1 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-09T11:09:37Z says they run
composing every machine as the mesh is
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
composing every machine with the change
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
the bus's user list leaves out 5 user(s) the mesh has minted no credential for: controller, node.f35, node.idt, node.ygcyr, node.yvbpsm. Each is a user that cannot connect until one is issued
merge gate: PASS — every machine composes with the change as it did without (4 of 4 compose)
judged by controller development build against the facts of 2026-10-09T11:09:37Z
machines:
- a machine (f35): composes
- holds mesh-dns-resolver (idt): composes
- holds git, holds mesh-artifact-store, holds mesh-broker, holds mesh-catalog, holds mesh-delivery, holds mesh-dns-resolver, holds mesh-store, holds mesh-vault, holds npm-package-registry, the control node, the hub (ygcyr): composes
- a machine (yvbpsm): composes
a merge would rebuild 3 module(s) in 3 tier(s): build-agent, mesh-controller, route-proxy
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-controller/cmd/mesh-builder 1.034s
ok github.com/novox/mesh-controller/cmd/mesh-controller 208.388s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.055s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.063s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.048s
ok github.com/novox/mesh-controller/examples/route-proxy 1.283s
ok github.com/novox/mesh-controller/internal/artifacts 1.093s
ok github.com/novox/mesh-controller/internal/broker 2.773s
ok github.com/novox/mesh-controller/internal/builder 2.003s
ok github.com/novox/mesh-controller/internal/catalogue 4.943s
ok github.com/novox/mesh-controller/internal/conditions 2.577s
ok github.com/novox/mesh-controller/internal/envfile 1.056s
ok github.com/novox/mesh-controller/internal/facts 1.064s
ok github.com/novox/mesh-controller/internal/identity 4.825s
ok github.com/novox/mesh-controller/internal/inventory 85.867s
ok github.com/novox/mesh-controller/internal/lease 17.707s
ok github.com/novox/mesh-controller/internal/licences 4.400s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.034s
ok github.com/novox/mesh-controller/internal/link 53.669s
ok github.com/novox/mesh-controller/internal/lint 2.207s
ok github.com/novox/mesh-controller/internal/outward 1.090s
ok github.com/novox/mesh-controller/internal/overlay 1.080s
ok github.com/novox/mesh-controller/internal/secrets 1.547s
ok github.com/novox/mesh-controller/internal/store 3.556s
ok github.com/novox/mesh-controller/internal/testbus 1.265s
ok github.com/novox/mesh-controller/internal/token 1.014s
```
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Part of hq ADR 0272 (proposed, hq PR #243) and issue 343: the controller's terminal has no command (
zsh: command not found: mesh-controlleron the control-node, 2026-10-09).What.
link.ServeCLI: the serving controller answersmesh.control.*.cli(queue groupmesh-cli, so one of two controllers answers during a handover). Only node N's engine may publishmesh.control.N.cli, so the node is the bus server's fact; the account is the kernel's, as the engine read it. Each answer is cut to one bus message and says so.judgeCLI(ADR 0272 §4): N's operator account (node recordaccount) on the control-node (the one node themesh-controllermodule is assigned to) is the terminal; the same account on any other node is an ordinary call; any other account, root included, an unknown node, a node with no operator account, is refused. Two or more control-nodes: nobody is the terminal./proc/self/exe, so the running build even after an upgrade moved the file), with this process's environment and noMESH_VERB, even if the serving process carried one. An ordinary call first meets the genericcommandverb's refusals, now one function (refusedAsTheGenericCommand) for both routes, and runs withMESH_VERB=mesh-cli, so every terminal-only refusal applies with its reason.serve,apiandboardare never run. No stdin.<account> through mesh-cli on <node>.commandEnvironmentis shared byrunVerband this.mesh-clion the control-node.Trust today (said plainly). On the control-node, agents still run as the operator account until ADR 0266 is switched on, so an agent there can reach the terminal through mesh-cli. That equals today's trust: those agents hold passwordless sudo and could run this binary as root with the unit's environment. It is no wider. Once ADR 0266 moves them to
agent,agentis refused here. On every other node the operator account is never the terminal, because agents run as it. That boundary is ADR 0266's, not this PR's. No node names an agent account yet (ADR 0266 unbuilt), so phase 2 (another node as terminal) is not here.Tests.
TestMeshCLIIsTheTerminalOnlyForTheControlNodesOperator(the judge, seven cases),TestTheTerminalRunsWithoutAVerbAndAnOrdinaryCallNamesMeshCLI(runs the test binary as the command and reads the MESH_VERB/MESH_CALLER it got, with MESH_VERB leaked into the parent),TestAnOrdinaryCallMeetsTheCommandVerbsRefusals(settings set refused, servers never run, a refused line runs nothing), link tests for the field names (same list as mesh-host's), the subject, and the cut.merge-check.shpasses locally (race, full suite).Merge order. Third: mesh-sdk, mesh-host, this, mesh-catalog. No SDK dependency here (the bus request is this repo's own link code).
Do not merge before the operator accepts ADR 0272.
Delivery
novox/mesh-controller@ea1d3ed96d3c— covered since 2026-10-09T11:59:24ZDelivery plan — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
Transitions
63e85b25into main, walk plan-1791545949083465120): build-agent, mesh-controller, route-proxyThe commit's note under
refs/notes/mesh-plankeeps every transition:git log --notes=mesh-plan.Merge check at
b1897a34mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller, route-proxy)mesh/repo-check: PASS — its merge-check.sh passedDelivery plan — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
Run by the build seat on ace as
build-1791540771427111646(builds --log build-1791540771427111646).Merge check at
0c47f485mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller, route-proxy)mesh/repo-check: PASS — its merge-check.sh passedDelivery plan — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
Run by the build seat on shanks as
build-1791542967107494234(builds --log build-1791542967107494234).Merge check at
ea1d3ed9mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller, route-proxy)mesh/repo-check: PASS — its merge-check.sh passedDelivery plan — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
Run by the build seat on shanks as
build-1791544213706660746(builds --log build-1791544213706660746).