Fixes hq issue 764: every 15 s the node-engine's failed-units look logged in to each declared account's own manager (systemctl --user --machine=<account>@), and since module accounts do not linger, each look started a whole user manager that stopped 10 s later. On the control node that was ~1,700 of the journal's ~2,100 lines a minute and most of journald's remaining disk writes (issue 746). A look must start nothing (ADR 0240 rule 6, ADR 0177).
units.OwnedBy counts an account only when the declaration places a user-scoped unit in it, not for a plain User resource.
units.Look asks the machine's manager first whether user@<uid>.service is active (new system.ManagerRunning, the check apply.managerAway makes) and reads the account's manager only then; a manager not running is not read, has no failed units, and is listed under a new Away field (also in the units part of the health report); an account the machine lacks is listed unread.
liveness.Exec.Units does the same: a user-scoped unit whose manager is not running reads unknown ("not logged in and does not linger", the apply's own words), never down.
Issue 315 still holds: on desktops the dunst module places a user-scoped unit for the operator's account, so its manager (and the Razer daemon) is still read while the operator is logged in.
Noted by the review, not in this change: an account with openrazer but no user-scoped unit of its own would go unread; the controller ignores the new away field (no DisallowUnknownFields) and does not show it yet.
Checks: gofmt, go vet, go test ./..., merge-check.sh (bus tests skipped: no nats-server in that toolchain). Reviewed independently before push: APPROVE at 62af89f85d (the reviewer grepped every --machine= path).
Fixes hq issue 764: every 15 s the node-engine's failed-units look logged in to each declared account's own manager (`systemctl --user --machine=<account>@`), and since module accounts do not linger, each look started a whole user manager that stopped 10 s later. On the control node that was ~1,700 of the journal's ~2,100 lines a minute and most of journald's remaining disk writes (issue 746). A look must start nothing (ADR 0240 rule 6, ADR 0177).
- `units.OwnedBy` counts an account only when the declaration places a user-scoped unit in it, not for a plain User resource.
- `units.Look` asks the machine's manager first whether `user@<uid>.service` is active (new `system.ManagerRunning`, the check `apply.managerAway` makes) and reads the account's manager only then; a manager not running is not read, has no failed units, and is listed under a new `Away` field (also in the units part of the health report); an account the machine lacks is listed unread.
- `liveness.Exec.Units` does the same: a user-scoped unit whose manager is not running reads `unknown` ("not logged in and does not linger", the apply's own words), never `down`.
- Issue 315 still holds: on desktops the dunst module places a user-scoped unit for the operator's account, so its manager (and the Razer daemon) is still read while the operator is logged in.
Noted by the review, not in this change: an account with openrazer but no user-scoped unit of its own would go unread; the controller ignores the new `away` field (no `DisallowUnknownFields`) and does not show it yet.
Checks: gofmt, go vet, go test ./..., merge-check.sh (bus tests skipped: no nats-server in that toolchain). Reviewed independently before push: APPROVE at 62af89f85d0d38519cde1e8f7abcfc0a0015ffe5 (the reviewer grepped every `--machine=` path).
mesh/merge-gate head 62af89f85d0d merged into trunk 1a2677882380 — pass: builds mesh-host → ace, g14, novox, shanks; no bus step; every machine composes wi…
Every 15 s the failed-units look read the own manager of every account
the declaration creates, and reading one is a login that starts it: six
module accounts' managers on the control node started and stopped all
day, most of its journal. A look only reads (ADR 0240 rule 6) and never
asks an account's manager (ADR 0177).
An account's manager is read now only when the declaration places a
user-scoped unit in it, and only after the machine's own manager says
user@<uid>.service is active, as the apply asks before it. A manager not
running is said away in the units statement, with no failed units; in
liveness its units read unknown with the apply's words, never down. The
operator's account on a desktop is still read while logged in, since a
module places a user unit there (issue 315's Razer daemon stays said).
Deliverynovox/mesh-host@62af89f85d0d — delivered since 2026-10-14T22:40:13Z
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 every machine running it: sent
Transitions
2026-10-14 22:35 (new) → proposed (announced): novox/mesh-host#112's head announced
2026-10-14 22:37 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
2026-10-14 22:37 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
2026-10-14 22:38 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
2026-10-14 22:38 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-14 22:40 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@62af89f85d0d` — **delivered** since 2026-10-14T22:40:13Z
**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 every machine running it: sent
**Transitions**
- 2026-10-14 22:35 (new) → proposed (announced): novox/mesh-host#112's head announced
- 2026-10-14 22:37 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
- 2026-10-14 22:37 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
- 2026-10-14 22:38 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
- 2026-10-14 22:38 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-14 22:40 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 62af89f8
Judged: head 62af89f85d0d merged into trunk 1a2677882380; read beside it: mesh-catalog 7913b56d66f7, mesh-controller 4cc6b6c566a5, mesh-controller-main 4cc6b6c566a5, mesh-tools 5d70eb3e35a9
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: internal/liveness/liveness_test.go, internal/units/units_test.go
Run by the build seat on shanks as build-1792017316249160624 (builds --log build-1792017316249160624).
--- 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-14T22:35:08Z 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-14T22:35:08Z
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:
- internal/liveness/liveness_test.go and internal/units/units_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.016s
ok github.com/novox/mesh-host/cmd/mesh-host 5.900s
ok github.com/novox/mesh-host/examples 1.028s
ok github.com/novox/mesh-host/internal/accounts 1.524s
ok github.com/novox/mesh-host/internal/apply 15.448s
ok github.com/novox/mesh-host/internal/bootstrap 4.738s
ok github.com/novox/mesh-host/internal/bundle 1.048s
ok github.com/novox/mesh-host/internal/declaration 1.092s
ok github.com/novox/mesh-host/internal/firewall 1.867s
ok github.com/novox/mesh-host/internal/identity 1.189s
ok github.com/novox/mesh-host/internal/image 1.053s
ok github.com/novox/mesh-host/internal/inventory 1.081s
ok github.com/novox/mesh-host/internal/link 10.502s
ok github.com/novox/mesh-host/internal/liveness 2.203s
ok github.com/novox/mesh-host/internal/meshcli 1.571s
ok github.com/novox/mesh-host/internal/network 1.112s
ok github.com/novox/mesh-host/internal/outward 1.055s
ok github.com/novox/mesh-host/internal/profile 1.653s
ok github.com/novox/mesh-host/internal/reachable 1.063s
ok github.com/novox/mesh-host/internal/store 1.290s
ok github.com/novox/mesh-host/internal/system 1.060s
ok github.com/novox/mesh-host/internal/tunnel 1.057s
ok github.com/novox/mesh-host/internal/units 1.059s
ok github.com/novox/mesh-host/internal/upgrade 1.225s
ok github.com/novox/mesh-host/internal/witness 15.846s
ok github.com/novox/mesh-host/packaging 1.034s
? github.com/novox/mesh-host/rootsearch [no test files]
ok github.com/novox/mesh-host/validate 1.041s
**Merge check** at `62af89f8`
Judged: head `62af89f85d0d` merged into trunk `1a2677882380`; read beside it: mesh-catalog `7913b56d66f7`, mesh-controller `4cc6b6c566a5`, mesh-controller-main `4cc6b6c566a5`, mesh-tools `5d70eb3e35a9`
- `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: internal/liveness/liveness_test.go, internal/units/units_test.go
Run by the build seat on shanks as `build-1792017316249160624` (`builds --log build-1792017316249160624`).
```
--- 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-14T22:35:08Z 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-14T22:35:08Z
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:
- internal/liveness/liveness_test.go and internal/units/units_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.016s
ok github.com/novox/mesh-host/cmd/mesh-host 5.900s
ok github.com/novox/mesh-host/examples 1.028s
ok github.com/novox/mesh-host/internal/accounts 1.524s
ok github.com/novox/mesh-host/internal/apply 15.448s
ok github.com/novox/mesh-host/internal/bootstrap 4.738s
ok github.com/novox/mesh-host/internal/bundle 1.048s
ok github.com/novox/mesh-host/internal/declaration 1.092s
ok github.com/novox/mesh-host/internal/firewall 1.867s
ok github.com/novox/mesh-host/internal/identity 1.189s
ok github.com/novox/mesh-host/internal/image 1.053s
ok github.com/novox/mesh-host/internal/inventory 1.081s
ok github.com/novox/mesh-host/internal/link 10.502s
ok github.com/novox/mesh-host/internal/liveness 2.203s
ok github.com/novox/mesh-host/internal/meshcli 1.571s
ok github.com/novox/mesh-host/internal/network 1.112s
ok github.com/novox/mesh-host/internal/outward 1.055s
ok github.com/novox/mesh-host/internal/profile 1.653s
ok github.com/novox/mesh-host/internal/reachable 1.063s
ok github.com/novox/mesh-host/internal/store 1.290s
ok github.com/novox/mesh-host/internal/system 1.060s
ok github.com/novox/mesh-host/internal/tunnel 1.057s
ok github.com/novox/mesh-host/internal/units 1.059s
ok github.com/novox/mesh-host/internal/upgrade 1.225s
ok github.com/novox/mesh-host/internal/witness 15.846s
ok github.com/novox/mesh-host/packaging 1.034s
? github.com/novox/mesh-host/rootsearch [no test files]
ok github.com/novox/mesh-host/validate 1.041s
```
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.
Fixes hq issue 764: every 15 s the node-engine's failed-units look logged in to each declared account's own manager (
systemctl --user --machine=<account>@), and since module accounts do not linger, each look started a whole user manager that stopped 10 s later. On the control node that was ~1,700 of the journal's ~2,100 lines a minute and most of journald's remaining disk writes (issue 746). A look must start nothing (ADR 0240 rule 6, ADR 0177).units.OwnedBycounts an account only when the declaration places a user-scoped unit in it, not for a plain User resource.units.Lookasks the machine's manager first whetheruser@<uid>.serviceis active (newsystem.ManagerRunning, the checkapply.managerAwaymakes) and reads the account's manager only then; a manager not running is not read, has no failed units, and is listed under a newAwayfield (also in the units part of the health report); an account the machine lacks is listed unread.liveness.Exec.Unitsdoes the same: a user-scoped unit whose manager is not running readsunknown("not logged in and does not linger", the apply's own words), neverdown.Noted by the review, not in this change: an account with openrazer but no user-scoped unit of its own would go unread; the controller ignores the new
awayfield (noDisallowUnknownFields) and does not show it yet.Checks: gofmt, go vet, go test ./..., merge-check.sh (bus tests skipped: no nats-server in that toolchain). Reviewed independently before push: APPROVE at
62af89f85d(the reviewer grepped every--machine=path).Delivery
novox/mesh-host@62af89f85d0d— delivered since 2026-10-14T22:40:13ZDelivery 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.ready at
62af89f85d(the operator's word, 2026-10-15; independent review APPROVE at this sha).Merge check at
62af89f8Judged: head
62af89f85d0dmerged into trunk1a2677882380; read beside it: mesh-catalog7913b56d66f7, mesh-controller4cc6b6c566a5, mesh-controller-main4cc6b6c566a5, mesh-tools5d70eb3e35a9mesh/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 shanks as
build-1792017316249160624(builds --log build-1792017316249160624).