Replaces #244 (review 55). This is one commit on a fresh branch from main, so the built binary that #244's first commit carried never appears. .gitignore now names the build outputs. Everything #244's description says still holds; below is what changed for review 55.
Required 1: what was opened is judged, not the name (openJudged in reads.go). It is used by read, list and search.
The type is checked by stat before the open (lstat in a search), so a device or a fifo is never opened.
The open uses O_RDONLY|O_NONBLOCK|O_NOCTTY|O_CLOEXEC, plus O_NOFOLLOW in a search and O_DIRECTORY for a list.
The type is checked again with fstat on the descriptor.
The path of /proc/self/fd/<n> is judged by name. A path that is not absolute, or ends in (deleted), is refused.
New test TestALinkFlippedDuringAReadNeverReadsASecretPlace: a goroutine flips a link between a plain file and the module's own broker under a secret place, during 5000 reads and 5000 searches. Nothing leaks. With #244's code the same test fails.
Required 2: key blocks. Every line from a -----BEGIN through its -----END is withheld in a read and in a search. New test TestEveryLineOfAKeyBlockIsWithheld uses a generated RSA-2048 PKCS#8 key in server.pem; with #244's code it fails.
Required 3, and the should-items:
Refused by name: shell and program histories, browser and mail profiles (.mozilla, .thunderbird, .config/google-chrome, chromium, BraveSoftware, vivaldi, microsoft-edge), /proc/<pid>/{environ,mem,fd,map_files,root,cwd}, /etc/rancher and /etc/kubernetes/admin.conf. New test TestHistoriesProfilesAndProcessesAreRefusedByName; it fails with #244's code.
A search stays on the file system of the path named; the other file systems it reaches are named in other-file-systems-skipped. This also keeps /proc and /sys out unless the search starts inside them. The 20-second time bound is now checked every 1000 lines inside a file too.
The README names the limit for hard links.
go.mod pins mesh-sdk #23's new head, v0.1.14-0.20261012122749-67bfa22132f2 (review 53's fixes). I will move it to the merged commit once #23 merges.
Checks run here.
go vet passes, and go test -race ./... passes in the module.
MESH_GATE=<controller from mesh-controller #257 at 63a99d4> MESH_CHECK_MODULES=mesh-reads sh merge-check.sh passes: 69 resources without health, as kept.
mesh/merge-gate here stays red until #257 runs. The running controller has no node-reads seat.
Group. This branch is fix/418-node-reads-2, so it is not in the fix/418-node-reads delivery group with mesh-sdk #23 and mesh-controller #257. That does not change the order: #23, then #257 and its rollout done, then this.
Part of issue 418. Not merged.
Replaces #244 (review 55). This is one commit on a fresh branch from main, so the built binary that #244's first commit carried never appears. `.gitignore` now names the build outputs. Everything #244's description says still holds; below is what changed for review 55.
**Required 1: what was opened is judged, not the name** (`openJudged` in `reads.go`). It is used by `read`, `list` and `search`.
- The type is checked by stat before the open (lstat in a search), so a device or a fifo is never opened.
- The open uses `O_RDONLY|O_NONBLOCK|O_NOCTTY|O_CLOEXEC`, plus `O_NOFOLLOW` in a search and `O_DIRECTORY` for a list.
- The type is checked again with fstat on the descriptor.
- The path of `/proc/self/fd/<n>` is judged by name. A path that is not absolute, or ends in ` (deleted)`, is refused.
- New test `TestALinkFlippedDuringAReadNeverReadsASecretPlace`: a goroutine flips a link between a plain file and the module's own broker under a secret place, during 5000 reads and 5000 searches. Nothing leaks. With #244's code the same test fails.
**Required 2: key blocks.** Every line from a `-----BEGIN ` through its `-----END ` is withheld in a read and in a search. New test `TestEveryLineOfAKeyBlockIsWithheld` uses a generated RSA-2048 PKCS#8 key in `server.pem`; with #244's code it fails.
**Required 3, and the should-items:**
- Refused by name: shell and program histories, browser and mail profiles (`.mozilla`, `.thunderbird`, `.config/google-chrome`, `chromium`, `BraveSoftware`, `vivaldi`, `microsoft-edge`), `/proc/<pid>/{environ,mem,fd,map_files,root,cwd}`, `/etc/rancher` and `/etc/kubernetes/admin.conf`. New test `TestHistoriesProfilesAndProcessesAreRefusedByName`; it fails with #244's code.
- A search stays on the file system of the path named; the other file systems it reaches are named in `other-file-systems-skipped`. This also keeps `/proc` and `/sys` out unless the search starts inside them. The 20-second time bound is now checked every 1000 lines inside a file too.
- The README names the limit for hard links.
- `go.mod` pins mesh-sdk #23's new head, `v0.1.14-0.20261012122749-67bfa22132f2` (review 53's fixes). I will move it to the merged commit once #23 merges.
**Checks run here.**
- `go vet` passes, and `go test -race ./...` passes in the module.
- `MESH_GATE=<controller from mesh-controller #257 at 63a99d4> MESH_CHECK_MODULES=mesh-reads sh merge-check.sh` passes: 69 resources without health, as kept.
- `mesh/merge-gate` here stays red until #257 runs. The running controller has no `node-reads` seat.
**Group.** This branch is `fix/418-node-reads-2`, so it is not in the `fix/418-node-reads` delivery group with mesh-sdk #23 and mesh-controller #257. That does not change the order: #23, then #257 and its rollout done, then this.
Part of issue 418. Not merged.
mesh/merge-gate pass: builds new: modules/mesh-reads, sent nowhere; no bus step; every machine composes with the change as it did without (4 of 4 compose)
Reading a file, searching one, listing a directory, the owner and mode of each
component of a path and looking up an account went through the login shell's
execute as the operator's account, which sees the operator's keys and the
agent's credentials. This module holds node-reads on every node and runs as
mesh-reads (no login, no group beside its own). It refuses the node's secret
places by name, judging the file actually opened rather than the name asked,
so a flipped link reaches nothing refused; withholds any line shaped like a
secret through mesh-sdk's outward rule and every line of a BEGIN/END block;
and bounds every answer. Replaces mesh-catalog #244 (reviews 55), whose first
commit carried a built binary.
Deliverynovox/mesh-catalog@994cab533bbd — delivered since 2026-10-12T14:52:28Z
Delivery plan — builds new: modules/mesh-reads, sent nowhere; no bus step
Transitions
2026-10-12 12:33 (new) → proposed (announced): novox/mesh-catalog#247's head announced
2026-10-12 12:34 proposed → checked (checked): the verdict names this commit
2026-10-12 12:34 checked → rejected (refused): the gate failed or could not run, or the repository's own check failed
2026-10-12 13:31 rejected → proposed (recheck): mesh-controller #257 (the node-reads seat) is delivered on all four nodes, so mesh-reads' claim on it can be judged (issue 418)
2026-10-12 13:33 proposed → checked (checked): the verdict names this commit
2026-10-12 13:33 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
2026-10-12 14:52 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 14:52 published → delivered (done): nothing for a walk to move
The commit's note under refs/notes/mesh-plan keeps every transition: git log --notes=mesh-plan.
<!-- mesh-delivery:view -->
**Delivery** `novox/mesh-catalog@994cab533bbd` — **delivered** since 2026-10-12T14:52:28Z
**Delivery plan** — builds new: modules/mesh-reads, sent nowhere; no bus step
**Transitions**
- 2026-10-12 12:33 (new) → proposed (announced): novox/mesh-catalog#247's head announced
- 2026-10-12 12:34 proposed → checked (checked): the verdict names this commit
- 2026-10-12 12:34 checked → rejected (refused): the gate failed or could not run, or the repository's own check failed
- 2026-10-12 13:31 rejected → proposed (recheck): mesh-controller #257 (the node-reads seat) is delivered on all four nodes, so mesh-reads' claim on it can be judged (issue 418)
- 2026-10-12 13:33 proposed → checked (checked): the verdict names this commit
- 2026-10-12 13:33 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
- 2026-10-12 14:52 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 14:52 published → delivered (done): nothing for a walk to move
The commit's note under `refs/notes/mesh-plan` keeps every transition: `git log --notes=mesh-plan`.
mesh/merge-gate: FAIL — a manifest the change touches fails the module check: modules/mesh-reads/module.json: this manifest cannot be used: (modules: new:modules/mesh-reads)
mesh/repo-check: FAIL — its merge-check.sh failed: files asking for a setting without saying whether it is trusted: 25
Delivery plan — builds new: modules/mesh-reads, sent nowhere; no bus step
read by no module's build: .gitignore
Run by the build seat on g14 as build-1791808383039663245 (builds --log build-1791808383039663245).
--- the gate: new:modules/mesh-reads
modules/mesh-reads/module.json: this manifest cannot be used:
- mesh-reads claims "node-reads", which is a seat in the mesh's own namespace (mesh-*/node-*) that it does not define (novox/hq ADR 0121) — the seats are: git, mesh-artifact-store, mesh-broker, mesh-build-machine, mesh-catalog, mesh-controller, mesh-delivery, mesh-dns-resolver, mesh-store, mesh-vault, node-backup, node-bar, node-build-agent, node-clipboard, node-compositor, node-container-runtime, node-display-server, node-display-session, node-environment, node-hostname, node-hotkeys, node-intrusion-prevention, node-launcher, node-lock-screen, node-login-manager, node-login-shell, node-message-bus, node-mounts, node-nfs-server, node-notifier, node-package-manager, node-packet-filter, node-power, node-resolver, node-secret-service, node-service-manager, node-terminal-emulator, node-uplink, npm-package-registry, the-private-network
long-running resources without health: 0
files asking for a setting without saying whether it is trusted: 0
mesh-controller: 1 problem(s) in 1 manifest(s)
--- the same manifests on main
--- its merge-check.sh (go toolchain)
ok git.novox.be/novox/mesh-catalog/checks/words 0.002s
words: 12 retired words and 70 daemons' lines, none in the 43650 strings of 694 files
ok git.novox.be/novox/mesh-catalog/checks/agenthome 0.011s
agent-home: no archive and no file written into under the agent's home
ok git.novox.be/novox/mesh-catalog/checks/paths 0.004s
paths: no module names another's state on its machine (3 known, listed to go)
mesh-controller: 1 problem(s) in 127 manifest(s)
modules/mesh-reads/module.json: this manifest cannot be used:
- mesh-reads claims "node-reads", which is a seat in the mesh's own namespace (mesh-*/node-*) that it does not define (novox/hq ADR 0121) — the seats are: git, mesh-artifact-store, mesh-broker, mesh-build-machine, mesh-catalog, mesh-controller, mesh-delivery, mesh-dns-resolver, mesh-store, mesh-vault, node-backup, node-bar, node-build-agent, node-clipboard, node-compositor, node-container-runtime, node-display-server, node-display-session, node-environment, node-hostname, node-hotkeys, node-intrusion-prevention, node-launcher, node-lock-screen, node-login-manager, node-login-shell, node-message-bus, node-mounts, node-nfs-server, node-notifier, node-package-manager, node-packet-filter, node-power, node-resolver, node-secret-service, node-service-manager, node-terminal-emulator, node-uplink, npm-package-registry, the-private-network
adwaita: ok, 4 tool(s)
artifact-store-tools: ok, 4 tool(s), invokes seat:mesh-controller.artifacts, seat:mesh-controller.collect
asus-zephyrus-g14: ok, 11 tool(s); WARNING: asusd, supergfxd, upower stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
audit-logger: ok, keeps trail (valuable), spool (valuable)
avahi: ok, 4 tool(s); WARNING: daemon stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
baserow: ok, keeps data (valuable), ready: server by its image's own check every 30s; WARNING: runtime-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
betterbird: ok, 7 tool(s); WARNING: user-js ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
blueman: ok, 3 tool(s)
bluetooth: ok, 9 tool(s); WARNING: daemon stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
build-agent: ok, keeps workspace (cache); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
ca-trust: ok; WARNING: trust stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
claude-code: ok, 45 tool(s), keeps state servers, holdings, config, proposals, reads claude-licence-manager.bindings, keeps agent-home (valuable); WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
claude-licence-manager: ok, keeps state bindings, reads claude-code.holdings; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
clipmenu: ok, 3 tool(s)
confluence: ok
cups: ok, 7 tool(s); WARNING: socket, scheduler stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
dbus: ok, 5 tool(s); WARNING: system-bus stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
de-spiegel: ok; WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
desk-channel: ok, 1 tool(s), invokes seat:node-notifier.send, keeps state shown; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
disk-load: ok, 4 tool(s)
distribution: ok, keeps registry (rebuildable); WARNING: store stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
dmenu: ok, 2 tool(s)
dnsmasq: ok, 3 tool(s), ready: service by unit every 30s; watch by its tool dnsmasq_health every 20s
docker: ok, 22 tool(s), invokes seat:mesh-controller.images; WARNING: socket, runtime, prune stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
docker-compose: ok, 9 tool(s)
dunst: ok, 6 tool(s)
fail2ban: ok, 1 tool(s); WARNING: run stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
feh: ok, 2 tool(s)
flatpak: ok, 11 tool(s)
fonts: ok, 6 tool(s)
forticlient: ok, 3 tool(s), ready: split-dns by unit every 30s; WARNING: scheduler stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
gitea: ok, keeps data (valuable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
gitlab: ok
gnome-keyring: ok, 4 tool(s)
grafana: ok, keeps data (valuable), ready: server by http / on web every 30s; WARNING: runtime-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
hello-web: ok; WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
home-assistant: ok, keeps config (valuable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
hostname: ok; WARNING: name ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
i3: ok, 10 tool(s)
i3status-rust: ok, 4 tool(s)
icecast: ok, keeps logs (cache); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
influxdb: ok, keeps data (valuable), config (valuable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
invoicing: ok; WARNING: app, api stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
jira: ok
keycloak: ok; WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
lab: ok, keeps work (cache); WARNING: runtime-env ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
lemurs: ok, 2 tool(s); WARNING: service stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
letta: ok; WARNING: runtime-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
local-model-consumer: ok
localization: ok, 4 tool(s)
logrotate: ok, 7 tool(s); WARNING: timer stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
mailu: ok, keeps mail (valuable), dkim (valuable), data (valuable), dav (valuable), webmail (valuable), queue (valuable), filter (rebuildable), certs (rebuildable), automx (rebuildable), fetchmail (rebuildable), clamav (cache), redis (cache), ready: resolver by its image's own check every 30s; admin by its image's own check every 30s; imap by its image's own check every 30s; smtp by its image's own check every 30s; antispam by its image's own check every 30s; webmail by its image's own check every 30s; webdav by its image's own check every 30s; fetchmail by its image's own check every 30s; front by its image's own check every 30s; WARNING: config-env ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: redis, antivirus, automx stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
marrytts: ok; WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
matrix: ok, keeps db (valuable), ready: element by its image's own check every 30s; WARNING: element-conf ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: homeserver stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
memory-pressure: ok, 6 tool(s); WARNING: oomd stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
mesh-catalog: ok
mesh-cli: ok
mesh-delivery: ok, 1 tool(s), invokes seat:mesh-controller.delivery-plan, seat:mesh-controller.delivery-order, seat:mesh-controller.delivery-check, seat:mesh-controller.deliver, seat:mesh-controller.delivery-stop, seat:mesh-controller.delivery-walks, gitea.gitea_note_append, gitea.gitea_delivery_view, gitea.gitea_commit_status, gitea.gitea_commit_statuses, gitea.gitea_contains, gitea.gitea_open_pulls, keeps state deliveries, groups
mesh-issues: ok, invokes claude-code.claude_code_judge, seat:mesh-delivery.checks, seat:operator-channel.notify, records.records_status, records.records_list, records.records_read, mesh-knowledge.knowledge_highest, keeps state issues, counters, grooming, reservations, keeps log changes (1024 MiB)
mesh-knowledge: ok, 2 tool(s), invokes seat:issue-tracker.reserve, claude-code.claude_code_judge, claude-code.claude_code_judged, records.records_status, records.records_list, records.records_read, seat:operator-channel.notify, ready: keep by unit every 30s; watch by its tool knowledge_health every 1m0s
mesh-vault: ok, keeps state (valuable), ledger (valuable), root (valuable)
mesh-watcher: ok, 4 tool(s), invokes mesh-watcher.watcher_ping, seat:mesh-controller.seats; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
messenger: ok, 7 tool(s), invokes seat:mesh-controller.conditions, seat:mesh-controller.root-free, seat:issue-tracker.tracking, keeps state open, sent, asks, identities, walks; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
minio: ok, keeps data (valuable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
model-usage: ok, keeps state (cache), spool (valuable)
mongodb: ok, keeps data (valuable), dumps (rebuildable), ready: server by tcp on database every 30s
mosquitto: ok, keeps data (rebuildable), ready: server by tcp on mqtt every 30s
mounts: ok, 3 tool(s), invokes seat:mesh-controller.data, keeps state shares, reads nfs-server.exports, ready: apply by unit every 30s; watch by its tool mounts_health every 1m0s; WARNING: config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
mssql: ok, keeps data (valuable), dumps (rebuildable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
n8n: ok, keeps data (valuable), cache (cache); WARNING: server, cache-server, browser stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
nats: ok, 9 tool(s), keeps jetstream (valuable), snapshots (rebuildable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
netcheck: ok, 5 tool(s)
networkmanager: ok
nextcloud: ok, keeps html (valuable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
nextcloud-client: ok, 4 tool(s)
nfs-server: ok, 1 tool(s), invokes seat:mesh-controller.seats, seat:mesh-controller.data, keeps state exports, reads mounts.shares, ready: server by unit every 30s; exports by its tool nfs_health every 1m0s; WARNING: config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
nftables: ok, 1 tool(s); WARNING: load stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
nm-applet: ok, 3 tool(s)
node-env: ok
nodered: ok, keeps data (valuable), ready: server by its image's own check every 30s; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
ollama: ok, keeps models (rebuildable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
only-office: ok, keeps data (rebuildable), lib (rebuildable), db (rebuildable), fonts (rebuildable), logs (cache), rabbitmq (cache), redis (cache); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
openai-consumer: ok
openrazer: ok, 3 tool(s)
pacman: ok, 15 tool(s); WARNING: mirror-refresh, cache-cleaning stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
photos-eef: ok; WARNING: client stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
photos-filip: ok; WARNING: client stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
picom: ok, 4 tool(s); WARNING: configuration ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
polychromatic: ok, 3 tool(s)
postgres: ok, keeps store (valuable), dumps (rebuildable), ready: server by tcp on database every 30s
power: ok, 5 tool(s), keeps state draw, ready: draw by unit every 30s; WARNING: logind-power ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: after-boot, before-shutdown stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
powerlevel10k: ok
records: ok, 6 tool(s), keeps checkout (rebuildable)
redis: ok, keeps data (cache), ready: server by tcp on cache every 30s
restic: ok, 3 tool(s), keeps repository (rebuildable), state (cache), ready: night by its tool backup_health every 1m0s; measure by unit every 30s
rofi: ok, 3 tool(s)
route-adapter: ok; WARNING: config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
route-proxy: ok, keeps acme (rebuildable), ca (cache); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
screen-lock: ok, 3 tool(s)
searxng: ok, keeps valkey (cache); WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: cache, server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
sensors: ok, 6 tool(s), ready: drives by unit every 30s; watch by its tool sensors_health every 1m0s
showcase: ok; WARNING: server, tools stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
slack: ok, 4 tool(s)
snapd: ok, 10 tool(s)
ssh-client: ok, 8 tool(s), keeps ssh (valuable)
sshd: ok; WARNING: run stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
step-ca: ok, keeps home (valuable), ready: server by its image's own check every 30s
sudo: ok, 4 tool(s)
supabase: ok, keeps db (valuable), dumps (rebuildable), storage (valuable), functions (valuable), db-config (rebuildable), ready: db by its image's own check every 30s; kong by its image's own check every 30s; meta by its image's own check every 30s; studio by its image's own check every 30s; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: vector, analytics, auth, rest, realtime, imgproxy, storage-api, edge-functions, pooler stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
systemd: ok
systemd-networkd: ok
systemd-resolved: ok, ready: service by unit every 30s; guard by unit every 30s
telegram: ok, 1 tool(s), keeps state offset, messages
time-sync: ok, 3 tool(s); WARNING: daemon stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
triggerhappy: ok, 4 tool(s); WARNING: service stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
umami: ok; WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
unifi: ok, keeps data (valuable); WARNING: runtime-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
website: ok, ready: server by http / on web every 30s
xclip: ok, 4 tool(s)
xdg: ok, 5 tool(s); WARNING: user-dirs ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
xorg: ok, 9 tool(s)
xterm: ok, 2 tool(s)
zfs: ok, 15 tool(s), ready: watch by its tool zfs_health every 1m0s; events by unit every 30s; WARNING: scrub-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
zsh: ok, 1 tool(s); WARNING: tools-conf ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
zsh-autosuggestions: ok
zsh-syntax-highlighting: ok
long-running resources without health: 69
files asking for a setting without saying whether it is trusted: 25
**Merge check** at `994cab53`
- `mesh/merge-gate`: **FAIL** — a manifest the change touches fails the module check: modules/mesh-reads/module.json: this manifest cannot be used: (modules: new:modules/mesh-reads)
- `mesh/repo-check`: **FAIL** — its merge-check.sh failed: files asking for a setting without saying whether it is trusted: 25
**Delivery plan** — builds new: modules/mesh-reads, sent nowhere; no bus step
- read by no module's build: .gitignore
Run by the build seat on g14 as `build-1791808383039663245` (`builds --log build-1791808383039663245`).
```
--- the gate: new:modules/mesh-reads
modules/mesh-reads/module.json: this manifest cannot be used:
- mesh-reads claims "node-reads", which is a seat in the mesh's own namespace (mesh-*/node-*) that it does not define (novox/hq ADR 0121) — the seats are: git, mesh-artifact-store, mesh-broker, mesh-build-machine, mesh-catalog, mesh-controller, mesh-delivery, mesh-dns-resolver, mesh-store, mesh-vault, node-backup, node-bar, node-build-agent, node-clipboard, node-compositor, node-container-runtime, node-display-server, node-display-session, node-environment, node-hostname, node-hotkeys, node-intrusion-prevention, node-launcher, node-lock-screen, node-login-manager, node-login-shell, node-message-bus, node-mounts, node-nfs-server, node-notifier, node-package-manager, node-packet-filter, node-power, node-resolver, node-secret-service, node-service-manager, node-terminal-emulator, node-uplink, npm-package-registry, the-private-network
long-running resources without health: 0
files asking for a setting without saying whether it is trusted: 0
mesh-controller: 1 problem(s) in 1 manifest(s)
--- the same manifests on main
--- its merge-check.sh (go toolchain)
ok git.novox.be/novox/mesh-catalog/checks/words 0.002s
words: 12 retired words and 70 daemons' lines, none in the 43650 strings of 694 files
ok git.novox.be/novox/mesh-catalog/checks/agenthome 0.011s
agent-home: no archive and no file written into under the agent's home
ok git.novox.be/novox/mesh-catalog/checks/paths 0.004s
paths: no module names another's state on its machine (3 known, listed to go)
mesh-controller: 1 problem(s) in 127 manifest(s)
modules/mesh-reads/module.json: this manifest cannot be used:
- mesh-reads claims "node-reads", which is a seat in the mesh's own namespace (mesh-*/node-*) that it does not define (novox/hq ADR 0121) — the seats are: git, mesh-artifact-store, mesh-broker, mesh-build-machine, mesh-catalog, mesh-controller, mesh-delivery, mesh-dns-resolver, mesh-store, mesh-vault, node-backup, node-bar, node-build-agent, node-clipboard, node-compositor, node-container-runtime, node-display-server, node-display-session, node-environment, node-hostname, node-hotkeys, node-intrusion-prevention, node-launcher, node-lock-screen, node-login-manager, node-login-shell, node-message-bus, node-mounts, node-nfs-server, node-notifier, node-package-manager, node-packet-filter, node-power, node-resolver, node-secret-service, node-service-manager, node-terminal-emulator, node-uplink, npm-package-registry, the-private-network
adwaita: ok, 4 tool(s)
artifact-store-tools: ok, 4 tool(s), invokes seat:mesh-controller.artifacts, seat:mesh-controller.collect
asus-zephyrus-g14: ok, 11 tool(s); WARNING: asusd, supergfxd, upower stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
audit-logger: ok, keeps trail (valuable), spool (valuable)
avahi: ok, 4 tool(s); WARNING: daemon stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
baserow: ok, keeps data (valuable), ready: server by its image's own check every 30s; WARNING: runtime-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
betterbird: ok, 7 tool(s); WARNING: user-js ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
blueman: ok, 3 tool(s)
bluetooth: ok, 9 tool(s); WARNING: daemon stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
build-agent: ok, keeps workspace (cache); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
ca-trust: ok; WARNING: trust stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
claude-code: ok, 45 tool(s), keeps state servers, holdings, config, proposals, reads claude-licence-manager.bindings, keeps agent-home (valuable); WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
claude-licence-manager: ok, keeps state bindings, reads claude-code.holdings; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
clipmenu: ok, 3 tool(s)
confluence: ok
cups: ok, 7 tool(s); WARNING: socket, scheduler stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
dbus: ok, 5 tool(s); WARNING: system-bus stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
de-spiegel: ok; WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
desk-channel: ok, 1 tool(s), invokes seat:node-notifier.send, keeps state shown; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
disk-load: ok, 4 tool(s)
distribution: ok, keeps registry (rebuildable); WARNING: store stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
dmenu: ok, 2 tool(s)
dnsmasq: ok, 3 tool(s), ready: service by unit every 30s; watch by its tool dnsmasq_health every 20s
docker: ok, 22 tool(s), invokes seat:mesh-controller.images; WARNING: socket, runtime, prune stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
docker-compose: ok, 9 tool(s)
dunst: ok, 6 tool(s)
fail2ban: ok, 1 tool(s); WARNING: run stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
feh: ok, 2 tool(s)
flatpak: ok, 11 tool(s)
fonts: ok, 6 tool(s)
forticlient: ok, 3 tool(s), ready: split-dns by unit every 30s; WARNING: scheduler stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
gitea: ok, keeps data (valuable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
gitlab: ok
gnome-keyring: ok, 4 tool(s)
grafana: ok, keeps data (valuable), ready: server by http / on web every 30s; WARNING: runtime-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
hello-web: ok; WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
home-assistant: ok, keeps config (valuable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
hostname: ok; WARNING: name ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
i3: ok, 10 tool(s)
i3status-rust: ok, 4 tool(s)
icecast: ok, keeps logs (cache); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
influxdb: ok, keeps data (valuable), config (valuable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
invoicing: ok; WARNING: app, api stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
jira: ok
keycloak: ok; WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
lab: ok, keeps work (cache); WARNING: runtime-env ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
lemurs: ok, 2 tool(s); WARNING: service stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
letta: ok; WARNING: runtime-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
local-model-consumer: ok
localization: ok, 4 tool(s)
logrotate: ok, 7 tool(s); WARNING: timer stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
mailu: ok, keeps mail (valuable), dkim (valuable), data (valuable), dav (valuable), webmail (valuable), queue (valuable), filter (rebuildable), certs (rebuildable), automx (rebuildable), fetchmail (rebuildable), clamav (cache), redis (cache), ready: resolver by its image's own check every 30s; admin by its image's own check every 30s; imap by its image's own check every 30s; smtp by its image's own check every 30s; antispam by its image's own check every 30s; webmail by its image's own check every 30s; webdav by its image's own check every 30s; fetchmail by its image's own check every 30s; front by its image's own check every 30s; WARNING: config-env ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: redis, antivirus, automx stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
marrytts: ok; WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
matrix: ok, keeps db (valuable), ready: element by its image's own check every 30s; WARNING: element-conf ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: homeserver stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
memory-pressure: ok, 6 tool(s); WARNING: oomd stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
mesh-catalog: ok
mesh-cli: ok
mesh-delivery: ok, 1 tool(s), invokes seat:mesh-controller.delivery-plan, seat:mesh-controller.delivery-order, seat:mesh-controller.delivery-check, seat:mesh-controller.deliver, seat:mesh-controller.delivery-stop, seat:mesh-controller.delivery-walks, gitea.gitea_note_append, gitea.gitea_delivery_view, gitea.gitea_commit_status, gitea.gitea_commit_statuses, gitea.gitea_contains, gitea.gitea_open_pulls, keeps state deliveries, groups
mesh-issues: ok, invokes claude-code.claude_code_judge, seat:mesh-delivery.checks, seat:operator-channel.notify, records.records_status, records.records_list, records.records_read, mesh-knowledge.knowledge_highest, keeps state issues, counters, grooming, reservations, keeps log changes (1024 MiB)
mesh-knowledge: ok, 2 tool(s), invokes seat:issue-tracker.reserve, claude-code.claude_code_judge, claude-code.claude_code_judged, records.records_status, records.records_list, records.records_read, seat:operator-channel.notify, ready: keep by unit every 30s; watch by its tool knowledge_health every 1m0s
mesh-vault: ok, keeps state (valuable), ledger (valuable), root (valuable)
mesh-watcher: ok, 4 tool(s), invokes mesh-watcher.watcher_ping, seat:mesh-controller.seats; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
messenger: ok, 7 tool(s), invokes seat:mesh-controller.conditions, seat:mesh-controller.root-free, seat:issue-tracker.tracking, keeps state open, sent, asks, identities, walks; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
minio: ok, keeps data (valuable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
model-usage: ok, keeps state (cache), spool (valuable)
mongodb: ok, keeps data (valuable), dumps (rebuildable), ready: server by tcp on database every 30s
mosquitto: ok, keeps data (rebuildable), ready: server by tcp on mqtt every 30s
mounts: ok, 3 tool(s), invokes seat:mesh-controller.data, keeps state shares, reads nfs-server.exports, ready: apply by unit every 30s; watch by its tool mounts_health every 1m0s; WARNING: config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
mssql: ok, keeps data (valuable), dumps (rebuildable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
n8n: ok, keeps data (valuable), cache (cache); WARNING: server, cache-server, browser stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
nats: ok, 9 tool(s), keeps jetstream (valuable), snapshots (rebuildable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
netcheck: ok, 5 tool(s)
networkmanager: ok
nextcloud: ok, keeps html (valuable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
nextcloud-client: ok, 4 tool(s)
nfs-server: ok, 1 tool(s), invokes seat:mesh-controller.seats, seat:mesh-controller.data, keeps state exports, reads mounts.shares, ready: server by unit every 30s; exports by its tool nfs_health every 1m0s; WARNING: config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
nftables: ok, 1 tool(s); WARNING: load stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
nm-applet: ok, 3 tool(s)
node-env: ok
nodered: ok, keeps data (valuable), ready: server by its image's own check every 30s; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
ollama: ok, keeps models (rebuildable); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
only-office: ok, keeps data (rebuildable), lib (rebuildable), db (rebuildable), fonts (rebuildable), logs (cache), rabbitmq (cache), redis (cache); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
openai-consumer: ok
openrazer: ok, 3 tool(s)
pacman: ok, 15 tool(s); WARNING: mirror-refresh, cache-cleaning stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
photos-eef: ok; WARNING: client stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
photos-filip: ok; WARNING: client stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
picom: ok, 4 tool(s); WARNING: configuration ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
polychromatic: ok, 3 tool(s)
postgres: ok, keeps store (valuable), dumps (rebuildable), ready: server by tcp on database every 30s
power: ok, 5 tool(s), keeps state draw, ready: draw by unit every 30s; WARNING: logind-power ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: after-boot, before-shutdown stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
powerlevel10k: ok
records: ok, 6 tool(s), keeps checkout (rebuildable)
redis: ok, keeps data (cache), ready: server by tcp on cache every 30s
restic: ok, 3 tool(s), keeps repository (rebuildable), state (cache), ready: night by its tool backup_health every 1m0s; measure by unit every 30s
rofi: ok, 3 tool(s)
route-adapter: ok; WARNING: config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
route-proxy: ok, keeps acme (rebuildable), ca (cache); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
screen-lock: ok, 3 tool(s)
searxng: ok, keeps valkey (cache); WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: cache, server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
sensors: ok, 6 tool(s), ready: drives by unit every 30s; watch by its tool sensors_health every 1m0s
showcase: ok; WARNING: server, tools stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
slack: ok, 4 tool(s)
snapd: ok, 10 tool(s)
ssh-client: ok, 8 tool(s), keeps ssh (valuable)
sshd: ok; WARNING: run stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
step-ca: ok, keeps home (valuable), ready: server by its image's own check every 30s
sudo: ok, 4 tool(s)
supabase: ok, keeps db (valuable), dumps (rebuildable), storage (valuable), functions (valuable), db-config (rebuildable), ready: db by its image's own check every 30s; kong by its image's own check every 30s; meta by its image's own check every 30s; studio by its image's own check every 30s; WARNING: settings ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: vector, analytics, auth, rest, realtime, imgproxy, storage-api, edge-functions, pooler stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
systemd: ok
systemd-networkd: ok
systemd-resolved: ok, ready: service by unit every 30s; guard by unit every 30s
telegram: ok, 1 tool(s), keeps state offset, messages
time-sync: ok, 3 tool(s); WARNING: daemon stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
triggerhappy: ok, 4 tool(s); WARNING: service stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
umami: ok; WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
unifi: ok, keeps data (valuable); WARNING: runtime-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339); WARNING: server stay(s) up and say(s) not how it is ready — judged by liveness alone, refused from 2026-11-18 (ADR 0240 rule 8)
website: ok, ready: server by http / on web every 30s
xclip: ok, 4 tool(s)
xdg: ok, 5 tool(s); WARNING: user-dirs ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
xorg: ok, 9 tool(s)
xterm: ok, 2 tool(s)
zfs: ok, 15 tool(s), ready: watch by its tool zfs_health every 1m0s; events by unit every 30s; WARNING: scrub-config ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
zsh: ok, 1 tool(s); WARNING: tools-conf ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted: set at the terminal alone; say "trusted" false where nothing trusts it (novox/hq issue 339)
zsh-autosuggestions: ok
zsh-syntax-highlighting: ok
long-running resources without health: 69
files asking for a setting without saying whether it is trusted: 25
```
Re-review against review 55 (on #244, which this PR replaces). The branch is one commit on current main, and the tree holds no binary. .gitignore names both build outputs. go vet ./... is clean and go test -race -count=1 ./... passes. With a controller built from mesh-controller #257 head 63a99d4, MESH_GATE=… MESH_CHECK_MODULES=mesh-reads sh merge-check.sh exits 0. The red mesh/merge-gate and mesh/repo-check here come from the running controller lacking node-reads, and clear once #257 is live.
I reran my probes:
The link-flip race is closed.read answered the secret place's content 0 times in 20000 calls (was 3744). search, with an entry flipped between a regular file and a link into the secret place, answered it 0 times in 5000. openJudged checks the type first, opens with O_NONBLOCK|O_NOCTTY|O_CLOEXEC (plus O_NOFOLLOW in search), checks fstat again, and judges the path the kernel gives for the descriptor (/proc/self/fd). It refuses a deleted file.
The private-key block is withheld. All 28 lines of a generated RSA-2048 key in server.pem are withheld, and a line before the block is kept. Reads from line 10, a tail read (from -3) and a search across the key withheld every line of the block.
History files are refused by name, for example .zsh_history.
Devices and FIFOs are refused before any open, at once:/dev/null, /dev/ptmx, /dev/tty and a fifo.
/proc:/proc/self/environ, /proc/self/fd/N (including a deleted file) and /proc/thread-self/fd are refused by name. cmdline is refused as binary. /proc/loadavg and /proc/self/status are read.
A search from / stays on the root's file system. It skipped 6 other file systems and stopped at the 5000-file bound, which it names. The time bound is now checked inside a file too.
Minor, not blocking: the process-private rule matches only /proc/<pid>/<entry>, so /proc/<pid>/task/<tid>/environ and /proc/<pid>/task/<tid>/fd are not refused by name. environ is refused anyway as binary, and a file reached through fd is judged by its real path. A follow-up could also match task/*/ entries.
Merge order: mesh-sdk #23, then mesh-controller #257, then wait until mesh-controller.plans says done and recheck this PR's gate, then this PR. After merge, assign mesh-reads to novox first.
Verdict: approve at 994cab533bbd988f7e951040cbb6013d1a3441dc
Re-review against review 55 (on #244, which this PR replaces). The branch is one commit on current main, and the tree holds no binary. `.gitignore` names both build outputs. `go vet ./...` is clean and `go test -race -count=1 ./...` passes. With a controller built from mesh-controller #257 head 63a99d4, `MESH_GATE=… MESH_CHECK_MODULES=mesh-reads sh merge-check.sh` exits 0. The red `mesh/merge-gate` and `mesh/repo-check` here come from the running controller lacking `node-reads`, and clear once #257 is live.
I reran my probes:
- **The link-flip race is closed.** `read` answered the secret place's content 0 times in 20000 calls (was 3744). `search`, with an entry flipped between a regular file and a link into the secret place, answered it 0 times in 5000. `openJudged` checks the type first, opens with `O_NONBLOCK|O_NOCTTY|O_CLOEXEC` (plus `O_NOFOLLOW` in search), checks `fstat` again, and judges the path the kernel gives for the descriptor (`/proc/self/fd`). It refuses a deleted file.
- **The private-key block is withheld.** All 28 lines of a generated RSA-2048 key in `server.pem` are withheld, and a line before the block is kept. Reads from line 10, a tail read (`from -3`) and a search across the key withheld every line of the block.
- **History files are refused by name**, for example `.zsh_history`.
- **Devices and FIFOs are refused before any open, at once:** `/dev/null`, `/dev/ptmx`, `/dev/tty` and a fifo.
- **/proc:** `/proc/self/environ`, `/proc/self/fd/N` (including a deleted file) and `/proc/thread-self/fd` are refused by name. `cmdline` is refused as binary. `/proc/loadavg` and `/proc/self/status` are read.
- **A search from / stays on the root's file system.** It skipped 6 other file systems and stopped at the 5000-file bound, which it names. The time bound is now checked inside a file too.
- `go.mod` pins mesh-sdk 67bfa22 (#23's head).
Minor, not blocking: the process-private rule matches only `/proc/<pid>/<entry>`, so `/proc/<pid>/task/<tid>/environ` and `/proc/<pid>/task/<tid>/fd` are not refused by name. `environ` is refused anyway as binary, and a file reached through `fd` is judged by its real path. A follow-up could also match `task/*/` entries.
Merge order: mesh-sdk #23, then mesh-controller #257, then wait until `mesh-controller.plans` says done and recheck this PR's gate, then this PR. After merge, assign `mesh-reads` to novox first.
mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: new:modules/mesh-reads)
mesh/repo-check: PASS — its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
Delivery plan — builds new: modules/mesh-reads, sent nowhere; no bus step
read by no module's build: .gitignore
Run by the build seat on shanks as build-1791811865596626104 (builds --log build-1791811865596626104).
--- the gate: new:modules/mesh-reads
mesh-reads: 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 1 module(s) changed against 4 machine(s), as the snapshot of 2026-10-12T13:22:45Z 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-12T13:22:45Z
modules the change moves:
- mesh-reads (added)
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 0 module(s) in 0 tier(s)
notes:
- mesh-reads could not be tried on a machine: mesh-reads on f35 has no bus credential: nothing was issued for f35.mesh-reads, and a push would seal a placeholder its process cannot read (novox/hq issue 203). `module issue mesh-reads --node f35`, then push again
- .gitignore read by no module's build, and rebuild nothing (issue 280)
--- its merge-check.sh (go toolchain)
ok git.novox.be/novox/mesh-catalog/checks/words 0.003s
words: 12 retired words and 70 daemons' lines, none in the 43650 strings of 694 files
ok git.novox.be/novox/mesh-catalog/checks/agenthome 0.013s
agent-home: no archive and no file written into under the agent's home
ok git.novox.be/novox/mesh-catalog/checks/paths 0.006s
paths: no module names another's state on its machine (3 known, listed to go)
long-running resources without health: 69, as kept
ok git.novox.be/novox/mesh-catalog/checks/deps 0.259s
testing modules/mesh-reads
ok mesh-reads/cmd/mesh-reads 2.651s
--- its merge-check-typescript.sh (typescript toolchain)
**Merge check** at `994cab53`
- `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (modules: new:modules/mesh-reads)
- `mesh/repo-check`: **PASS** — its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
**Delivery plan** — builds new: modules/mesh-reads, sent nowhere; no bus step
- read by no module's build: .gitignore
Run by the build seat on shanks as `build-1791811865596626104` (`builds --log build-1791811865596626104`).
```
--- the gate: new:modules/mesh-reads
mesh-reads: 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 1 module(s) changed against 4 machine(s), as the snapshot of 2026-10-12T13:22:45Z 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-12T13:22:45Z
modules the change moves:
- mesh-reads (added)
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 0 module(s) in 0 tier(s)
notes:
- mesh-reads could not be tried on a machine: mesh-reads on f35 has no bus credential: nothing was issued for f35.mesh-reads, and a push would seal a placeholder its process cannot read (novox/hq issue 203). `module issue mesh-reads --node f35`, then push again
- .gitignore read by no module's build, and rebuild nothing (issue 280)
--- its merge-check.sh (go toolchain)
ok git.novox.be/novox/mesh-catalog/checks/words 0.003s
words: 12 retired words and 70 daemons' lines, none in the 43650 strings of 694 files
ok git.novox.be/novox/mesh-catalog/checks/agenthome 0.013s
agent-home: no archive and no file written into under the agent's home
ok git.novox.be/novox/mesh-catalog/checks/paths 0.006s
paths: no module names another's state on its machine (3 known, listed to go)
long-running resources without health: 69, as kept
ok git.novox.be/novox/mesh-catalog/checks/deps 0.259s
testing modules/mesh-reads
ok mesh-reads/cmd/mesh-reads 2.651s
--- its merge-check-typescript.sh (typescript toolchain)
```
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.
Replaces #244 (review 55). This is one commit on a fresh branch from main, so the built binary that #244's first commit carried never appears.
.gitignorenow names the build outputs. Everything #244's description says still holds; below is what changed for review 55.Required 1: what was opened is judged, not the name (
openJudgedinreads.go). It is used byread,listandsearch.O_RDONLY|O_NONBLOCK|O_NOCTTY|O_CLOEXEC, plusO_NOFOLLOWin a search andO_DIRECTORYfor a list./proc/self/fd/<n>is judged by name. A path that is not absolute, or ends in(deleted), is refused.TestALinkFlippedDuringAReadNeverReadsASecretPlace: a goroutine flips a link between a plain file and the module's own broker under a secret place, during 5000 reads and 5000 searches. Nothing leaks. With #244's code the same test fails.Required 2: key blocks. Every line from a
-----BEGINthrough its-----ENDis withheld in a read and in a search. New testTestEveryLineOfAKeyBlockIsWithhelduses a generated RSA-2048 PKCS#8 key inserver.pem; with #244's code it fails.Required 3, and the should-items:
.mozilla,.thunderbird,.config/google-chrome,chromium,BraveSoftware,vivaldi,microsoft-edge),/proc/<pid>/{environ,mem,fd,map_files,root,cwd},/etc/rancherand/etc/kubernetes/admin.conf. New testTestHistoriesProfilesAndProcessesAreRefusedByName; it fails with #244's code.other-file-systems-skipped. This also keeps/procand/sysout unless the search starts inside them. The 20-second time bound is now checked every 1000 lines inside a file too.go.modpins mesh-sdk #23's new head,v0.1.14-0.20261012122749-67bfa22132f2(review 53's fixes). I will move it to the merged commit once #23 merges.Checks run here.
go vetpasses, andgo test -race ./...passes in the module.MESH_GATE=<controller from mesh-controller #257 at 63a99d4> MESH_CHECK_MODULES=mesh-reads sh merge-check.shpasses: 69 resources without health, as kept.mesh/merge-gatehere stays red until #257 runs. The running controller has nonode-readsseat.Group. This branch is
fix/418-node-reads-2, so it is not in thefix/418-node-readsdelivery group with mesh-sdk #23 and mesh-controller #257. That does not change the order: #23, then #257 and its rollout done, then this.Part of issue 418. Not merged.
Delivery
novox/mesh-catalog@994cab533bbd— delivered since 2026-10-12T14:52:28ZDelivery plan — builds new: modules/mesh-reads, sent nowhere; no bus step
Transitions
The commit's note under
refs/notes/mesh-plankeeps every transition:git log --notes=mesh-plan.Merge check at
994cab53mesh/merge-gate: FAIL — a manifest the change touches fails the module check: modules/mesh-reads/module.json: this manifest cannot be used: (modules: new:modules/mesh-reads)mesh/repo-check: FAIL — its merge-check.sh failed: files asking for a setting without saying whether it is trusted: 25Delivery plan — builds new: modules/mesh-reads, sent nowhere; no bus step
Run by the build seat on g14 as
build-1791808383039663245(builds --log build-1791808383039663245).Verdict: approve at
994cab533bRe-review against review 55 (on #244, which this PR replaces). The branch is one commit on current main, and the tree holds no binary.
.gitignorenames both build outputs.go vet ./...is clean andgo test -race -count=1 ./...passes. With a controller built from mesh-controller #257 head 63a99d4,MESH_GATE=… MESH_CHECK_MODULES=mesh-reads sh merge-check.shexits 0. The redmesh/merge-gateandmesh/repo-checkhere come from the running controller lackingnode-reads, and clear once #257 is live.I reran my probes:
readanswered the secret place's content 0 times in 20000 calls (was 3744).search, with an entry flipped between a regular file and a link into the secret place, answered it 0 times in 5000.openJudgedchecks the type first, opens withO_NONBLOCK|O_NOCTTY|O_CLOEXEC(plusO_NOFOLLOWin search), checksfstatagain, and judges the path the kernel gives for the descriptor (/proc/self/fd). It refuses a deleted file.server.pemare withheld, and a line before the block is kept. Reads from line 10, a tail read (from -3) and a search across the key withheld every line of the block..zsh_history./dev/null,/dev/ptmx,/dev/ttyand a fifo./proc/self/environ,/proc/self/fd/N(including a deleted file) and/proc/thread-self/fdare refused by name.cmdlineis refused as binary./proc/loadavgand/proc/self/statusare read.go.modpins mesh-sdk 67bfa22 (#23's head).Minor, not blocking: the process-private rule matches only
/proc/<pid>/<entry>, so/proc/<pid>/task/<tid>/environand/proc/<pid>/task/<tid>/fdare not refused by name.environis refused anyway as binary, and a file reached throughfdis judged by its real path. A follow-up could also matchtask/*/entries.Merge order: mesh-sdk #23, then mesh-controller #257, then wait until
mesh-controller.planssays done and recheck this PR's gate, then this PR. After merge, assignmesh-readsto novox first.Merge check at
994cab53mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: new:modules/mesh-reads)mesh/repo-check: PASS — its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)Delivery plan — builds new: modules/mesh-reads, sent nowhere; no bus step
Run by the build seat on shanks as
build-1791811865596626104(builds --log build-1791811865596626104).