Why: hq ADR 0334 (small design limit under ADR 0328): a joining module's own directories belong to its own group with setgid, and the tool runner joins those groups so the modules' tools keep reading their state. Found by the review of ADR 0328's controller half. Issue 567.
What
Identity entries may carry runner (an account name); the engine puts it in mesh-<module> via the ADR 0252 join path, records only what it gave, takes it back when nothing names it, and marks identity:<module> changed so the tool runner restarts once on a gain or a loss. Contract 7 (link.OwnGroupContract).
A refused runner (missing, uid 0, root-group primary) is a warning of its own (runner:<module>, runner:library:<name>), never an apply or module failure; library runners now go through the same refusal.
Directory modes may carry setgid (2xxx; setuid and sticky still refused), set on every directory path, kept across applies and compared with it; applied only to directories the mesh made or was handed over, never to an access or a library root.
Old shapes unchanged.
Checked: merge-check.sh green (race). Independent review: APPROVE at c7b534a0 after two rounds; every finding fixed with a failing-first test (mutation-checked).
Delivery effects: node-engine restarts on every node; nothing changes until the controller sends contract-7 fields.
**Why**: hq ADR 0334 (small design limit under ADR 0328): a joining module's own directories belong to its own group with setgid, and the tool runner joins those groups so the modules' tools keep reading their state. Found by the review of ADR 0328's controller half. Issue 567.
**What**
- Identity entries may carry `runner` (an account name); the engine puts it in `mesh-<module>` via the ADR 0252 join path, records only what it gave, takes it back when nothing names it, and marks `identity:<module>` changed so the tool runner restarts once on a gain or a loss. Contract 7 (`link.OwnGroupContract`).
- A refused runner (missing, uid 0, root-group primary) is a warning of its own (`runner:<module>`, `runner:library:<name>`), never an apply or module failure; library runners now go through the same refusal.
- Directory modes may carry setgid (2xxx; setuid and sticky still refused), set on every directory path, kept across applies and compared with it; applied only to directories the mesh made or was handed over, never to an access or a library root.
- Old shapes unchanged.
**Checked**: `merge-check.sh` green (race). Independent review: APPROVE at c7b534a0 after two rounds; every finding fixed with a failing-first test (mutation-checked).
**Delivery effects**: node-engine restarts on every node; nothing changes until the controller sends contract-7 fields.
A joining module's own directories belong to its own group, and its tools run in the
tool runner, which could not read them. An identity may now name the tool runner's
account: the engine puts it in mesh-<module> as it puts it in a library's group,
says the change as identity:<module> for the runner's unit to restart once, takes
it back when no identity names it, and refuses an account that is missing or root's.
The engine states contract 7.
mesh/merge-gate head c7b534a08c98 merged into trunk 6fe82c61bd32 — pass: builds mesh-host → ace, g14, novox, shanks; no bus step; every machine composes wi…
A module's own directories need setgid so what is made beneath keeps its own group,
and a mode of 2750 refused the whole declaration while every apply dropped the bit:
a directory's mode now carries setgid (never setuid or sticky), set, kept and said.
A tool runner's account that is missing or root's failed the whole apply and dropped
the library's outcome: it is now a warning, said as runner:<module> or
runner:library:<name>. And a runner that leaves a group is taken out before the
resources apply, so its unit is restarted in that apply to lose it.
Deliverynovox/mesh-host@c7b534a08c98 — delivered since 2026-10-12T22:36:45Z
Delivery plan — builds mesh-host → ace, g14, novox, shanks; no bus step
tier 0: mesh-host
ace: receives mesh-host
g14: receives mesh-host
novox: receives mesh-host
shanks: receives mesh-host
grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before mesh-host is judged on its first machine
Machines
mesh-host on ace: passed — healthy 3 times over 2m27s
mesh-host on the rest running it: sent
Transitions
2026-10-12 22:13 (new) → proposed (announced): novox/mesh-host#97's head announced
2026-10-12 22:18 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
2026-10-12 22:18 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
2026-10-12 22:33 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
2026-10-12 22:33 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 — not a failed walk that carried a later commit for it, after which it waits for a walk of its own commit
2026-10-12 22:36 delivering → delivered (done): its walk is done, carrying its own commit: every machine of its deploy plan passed, or was left as its policy says
The commit's note under refs/notes/mesh-plan keeps every transition: git log --notes=mesh-plan.
<!-- mesh-delivery:view -->
**Delivery** `novox/mesh-host@c7b534a08c98` — **delivered** since 2026-10-12T22:36:45Z
**Delivery plan** — builds mesh-host → ace, g14, novox, shanks; no bus step
- tier 0: mesh-host
- ace: receives mesh-host
- g14: receives mesh-host
- novox: receives mesh-host
- shanks: receives mesh-host
- grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before mesh-host is judged on its first machine
**Machines**
- mesh-host on ace: passed — healthy 3 times over 2m27s
- mesh-host on the rest running it: sent
**Transitions**
- 2026-10-12 22:13 (new) → proposed (announced): novox/mesh-host#97's head announced
- 2026-10-12 22:18 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
- 2026-10-12 22:18 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
- 2026-10-12 22:33 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
- 2026-10-12 22:33 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 — not a failed walk that carried a later commit for it, after which it waits for a walk of its own commit
- 2026-10-12 22:36 delivering → delivered (done): its walk is done, carrying its own commit: every machine of its deploy plan passed, or was left as its policy says
The commit's note under `refs/notes/mesh-plan` keeps every transition: `git log --notes=mesh-plan`.
Merge check at c7b534a0
Judged: head c7b534a08c98 merged into trunk 6fe82c61bd32; read beside it: mesh-catalog 43a9155d5afe, mesh-controller 21ac8fd8586d, mesh-controller-main 21ac8fd8586d, mesh-tools 954e1a53eef9
mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: mesh-host)
mesh/repo-check: PASS — its merge-check.sh passed
Delivery plan — builds mesh-host → ace, g14, novox, shanks; no bus step
tier 0: mesh-host
ace: receives mesh-host
g14: receives mesh-host
novox: receives mesh-host
shanks: receives mesh-host
grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before mesh-host is judged on its first machine
read by no module's build: cmd/mesh-host/units_test.go, internal/apply/library_test.go
Run by the build seat on g14 as build-1791843189305159638 (builds --log build-1791843189305159638).
--- the gate: mesh-host
mesh-host: ok
long-running resources without health: 0
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-12T22:09:48Z 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-12T22:09:48Z
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 1 module(s) in 1 tier(s): mesh-host
notes:
- cmd/mesh-host/units_test.go and internal/apply/library_test.go read by no module's build, and rebuild nothing (issue 280)
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-host/cmd/mesh-bootstrap 1.009s
ok github.com/novox/mesh-host/cmd/mesh-host 5.448s
ok github.com/novox/mesh-host/examples 1.020s
ok github.com/novox/mesh-host/internal/accounts 1.368s
ok github.com/novox/mesh-host/internal/apply 2.699s
ok github.com/novox/mesh-host/internal/bootstrap 3.280s
ok github.com/novox/mesh-host/internal/bundle 1.012s
ok github.com/novox/mesh-host/internal/declaration 1.054s
ok github.com/novox/mesh-host/internal/firewall 1.656s
ok github.com/novox/mesh-host/internal/identity 1.054s
ok github.com/novox/mesh-host/internal/image 1.017s
ok github.com/novox/mesh-host/internal/inventory 1.039s
ok github.com/novox/mesh-host/internal/link 10.516s
ok github.com/novox/mesh-host/internal/liveness 2.072s
ok github.com/novox/mesh-host/internal/meshcli 1.561s
ok github.com/novox/mesh-host/internal/network 1.044s
ok github.com/novox/mesh-host/internal/outward 1.031s
ok github.com/novox/mesh-host/internal/profile 1.602s
ok github.com/novox/mesh-host/internal/reachable 1.018s
ok github.com/novox/mesh-host/internal/store 1.076s
ok github.com/novox/mesh-host/internal/system 1.012s
ok github.com/novox/mesh-host/internal/tunnel 1.014s
ok github.com/novox/mesh-host/internal/units 1.010s
ok github.com/novox/mesh-host/internal/upgrade 1.041s
ok github.com/novox/mesh-host/internal/witness 1.425s
ok github.com/novox/mesh-host/packaging 1.011s
? github.com/novox/mesh-host/rootsearch [no test files]
ok github.com/novox/mesh-host/validate 1.010s
**Merge check** at `c7b534a0`
Judged: head `c7b534a08c98` merged into trunk `6fe82c61bd32`; read beside it: mesh-catalog `43a9155d5afe`, mesh-controller `21ac8fd8586d`, mesh-controller-main `21ac8fd8586d`, mesh-tools `954e1a53eef9`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: mesh-host)
- `mesh/repo-check`: **PASS** — its merge-check.sh passed
**Delivery plan** — builds mesh-host → ace, g14, novox, shanks; no bus step
- tier 0: mesh-host
- ace: receives mesh-host
- g14: receives mesh-host
- novox: receives mesh-host
- shanks: receives mesh-host
- grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before mesh-host is judged on its first machine
- read by no module's build: cmd/mesh-host/units_test.go, internal/apply/library_test.go
Run by the build seat on g14 as `build-1791843189305159638` (`builds --log build-1791843189305159638`).
```
--- the gate: mesh-host
mesh-host: ok
long-running resources without health: 0
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-12T22:09:48Z 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-12T22:09:48Z
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 1 module(s) in 1 tier(s): mesh-host
notes:
- cmd/mesh-host/units_test.go and internal/apply/library_test.go read by no module's build, and rebuild nothing (issue 280)
--- its merge-check.sh (go toolchain)
ok github.com/novox/mesh-host/cmd/mesh-bootstrap 1.009s
ok github.com/novox/mesh-host/cmd/mesh-host 5.448s
ok github.com/novox/mesh-host/examples 1.020s
ok github.com/novox/mesh-host/internal/accounts 1.368s
ok github.com/novox/mesh-host/internal/apply 2.699s
ok github.com/novox/mesh-host/internal/bootstrap 3.280s
ok github.com/novox/mesh-host/internal/bundle 1.012s
ok github.com/novox/mesh-host/internal/declaration 1.054s
ok github.com/novox/mesh-host/internal/firewall 1.656s
ok github.com/novox/mesh-host/internal/identity 1.054s
ok github.com/novox/mesh-host/internal/image 1.017s
ok github.com/novox/mesh-host/internal/inventory 1.039s
ok github.com/novox/mesh-host/internal/link 10.516s
ok github.com/novox/mesh-host/internal/liveness 2.072s
ok github.com/novox/mesh-host/internal/meshcli 1.561s
ok github.com/novox/mesh-host/internal/network 1.044s
ok github.com/novox/mesh-host/internal/outward 1.031s
ok github.com/novox/mesh-host/internal/profile 1.602s
ok github.com/novox/mesh-host/internal/reachable 1.018s
ok github.com/novox/mesh-host/internal/store 1.076s
ok github.com/novox/mesh-host/internal/system 1.012s
ok github.com/novox/mesh-host/internal/tunnel 1.014s
ok github.com/novox/mesh-host/internal/units 1.010s
ok github.com/novox/mesh-host/internal/upgrade 1.041s
ok github.com/novox/mesh-host/internal/witness 1.425s
ok github.com/novox/mesh-host/packaging 1.011s
? github.com/novox/mesh-host/rootsearch [no test files]
ok github.com/novox/mesh-host/validate 1.010s
```
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.
Why: hq ADR 0334 (small design limit under ADR 0328): a joining module's own directories belong to its own group with setgid, and the tool runner joins those groups so the modules' tools keep reading their state. Found by the review of ADR 0328's controller half. Issue 567.
What
runner(an account name); the engine puts it inmesh-<module>via the ADR 0252 join path, records only what it gave, takes it back when nothing names it, and marksidentity:<module>changed so the tool runner restarts once on a gain or a loss. Contract 7 (link.OwnGroupContract).runner:<module>,runner:library:<name>), never an apply or module failure; library runners now go through the same refusal.Checked:
merge-check.shgreen (race). Independent review: APPROVE atc7b534a0after two rounds; every finding fixed with a failing-first test (mutation-checked).Delivery effects: node-engine restarts on every node; nothing changes until the controller sends contract-7 fields.
Delivery
novox/mesh-host@c7b534a08c98— delivered since 2026-10-12T22:36:45ZDelivery plan — builds mesh-host → 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
c7b534a0Judged: head
c7b534a08c98merged into trunk6fe82c61bd32; read beside it: mesh-catalog43a9155d5afe, mesh-controller21ac8fd8586d, mesh-controller-main21ac8fd8586d, mesh-tools954e1a53eef9mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: mesh-host)mesh/repo-check: PASS — its merge-check.sh passedDelivery plan — builds mesh-host → ace, g14, novox, shanks; no bus step
Run by the build seat on g14 as
build-1791843189305159638(builds --log build-1791843189305159638).