Merge after #164 — built on feat/a-node-names-the-account-its-agents-run-as (it changes #164's probe DA). Until #164 merges this diff also shows #164's commits; this PR's change is the last commit.
The symptom
After every node-engine restart, the account verdict says not judged yet (search running) until the engine's first search for setuid programs ends (mesh-host #61: SetuidNotJudged{Pending}, state unknown). Probe DA read that as any other not-judged verdict and raised the urgentagent-can-become-root on every restart.
The change
searchStillRunning: DA raises nothing while the only thing keeping the account from being judged is that first search, and only while the verdict's since is within link.RootSearchBound (15 minutes, mesh-host's SearchBound) plus one statement period (5 minutes). The account is still not confined (agentConfined, which ADR 0259's router reads, is unchanged) and node show still says not judged. It is loud again — urgent — when the search failed or ran out its bound (not judged (search incomplete)), when it runs past the window, when a way to root is found, when any other verdict is unknown, or when the statement is stale.
link.ReasonRootPending must stay equal to mesh-host's accounts.ReasonPending (not judged yet (search running)).
Test
TestASearchStillRunningAfterARestartIsNotUrgent: a search two minutes in raises nothing (fails before this change: urgent condition raised); past the window, an incomplete search, and a way to root found while it runs are each urgent.
merge-check.sh run on this head (which contains current main).
**Merge after #164** — built on `feat/a-node-names-the-account-its-agents-run-as` (it changes #164's probe DA). Until #164 merges this diff also shows #164's commits; this PR's change is the last commit.
## The symptom
After every node-engine restart, the account verdict says `not judged yet (search running)` until the engine's first search for setuid programs ends (mesh-host #61: `SetuidNotJudged{Pending}`, state unknown). Probe DA read that as any other not-judged verdict and raised the **urgent** `agent-can-become-root` on every restart.
## The change
`searchStillRunning`: DA raises nothing while the only thing keeping the account from being judged is that first search, and only while the verdict's `since` is within `link.RootSearchBound` (15 minutes, mesh-host's `SearchBound`) plus one statement period (5 minutes). The account is still **not confined** (`agentConfined`, which ADR 0259's router reads, is unchanged) and `node show` still says not judged. It is loud again — urgent — when the search failed or ran out its bound (`not judged (search incomplete)`), when it runs past the window, when a way to root is found, when any other verdict is unknown, or when the statement is stale.
`link.ReasonRootPending` must stay equal to mesh-host's `accounts.ReasonPending` (`not judged yet (search running)`).
## Test
`TestASearchStillRunningAfterARestartIsNotUrgent`: a search two minutes in raises nothing (fails before this change: urgent condition raised); past the window, an incomplete search, and a way to root found while it runs are each urgent.
`merge-check.sh` run on this head (which contains current main).
On the control node every agent ran as the operator's account, which has
passwordless sudo, so an agent could become root without a person (hq ADR
0266). A node now names an agent account at the controller's terminal only;
the agent's module declares it never to become root, the node-engine judges
that, and the self-check (DA) raises agent-can-become-root while it does not
hold, so ADR 0259's router can rest on it.
The generic command verb ran node account and node agent-account, so an agent
could name itself the operator account and have the next send grant it root
(hq ADR 0266 review). Refuse every node subcommand but list and show through
any verb; refuse the operator account as the agent account in both
directions and well-known service accounts as an agent account; and count a
verdict heard more than 15 minutes ago as not judged, so stopping the
node-engine cannot freeze a healthy one. Re-pin mesh-host to its review head.
Review found a chain through the command verb: set the operator's key to one
the caller holds, rotate secrets so they are sealed to it too, read the sealed
copies, open them. Whoever may call a verb includes agents (hq ADR 0266), so
command now runs an allow list of reading forms, and operator, identity,
token, broker, api, licence and every secret command but rotate are refused
through any verb.
A flag before the subcommand (plans --json go <id>) still acts, so the
generic command verb judges every word of a plans line, retry included
(hq ADR 0266). The rest of this change, places and accesses at the
terminal and one line per setting, is issue 339's on main (#168, #170,
#172), which now does it for every process a verb runs; this branch's
--through-verb flag and its copy of those rules go.
The engine's pull request now keeps main's placement guard (issue 339) and adds
only the agent-home rule; the pin follows it so the two are judged together
(hq ADR 0266). Move it to the engine's merged commit before this merges.
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…
node agent-account <node> <account> [home] stored a home that nothing used: the
account was created at /home/<account> while its files went to the named home
(hq ADR 0266). The engine reads a user's home only when it creates the account,
so an existing one is never moved.
Deliverynovox/mesh-controller@2e1a9abbf70d — failed since 2026-10-09T11:09:58Z
Covered: covered after its failure: a later walk that contains it was delivered: plan-1791658180097457523 (novox/mesh-controller at a2a671ad into main, done, contains its merge 5438d7ff)
Delivery plan — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
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
Machines
mesh-controller on novox: rolled-back — not healthy within 10m0s of its apply: novox as a whole: raised since it was sent: machine.novox.network — novox's network is not healthy: 1 of its 2 resolvers do not answer as the mesh's do; ace cannot reach it
Transitions
2026-10-09 10:43 (new) → proposed (announced): novox/mesh-controller#175's head announced
2026-10-09 10:49 proposed → checked (checked): the verdict names this commit
2026-10-09 10:49 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
2026-10-09 10:56 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
2026-10-09 10:56 published → delivering (go): its walk started: let go by this owner in its group's order, by a person, or on the controller's own path
2026-10-09 11:09 delivering → failed (failed): its walk failed: a gate on a first machine (what it carried put back), a build, a machine
The commit's note under refs/notes/mesh-plan keeps every transition: git log --notes=mesh-plan.
<!-- mesh-delivery:view -->
**Delivery** `novox/mesh-controller@2e1a9abbf70d` — **failed** since 2026-10-09T11:09:58Z
**Covered**: covered after its failure: a later walk that contains it was delivered: plan-1791658180097457523 (novox/mesh-controller at a2a671ad into main, done, contains its merge 5438d7ff)
**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
**Machines**
- mesh-controller on novox: rolled-back — not healthy within 10m0s of its apply: novox as a whole: raised since it was sent: machine.novox.network — novox's network is not healthy: 1 of its 2 resolvers do not answer as the mesh's do; ace cannot reach it
**Transitions**
- 2026-10-09 10:43 (new) → proposed (announced): novox/mesh-controller#175's head announced
- 2026-10-09 10:49 proposed → checked (checked): the verdict names this commit
- 2026-10-09 10:49 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
- 2026-10-09 10:56 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
- 2026-10-09 10:56 published → delivering (go): its walk started: let go by this owner in its group's order, by a person, or on the controller's own path
- 2026-10-09 11:09 delivering → failed (failed): its walk failed: a gate on a first machine (what it carried put back), a build, a machine
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-1791539341499746904 (builds --log build-1791539341499746904).
--- 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.033s
ok github.com/novox/mesh-controller/cmd/mesh-controller 172.828s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.029s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.040s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.036s
ok github.com/novox/mesh-controller/examples/route-proxy 1.131s
ok github.com/novox/mesh-controller/internal/artifacts 1.065s
ok github.com/novox/mesh-controller/internal/broker 2.559s
ok github.com/novox/mesh-controller/internal/builder 1.824s
ok github.com/novox/mesh-controller/internal/catalogue 4.348s
ok github.com/novox/mesh-controller/internal/conditions 2.411s
ok github.com/novox/mesh-controller/internal/envfile 1.035s
ok github.com/novox/mesh-controller/internal/facts 1.037s
ok github.com/novox/mesh-controller/internal/identity 4.122s
ok github.com/novox/mesh-controller/internal/inventory 71.780s
ok github.com/novox/mesh-controller/internal/lease 17.668s
ok github.com/novox/mesh-controller/internal/licences 3.757s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.030s
ok github.com/novox/mesh-controller/internal/link 50.987s
ok github.com/novox/mesh-controller/internal/lint 1.979s
ok github.com/novox/mesh-controller/internal/outward 1.059s
ok github.com/novox/mesh-controller/internal/overlay 1.067s
ok github.com/novox/mesh-controller/internal/secrets 1.439s
ok github.com/novox/mesh-controller/internal/store 3.255s
ok github.com/novox/mesh-controller/internal/testbus 1.236s
ok github.com/novox/mesh-controller/internal/token 1.017s
**Merge check** at `6751f75e`
- `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-1791539341499746904` (`builds --log build-1791539341499746904`).
```
--- 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.033s
ok github.com/novox/mesh-controller/cmd/mesh-controller 172.828s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.029s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.040s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.036s
ok github.com/novox/mesh-controller/examples/route-proxy 1.131s
ok github.com/novox/mesh-controller/internal/artifacts 1.065s
ok github.com/novox/mesh-controller/internal/broker 2.559s
ok github.com/novox/mesh-controller/internal/builder 1.824s
ok github.com/novox/mesh-controller/internal/catalogue 4.348s
ok github.com/novox/mesh-controller/internal/conditions 2.411s
ok github.com/novox/mesh-controller/internal/envfile 1.035s
ok github.com/novox/mesh-controller/internal/facts 1.037s
ok github.com/novox/mesh-controller/internal/identity 4.122s
ok github.com/novox/mesh-controller/internal/inventory 71.780s
ok github.com/novox/mesh-controller/internal/lease 17.668s
ok github.com/novox/mesh-controller/internal/licences 3.757s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.030s
ok github.com/novox/mesh-controller/internal/link 50.987s
ok github.com/novox/mesh-controller/internal/lint 1.979s
ok github.com/novox/mesh-controller/internal/outward 1.059s
ok github.com/novox/mesh-controller/internal/overlay 1.067s
ok github.com/novox/mesh-controller/internal/secrets 1.439s
ok github.com/novox/mesh-controller/internal/store 3.255s
ok github.com/novox/mesh-controller/internal/testbus 1.236s
ok github.com/novox/mesh-controller/internal/token 1.017s
```
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-host #61 dropped the two-minute limit inside the search's 15-minute
bound, asks pacman once, and calls a walk with errors incomplete; the pin
follows it so the two are judged together (hq ADR 0266). Move it to the
engine's merged commit before this merges.
Follow-up of the review (commit 9632278). This branch is now stacked on #174. It adds migration 0085, and the store refuses a lower-numbered migration after a higher one has run. Merge order: #164, then #174, then this.
The quiet no longer reads the node-engine's since, which restarts with the engine. The controller keeps node.agent_root_pending_since: set the first time it sees the verdict waiting for the search, kept across engine and controller restarts, cleared at the next complete verdict (healthy, or a way to root). The condition is raised once searchQuietFor has passed since that time.
searchQuietFor is the node-engine's own bound. The test pins searchQuietFor == rootsearch.Bound. The 5-minute grace is gone. link.RootSearchBound and link.ReasonRootPending are now mesh-host's rootsearch.Bound and rootsearch.ReasonPending, vendored from mesh-host #61's head.
Test: TestASearchStillRunningAfterARestartIsNotUrgent simulates a restart loop, where every statement carries a fresh engine since and the controller first saw the waiting past the bound. It is urgent; before this change the condition stayed quiet.
Follow-up of the review (commit 9632278). **This branch is now stacked on #174.** It adds migration 0085, and the store refuses a lower-numbered migration after a higher one has run. **Merge order: #164, then #174, then this.**
- The quiet no longer reads the node-engine's `since`, which restarts with the engine. The controller keeps `node.agent_root_pending_since`: set the first time it sees the verdict waiting for the search, kept across engine and controller restarts, cleared at the next complete verdict (healthy, or a way to root). The condition is raised once `searchQuietFor` has passed since that time.
- `searchQuietFor` is the node-engine's own bound. The test pins `searchQuietFor == rootsearch.Bound`. The 5-minute grace is gone. `link.RootSearchBound` and `link.ReasonRootPending` are now mesh-host's `rootsearch.Bound` and `rootsearch.ReasonPending`, vendored from mesh-host #61's head.
Test: `TestASearchStillRunningAfterARestartIsNotUrgent` simulates a restart loop, where every statement carries a fresh engine `since` and the controller first saw the waiting past the bound. It is urgent; before this change the condition stayed quiet.
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-1791541655299796289 (builds --log build-1791541655299796289).
--- 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.033s
ok github.com/novox/mesh-controller/cmd/mesh-controller 205.260s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.049s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.058s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.052s
ok github.com/novox/mesh-controller/examples/route-proxy 1.245s
ok github.com/novox/mesh-controller/internal/artifacts 1.087s
ok github.com/novox/mesh-controller/internal/broker 2.755s
ok github.com/novox/mesh-controller/internal/builder 1.946s
ok github.com/novox/mesh-controller/internal/catalogue 4.878s
ok github.com/novox/mesh-controller/internal/conditions 2.534s
ok github.com/novox/mesh-controller/internal/envfile 1.047s
ok github.com/novox/mesh-controller/internal/facts 1.060s
ok github.com/novox/mesh-controller/internal/identity 4.773s
ok github.com/novox/mesh-controller/internal/inventory 86.638s
ok github.com/novox/mesh-controller/internal/lease 17.705s
ok github.com/novox/mesh-controller/internal/licences 4.344s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.051s
ok github.com/novox/mesh-controller/internal/link 53.492s
ok github.com/novox/mesh-controller/internal/lint 2.184s
ok github.com/novox/mesh-controller/internal/outward 1.094s
ok github.com/novox/mesh-controller/internal/overlay 1.062s
ok github.com/novox/mesh-controller/internal/secrets 1.542s
ok github.com/novox/mesh-controller/internal/store 3.462s
ok github.com/novox/mesh-controller/internal/testbus 1.241s
ok github.com/novox/mesh-controller/internal/token 1.014s
**Merge check** at `9632278e`
- `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-1791541655299796289` (`builds --log build-1791541655299796289`).
```
--- 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.033s
ok github.com/novox/mesh-controller/cmd/mesh-controller 205.260s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.049s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.058s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.052s
ok github.com/novox/mesh-controller/examples/route-proxy 1.245s
ok github.com/novox/mesh-controller/internal/artifacts 1.087s
ok github.com/novox/mesh-controller/internal/broker 2.755s
ok github.com/novox/mesh-controller/internal/builder 1.946s
ok github.com/novox/mesh-controller/internal/catalogue 4.878s
ok github.com/novox/mesh-controller/internal/conditions 2.534s
ok github.com/novox/mesh-controller/internal/envfile 1.047s
ok github.com/novox/mesh-controller/internal/facts 1.060s
ok github.com/novox/mesh-controller/internal/identity 4.773s
ok github.com/novox/mesh-controller/internal/inventory 86.638s
ok github.com/novox/mesh-controller/internal/lease 17.705s
ok github.com/novox/mesh-controller/internal/licences 4.344s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.051s
ok github.com/novox/mesh-controller/internal/link 53.492s
ok github.com/novox/mesh-controller/internal/lint 2.184s
ok github.com/novox/mesh-controller/internal/outward 1.094s
ok github.com/novox/mesh-controller/internal/overlay 1.062s
ok github.com/novox/mesh-controller/internal/secrets 1.542s
ok github.com/novox/mesh-controller/internal/store 3.462s
ok github.com/novox/mesh-controller/internal/testbus 1.241s
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…
Only the engine's own test changed; the pin follows the head so the two are
judged together (hq ADR 0266). Move it to the engine's merged commit before
this merges.
An agent could make a repository of its own, or fork one the mesh builds
from, commit a module.json naming sudo or mesh-host, and ask the build verb
for it: the outcome was registered under that name, and the next push made
whoever wrote it root on every node (novox/hq ADR 0266 §7, the review of
2026-10-09). The trunk rule checked the trunk of the repository built, which
was the agent's.
The take-in, which every outcome reaches whichever verb asked it, now
registers a module only from its registered repository, and a new module only
from a repository the catalogue already builds from (a merge adding one);
anything else only when the build request was kept as asked at the
controller's terminal (migration 0084). Through a verb, a build of a
repository the catalogue builds nothing from is not asked at all.
A build refused for its repository is still recorded, and a fork carries the
commit the module was registered at: the rollback's search for the previous
build would have found it and registered it by the back door.
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@eca6390d6fe4 (merged as 33dc85d8 into main, walk plan-17915444…
A source repository's name is not its identity, and a trunk anyone may push
to makes the trunk rule mean nothing (the review of 2026-10-09). Through any
verb a module now registers only from a repository on the mesh's forge whose
trunk refuses direct pushes, requires a status and lets no administrator
merge past one, asked of the forge's own tools; and only from the repository
by the forge's id, recorded at registration (migration 0084), so one deleted
and made again under the name is refused. The serving controller marks its
environment, so nothing it runs or starts reads as the terminal, and a
terminal request covers only the repository and path it asked.
After every node-engine restart the account verdict says not judged yet until
the engine's first search for setuid programs ends, and DA raised the urgent
condition each time. The account stays unconfined and node show still says
not judged; the condition is raised once the search fails, runs out its bound,
finds a way to root, or the statement goes stale.
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 after its failure: a later walk that contains it was delivered: plan-1791658180097457523 (novox/mesh-controller at a2a671ad into ma…
The node-engine's own since starts again at every restart, so an agent that
restarted the engine in a loop kept agent-can-become-root quiet for ever (the
review of 2026-10-09). The controller now keeps when it first saw the verdict
waiting for the setuid search (migration 0085), forgets it at the next
complete verdict, and raises once the engine's own bound has passed since;
the bound and the pending reason are read from mesh-host's rootsearch.
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 g14 as build-1791542632255817693 (builds --log build-1791542632255817693).
--- 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 196.305s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.018s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.029s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.018s
ok github.com/novox/mesh-controller/examples/route-proxy 1.153s
ok github.com/novox/mesh-controller/internal/artifacts 1.053s
ok github.com/novox/mesh-controller/internal/broker 2.502s
ok github.com/novox/mesh-controller/internal/builder 1.791s
ok github.com/novox/mesh-controller/internal/catalogue 4.289s
ok github.com/novox/mesh-controller/internal/conditions 2.327s
ok github.com/novox/mesh-controller/internal/envfile 1.027s
ok github.com/novox/mesh-controller/internal/facts 1.027s
ok github.com/novox/mesh-controller/internal/identity 3.949s
ok github.com/novox/mesh-controller/internal/inventory 72.375s
ok github.com/novox/mesh-controller/internal/lease 17.701s
ok github.com/novox/mesh-controller/internal/licences 3.605s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.006s
ok github.com/novox/mesh-controller/internal/link 50.574s
ok github.com/novox/mesh-controller/internal/lint 1.884s
ok github.com/novox/mesh-controller/internal/outward 1.031s
ok github.com/novox/mesh-controller/internal/overlay 1.018s
ok github.com/novox/mesh-controller/internal/secrets 1.408s
ok github.com/novox/mesh-controller/internal/store 3.179s
ok github.com/novox/mesh-controller/internal/testbus 1.158s
ok github.com/novox/mesh-controller/internal/token 1.011s
**Merge check** at `2e1a9abb`
- `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 g14 as `build-1791542632255817693` (`builds --log build-1791542632255817693`).
```
--- 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 196.305s
ok github.com/novox/mesh-controller/examples/objectstore-provisioner 1.018s
ok github.com/novox/mesh-controller/examples/postgres-provisioner 1.029s
ok github.com/novox/mesh-controller/examples/redis-provisioner 1.018s
ok github.com/novox/mesh-controller/examples/route-proxy 1.153s
ok github.com/novox/mesh-controller/internal/artifacts 1.053s
ok github.com/novox/mesh-controller/internal/broker 2.502s
ok github.com/novox/mesh-controller/internal/builder 1.791s
ok github.com/novox/mesh-controller/internal/catalogue 4.289s
ok github.com/novox/mesh-controller/internal/conditions 2.327s
ok github.com/novox/mesh-controller/internal/envfile 1.027s
ok github.com/novox/mesh-controller/internal/facts 1.027s
ok github.com/novox/mesh-controller/internal/identity 3.949s
ok github.com/novox/mesh-controller/internal/inventory 72.375s
ok github.com/novox/mesh-controller/internal/lease 17.701s
ok github.com/novox/mesh-controller/internal/licences 3.605s
ok github.com/novox/mesh-controller/internal/licences/adapters 1.006s
ok github.com/novox/mesh-controller/internal/link 50.574s
ok github.com/novox/mesh-controller/internal/lint 1.884s
ok github.com/novox/mesh-controller/internal/outward 1.031s
ok github.com/novox/mesh-controller/internal/overlay 1.018s
ok github.com/novox/mesh-controller/internal/secrets 1.408s
ok github.com/novox/mesh-controller/internal/store 3.179s
ok github.com/novox/mesh-controller/internal/testbus 1.158s
ok github.com/novox/mesh-controller/internal/token 1.011s
```
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.
Merge after #164 — built on
feat/a-node-names-the-account-its-agents-run-as(it changes #164's probe DA). Until #164 merges this diff also shows #164's commits; this PR's change is the last commit.The symptom
After every node-engine restart, the account verdict says
not judged yet (search running)until the engine's first search for setuid programs ends (mesh-host #61:SetuidNotJudged{Pending}, state unknown). Probe DA read that as any other not-judged verdict and raised the urgentagent-can-become-rooton every restart.The change
searchStillRunning: DA raises nothing while the only thing keeping the account from being judged is that first search, and only while the verdict'ssinceis withinlink.RootSearchBound(15 minutes, mesh-host'sSearchBound) plus one statement period (5 minutes). The account is still not confined (agentConfined, which ADR 0259's router reads, is unchanged) andnode showstill says not judged. It is loud again — urgent — when the search failed or ran out its bound (not judged (search incomplete)), when it runs past the window, when a way to root is found, when any other verdict is unknown, or when the statement is stale.link.ReasonRootPendingmust stay equal to mesh-host'saccounts.ReasonPending(not judged yet (search running)).Test
TestASearchStillRunningAfterARestartIsNotUrgent: a search two minutes in raises nothing (fails before this change: urgent condition raised); past the window, an incomplete search, and a way to root found while it runs are each urgent.merge-check.shrun on this head (which contains current main).Delivery
novox/mesh-controller@2e1a9abbf70d— failed since 2026-10-09T11:09:58ZCovered: covered after its failure: a later walk that contains it was delivered: plan-1791658180097457523 (novox/mesh-controller at
a2a671adinto main, done, contains its merge5438d7ff)Delivery plan — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
Machines
Transitions
The commit's note under
refs/notes/mesh-plankeeps every transition:git log --notes=mesh-plan.Merge check at
6751f75emesh/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-1791539341499746904(builds --log build-1791539341499746904).6751f75e3eto9632278e03Follow-up of the review (commit
9632278). This branch is now stacked on #174. It adds migration 0085, and the store refuses a lower-numbered migration after a higher one has run. Merge order: #164, then #174, then this.since, which restarts with the engine. The controller keepsnode.agent_root_pending_since: set the first time it sees the verdict waiting for the search, kept across engine and controller restarts, cleared at the next complete verdict (healthy, or a way to root). The condition is raised oncesearchQuietForhas passed since that time.searchQuietForis the node-engine's own bound. The test pinssearchQuietFor == rootsearch.Bound. The 5-minute grace is gone.link.RootSearchBoundandlink.ReasonRootPendingare now mesh-host'srootsearch.Boundandrootsearch.ReasonPending, vendored from mesh-host #61's head.Test:
TestASearchStillRunningAfterARestartIsNotUrgentsimulates a restart loop, where every statement carries a fresh enginesinceand the controller first saw the waiting past the bound. It is urgent; before this change the condition stayed quiet.Merge check at
9632278emesh/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-1791541655299796289(builds --log build-1791541655299796289).9632278e03to2e1a9abbf7Merge check at
2e1a9abbmesh/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 g14 as
build-1791542632255817693(builds --log build-1791542632255817693).