nats: say every bus user's slow consumer and closed connection on the bus (hq issue 270, ADR 0357) #293

Closed
mesh-admin wants to merge 2 commits from fix/270-nats-emits-bus-faults into main
Contributor

Replaces #292, taken out of its delivery group. It needs the controller of mesh-controller #326 (merged) to be live: the controller before it refuses a bus module that declares events. Its own delivery then waits for the operator's bus upgrade. The heartbeat it adds is raised by mesh-controller #327.

What

  • modules/nats/cmd/nats-tools/watch.go: a watch beside the tools reads the server's record of closed connections every 30 seconds, newest first (sort=stop, 256 a page) back to one interval before its last whole read (the first look: the last hour), and publishes, through the runtime, bus.slow-consumer for each connection closed as a slow consumer and bus.connection-closed for each closed for breaking the bus's rules (any reason not on the routine list). Each names the user, connection name and id, reason, opened, closed, lived and pending bytes; never a credential.
  • Said at least once: closures said are remembered by user, connection id and opening time; a failed publish is retried at every look until said or older than the hour, then forgotten.
  • A dead watch is heard (review 274): a look that panics is recovered and counted, and the loop goes on. Every look ends with a bus.watch heartbeat: healthy, or not with why — not healthy when the record has not been read whole for three looks (90 s, after the same grace from start) or a closure stayed unpublished that long. mesh-controller #327 raises a silent or blind watch as bus-watch-dead. A health check on the bus container was the other option; the module check refuses a module judged only by its own tool (ADR 0240 rule 2), so the heartbeat it is.
  • Tool nats_bus_watch: healthy and why, last look and read, counts said, newest said, faults recovered, reasons not said, anything not published.
  • module.json: emits bus.slow-consumer, bus.connection-closed, bus.watch; tools gains nats_bus_watch.

Why

The server records the user of every connection it closes as a slow consumer and says it nowhere the controller hears (issue 270, open question 2). Decided in ADR 0357. Refused subjects: issue 702.

Tested

watch_test.go, 13 tests, all failing on main: routine closures not said, none said twice, failed publish retried and forgotten after the hour, last hour said on start, reused connection id, unreadable record said, a watch blind for three looks beats not healthy and recovers, a closure unpublished three looks is not healthy, a panicking look recovered and the next look says, a later look reads one page back to the last look only, the manifest's tools, emits and bounds. MESH_GATE=<controller of #327> MESH_CHECK_MODULES=nats sh merge-check.sh: exit 0.

Delivery note: nats is the bus; it waits for the planned bus step a person starts (ADR 0236). The server image does not change.

Fixes issue 270

Replaces #292, taken out of its delivery group. It needs the controller of mesh-controller #326 (merged) to be live: the controller before it refuses a bus module that declares events. Its own delivery then waits for the operator's bus upgrade. The heartbeat it adds is raised by mesh-controller #327. ## What - `modules/nats/cmd/nats-tools/watch.go`: a watch beside the tools reads the server's record of closed connections every 30 seconds, newest first (`sort=stop`, 256 a page) back to one interval before its last whole read (the first look: the last hour), and publishes, through the runtime, `bus.slow-consumer` for each connection closed as a slow consumer and `bus.connection-closed` for each closed for breaking the bus's rules (any reason not on the routine list). Each names the user, connection name and id, reason, opened, closed, lived and pending bytes; never a credential. - Said at least once: closures said are remembered by user, connection id and opening time; a failed publish is retried at every look until said or older than the hour, then forgotten. - **A dead watch is heard (review 274):** a look that panics is recovered and counted, and the loop goes on. Every look ends with a `bus.watch` heartbeat: healthy, or not with why — not healthy when the record has not been read whole for three looks (90 s, after the same grace from start) or a closure stayed unpublished that long. mesh-controller #327 raises a silent or blind watch as `bus-watch-dead`. A health check on the bus container was the other option; the module check refuses a module judged only by its own tool (ADR 0240 rule 2), so the heartbeat it is. - Tool `nats_bus_watch`: healthy and why, last look and read, counts said, newest said, faults recovered, reasons not said, anything not published. - `module.json`: `emits` bus.slow-consumer, bus.connection-closed, bus.watch; `tools` gains `nats_bus_watch`. ## Why The server records the user of every connection it closes as a slow consumer and says it nowhere the controller hears (issue 270, open question 2). Decided in ADR 0357. Refused subjects: issue 702. ## Tested `watch_test.go`, 13 tests, all failing on main: routine closures not said, none said twice, failed publish retried and forgotten after the hour, last hour said on start, reused connection id, unreadable record said, a watch blind for three looks beats not healthy and recovers, a closure unpublished three looks is not healthy, a panicking look recovered and the next look says, a later look reads one page back to the last look only, the manifest's tools, emits and bounds. `MESH_GATE=<controller of #327> MESH_CHECK_MODULES=nats sh merge-check.sh`: exit 0. **Delivery note:** nats is the bus; it waits for the planned bus step a person starts (ADR 0236). The server image does not change. Fixes issue 270
mesh-admin added 1 commit 2026-10-14 06:58:01 +00:00
Say every bus user's slow consumer and closed connection on the bus (hq issue 270, ADR 0357)
mesh/delivery-group group fix/270-the-bus-module-says-every-users-slow-consumer rejected: a member's own check failed
mesh/delivery stopped: the pull request closed unmerged
mesh/merge-gate head 9e50c1eb36f0 merged into trunk a44d490d974c — fail: builds nats, sent nowhere; merging this needs a person's bus upgrade; 1 wait(s) fo…
mesh/repo-check head 9e50c1eb36f0 merged into trunk a44d490d974c — fail: its merge-check.sh failed: files asking for a setting without saying whether it is…
9e50c1eb36
The server records the user of every connection it closes as a slow consumer
or for breaking its rules, and says it nowhere the controller hears. The nats
tools bundle now reads that record every 30 seconds and publishes
bus.slow-consumer and bus.connection-closed, naming the user, never a credential.
Author
Contributor

Merge check at 9e50c1eb
Judged: head 9e50c1eb36f0 merged into trunk a44d490d974c; read beside it: mesh-controller 2959c8143536, mesh-controller-main 3479a35462b2, mesh-host 1a2677882380, mesh-tools 954e1a53eef9

  • mesh/merge-gate: FAIL — a manifest the change touches fails the module check: modules/nats/module.json: this manifest cannot be used: (modules: nats)
  • mesh/repo-check: FAIL — its merge-check.sh failed: files asking for a setting without saying whether it is trusted: 25

Delivery plan — builds nats, sent nowhere; merging this needs a person's bus upgrade; 1 wait(s) for a person

  • tier 0: nats
  • novox: waits for a person: nats
  • merging this needs a person's bus upgrade: nats is never sent by an ordinary send, and until mesh_call mesh-controller.bus {"upgrade": "true", "why": "…", "reversible" or "irreversible": "true"} runs, nothing else is sent to novox either — unless the new build turns out the same as the one running there (issue 280)
  • nats provides mesh-bus: its consumers are sent again after it
  • nats keeps data (ADR 0233): what it holds is backed up before it moves

Run by the build seat on shanks as build-1791961085211379849 (builds --log build-1791961085211379849).

--- the gate: nats
modules/nats/module.json: this manifest cannot be used:
  - nats holds mesh-broker and declares a bus account, which is granted the bus's snapshot API and nothing else (novox/hq ADR 0235); its emits would be granted nothing
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
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)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 0
1 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
--- 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 46921 strings of 719 files
ok  	git.novox.be/novox/mesh-catalog/checks/agenthome	0.018s
agent-home: no archive and no file written into under the agent's home
ok  	git.novox.be/novox/mesh-catalog/checks/secrets	0.013s
secrets: no setting can replace a vault secret in a mergeable file (1 known, nested)
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)
mesh-controller: 1 problem(s) in 128 manifest(s)
modules/nats/module.json: this manifest cannot be used:
  - nats holds mesh-broker and declares a bus account, which is granted the bus's snapshot API and nothing else (novox/hq ADR 0235); its emits would be granted nothing
adwaita: ok, 4 tool(s)
artifact-store-tools: ok, 4 tool(s), invokes seat:mesh-controller.artifacts, seat:mesh-controller.collect, mesh-catalog.catalog_modules, mesh-catalog.catalog_module
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, 17 tool(s), invokes seat:mesh-controller.settings, seat:mesh-controller.nodes, seat:mesh-controller.node, betterbird.betterbird_derive
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), ready: server by exec every 10s
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, 48 tool(s), keeps state servers, holdings, config, proposals, questions, memory, 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)
dev-tools: ok
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, 2 tool(s), ready: watch by its tool fail2ban_health every 1m0s; run by unit every 30s
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), ready: server by http /api/healthz on web expecting 200 every 30s
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: 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)
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, seat:mesh-controller.forget-checks, 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, gitea.gitea_pull_reviews, 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-reads: ok
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), ready: server by http /healthz/readiness on web expecting 200 every 30s; WARNING: 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)
netcheck: ok, 5 tool(s)
networkmanager: ok
nextcloud: ok, keeps html (valuable), ready: server by http /status.php on web expecting 200 every 30s
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), ready: server by tcp on http every 10s
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, ready: server by http /api/share/mesh-health on web expecting 404 every 30s
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: 61
files asking for a setting without saying whether it is trusted: 25
**Merge check** at `9e50c1eb` Judged: head `9e50c1eb36f0` merged into trunk `a44d490d974c`; read beside it: mesh-controller `2959c8143536`, mesh-controller-main `3479a35462b2`, mesh-host `1a2677882380`, mesh-tools `954e1a53eef9` - `mesh/merge-gate`: **FAIL** — a manifest the change touches fails the module check: modules/nats/module.json: this manifest cannot be used: (modules: nats) - `mesh/repo-check`: **FAIL** — its merge-check.sh failed: files asking for a setting without saying whether it is trusted: 25 **Delivery plan** — builds nats, sent nowhere; merging this needs a person's bus upgrade; 1 wait(s) for a person - tier 0: nats - novox: waits for a person: nats - merging this needs a person's bus upgrade: nats is never sent by an ordinary send, and until `mesh_call mesh-controller.bus {"upgrade": "true", "why": "…", "reversible" or "irreversible": "true"}` runs, nothing else is sent to novox either — unless the new build turns out the same as the one running there (issue 280) - nats provides mesh-bus: its consumers are sent again after it - nats keeps data (ADR 0233): what it holds is backed up before it moves Run by the build seat on shanks as `build-1791961085211379849` (`builds --log build-1791961085211379849`). ``` --- the gate: nats modules/nats/module.json: this manifest cannot be used: - nats holds mesh-broker and declares a bus account, which is granted the bus's snapshot API and nothing else (novox/hq ADR 0235); its emits would be granted nothing 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 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) long-running resources without health: 1 files asking for a setting without saying whether it is trusted: 0 1 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here --- 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 46921 strings of 719 files ok git.novox.be/novox/mesh-catalog/checks/agenthome 0.018s agent-home: no archive and no file written into under the agent's home ok git.novox.be/novox/mesh-catalog/checks/secrets 0.013s secrets: no setting can replace a vault secret in a mergeable file (1 known, nested) 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) mesh-controller: 1 problem(s) in 128 manifest(s) modules/nats/module.json: this manifest cannot be used: - nats holds mesh-broker and declares a bus account, which is granted the bus's snapshot API and nothing else (novox/hq ADR 0235); its emits would be granted nothing adwaita: ok, 4 tool(s) artifact-store-tools: ok, 4 tool(s), invokes seat:mesh-controller.artifacts, seat:mesh-controller.collect, mesh-catalog.catalog_modules, mesh-catalog.catalog_module 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, 17 tool(s), invokes seat:mesh-controller.settings, seat:mesh-controller.nodes, seat:mesh-controller.node, betterbird.betterbird_derive 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), ready: server by exec every 10s 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, 48 tool(s), keeps state servers, holdings, config, proposals, questions, memory, 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) dev-tools: ok 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, 2 tool(s), ready: watch by its tool fail2ban_health every 1m0s; run by unit every 30s 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), ready: server by http /api/healthz on web expecting 200 every 30s 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: 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) 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, seat:mesh-controller.forget-checks, 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, gitea.gitea_pull_reviews, 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-reads: ok 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), ready: server by http /healthz/readiness on web expecting 200 every 30s; WARNING: 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) netcheck: ok, 5 tool(s) networkmanager: ok nextcloud: ok, keeps html (valuable), ready: server by http /status.php on web expecting 200 every 30s 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), ready: server by tcp on http every 10s 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, ready: server by http /api/share/mesh-health on web expecting 404 every 30s 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: 61 files asking for a setting without saying whether it is trusted: 25 ```
mesh-admin left a comment
Author
Contributor

Verdict: changes needed at 9e50c1eb36 (one small one): the code is sound and leaks no credential, but a watch that stops or cannot read is heard by nobody.

Independent review for issue 270 under ADR 0357 (the nats module's watch, its two events, nats_bus_watch).

Checks at this head, still those of the same commit under the closed #292, judged beside mesh-controller 2959c814: mesh/merge-gate FAILURE ("FAIL — a manifest the change touches fails the module check: modules/nats/module.json ... its emits would be granted nothing"; the gate's line also says "merging this needs a person's bus upgrade"), mesh/repo-check FAILURE ("its merge-check.sh failed: files asking for a setting without saying whether it is trusted: 25", from the same manifest problem), mesh/delivery error ("stopped: the pull request closed unmerged", #292's), mesh/delivery-group FAILURE (06:44:41, "rejected: a member's own check failed"). As expected: they need mesh-controller #326 merged and this head checked again. Note for the operator that the merge gate expects a person's bus upgrade for nats.

  1. No credential reaches an event. Closures() reads /connz?state=closed&auth=1 into a fixed struct (cid, name, authorized_user, start, stop, reason, pending_bytes), so any other field the server serves (an nkey or jwt, for instance) is dropped. The event is the Closure type: user, connection name, cid, reason, opened, closed, lived, pending. The test record carries a password-shaped field and fails if "password" or its value is ever published. The connection name is a label the client chooses.
  2. Rules: every reason except the routine ones (client closed, stale, read/write error, TLS handshake, authentication timeout or failure, server shutdown) is said, an unknown reason included; a closure with no user is skipped. The two events are split by the "Slow Consumer" prefix. Identity is user, cid and opening time, so a reused cid after a restart is a new closure (tested). The first look is one interval in and reads the last hour again (tested); a failed publish stays out of the said set and is retried (tested). stdio.Emit takes the SDK's lock, so the watch's writes do not interleave with MCP replies.
  3. The change asked: when the watch fails, nobody hears it. Run() recovers a panic, records "stopped" and returns, so the watch is dead until the bundle restarts. A Look that cannot read the record writes stderr and last_error. Both show only in nats_bus_watch, which nobody polls. The controller's bus-faults-unread covers the read-back, not the watch, so a dead watch reads as "no user had a slow consumer", which is issue 270's blindness again. Smallest fix: on a panic, exit the bundle so the runtime restarts it (the first look then says the last hour again), or restart the loop; and say a look that has failed for some minutes in a way the mesh hears (the module's health tool, or an event the controller raises).
  4. Smaller points, not blocking: the failed map is never pruned, so a closure whose publish kept failing until it left the hour stays in not_published for good; prune it with said. Each look reads the whole record, up to 10,000 closed connections, every 30 s; sort=stop with a smaller limit would read only the recent ones.

Niced on g14 (modules/nats): go vet clean; go test ./... ok, the 7 watch tests included.

Merge order: mesh-controller #326 first, then this one after a fresh check and the person's bus upgrade the gate names.

Reviewed by an independent reviewer on g14.

Verdict: changes needed at 9e50c1eb36f0 (one small one): the code is sound and leaks no credential, but a watch that stops or cannot read is heard by nobody. Independent review for issue 270 under ADR 0357 (the nats module's watch, its two events, nats_bus_watch). Checks at this head, still those of the same commit under the closed #292, judged beside mesh-controller 2959c814: mesh/merge-gate FAILURE ("FAIL — a manifest the change touches fails the module check: modules/nats/module.json ... its emits would be granted nothing"; the gate's line also says "merging this needs a person's bus upgrade"), mesh/repo-check FAILURE ("its merge-check.sh failed: files asking for a setting without saying whether it is trusted: 25", from the same manifest problem), mesh/delivery error ("stopped: the pull request closed unmerged", #292's), mesh/delivery-group FAILURE (06:44:41, "rejected: a member's own check failed"). As expected: they need mesh-controller #326 merged and this head checked again. Note for the operator that the merge gate expects a person's bus upgrade for nats. 1. No credential reaches an event. Closures() reads /connz?state=closed&auth=1 into a fixed struct (cid, name, authorized_user, start, stop, reason, pending_bytes), so any other field the server serves (an nkey or jwt, for instance) is dropped. The event is the Closure type: user, connection name, cid, reason, opened, closed, lived, pending. The test record carries a password-shaped field and fails if "password" or its value is ever published. The connection name is a label the client chooses. 2. Rules: every reason except the routine ones (client closed, stale, read/write error, TLS handshake, authentication timeout or failure, server shutdown) is said, an unknown reason included; a closure with no user is skipped. The two events are split by the "Slow Consumer" prefix. Identity is user, cid and opening time, so a reused cid after a restart is a new closure (tested). The first look is one interval in and reads the last hour again (tested); a failed publish stays out of the said set and is retried (tested). stdio.Emit takes the SDK's lock, so the watch's writes do not interleave with MCP replies. 3. The change asked: when the watch fails, nobody hears it. Run() recovers a panic, records "stopped" and returns, so the watch is dead until the bundle restarts. A Look that cannot read the record writes stderr and last_error. Both show only in nats_bus_watch, which nobody polls. The controller's bus-faults-unread covers the read-back, not the watch, so a dead watch reads as "no user had a slow consumer", which is issue 270's blindness again. Smallest fix: on a panic, exit the bundle so the runtime restarts it (the first look then says the last hour again), or restart the loop; and say a look that has failed for some minutes in a way the mesh hears (the module's health tool, or an event the controller raises). 4. Smaller points, not blocking: the `failed` map is never pruned, so a closure whose publish kept failing until it left the hour stays in not_published for good; prune it with `said`. Each look reads the whole record, up to 10,000 closed connections, every 30 s; `sort=stop` with a smaller limit would read only the recent ones. Niced on g14 (modules/nats): go vet clean; go test ./... ok, the 7 watch tests included. Merge order: mesh-controller #326 first, then this one after a fresh check and the person's bus upgrade the gate names. Reviewed by an independent reviewer on g14.
jschoubben added 1 commit 2026-10-14 07:19:59 +00:00
Keep the nats watch alive and heard: recover a faulted look, beat after every look, read only what closed since (hq issue 270, review 274)
mesh/merge-gate out of date: judged against trunk a44d490d974c, the trunk is now b15846dd6e78; judged again on a recheck or when it is merged
mesh/repo-check out of date: judged against trunk a44d490d974c, the trunk is now b15846dd6e78; judged again on a recheck or when it is merged
mesh/delivery closed: the pull request closed unmerged
mesh/check checking 950e37a46e8d on 573a59e3cc07
950e37a46e
A watch that panicked stopped for good, and one that could not read said so
only to stderr, so a dead watch read as no slow consumers. A faulted look is
now recovered and the loop goes on; every look ends with a bus.watch
heartbeat saying whether the watch is healthy, which the controller raises
when it stops or says it cannot see. The record is read newest first back to
the last look, and closures that could not be published are forgotten after
the hour.
Author
Contributor

Delivery novox/mesh-catalog@950e37a46e8d — closed since 2026-10-25T17:26:57Z

Transitions

  • 2026-10-14 07:20 (new) → proposed (announced): novox/mesh-catalog#293's head announced
  • 2026-10-14 07:22 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
  • 2026-10-14 07:22 checked → rejected (refused): the gate failed or could not run, or the repository's own check failed
  • 2026-10-25 13:38 rejected → proposed (recheck): its mesh/check judged it again: pass 950e37a46e on 68f7431d98 | unit 1981 run, 2334 kept, 5 skipped | integration 2003 run, 2353 kept, 9 skipped | …
  • 2026-10-25 13:38 proposed → ready (accepted): a verdict names this commit and the trunk's head as its trunk commit, the gate passed or warned, and the repository's own check did not fail
  • 2026-10-25 15:07 ready → proposed (trunk moved): out of date: judged against trunk 68f7431d98, the trunk is now f27f4c8cd58c; judged again on a recheck or when it is merged
  • 2026-10-25 15:08 proposed → rejected (refused): a verdict names this commit and the trunk's head as its trunk commit, and the gate failed or could not run, or the repository's own check failed
  • 2026-10-25 16:48 rejected → proposed (recheck): its mesh/check judged it again: pass 950e37a46e on a85d903741 | unit 1994 run, 2334 kept, 5 skipped | integration 2016 run, 2353 kept, 9 skipped | …
  • 2026-10-25 16:48 proposed → ready (accepted): a verdict names this commit and the trunk's head as its trunk commit, the gate passed or warned, and the repository's own check did not fail
  • 2026-10-25 17:02 ready → proposed (trunk moved): out of date: judged against trunk a85d903741, the trunk is now 2df0503034dc; judged again on a recheck or when it is merged
  • 2026-10-25 17:26 proposed → closed (closed): the pull request closed unmerged

The commit's note under refs/notes/mesh-plan keeps every transition of this change up to its merge: git log --notes=mesh-plan.

<!-- mesh-delivery:view --> **Delivery** `novox/mesh-catalog@950e37a46e8d` — **closed** since 2026-10-25T17:26:57Z **Transitions** - 2026-10-14 07:20 (new) → proposed (announced): novox/mesh-catalog#293's head announced - 2026-10-14 07:22 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit - 2026-10-14 07:22 checked → rejected (refused): the gate failed or could not run, or the repository's own check failed - 2026-10-25 13:38 rejected → proposed (recheck): its mesh/check judged it again: pass 950e37a46e8d on 68f7431d98d7 | unit 1981 run, 2334 kept, 5 skipped | integration 2003 run, 2353 kept, 9 skipped | … - 2026-10-25 13:38 proposed → ready (accepted): a verdict names this commit and the trunk's head as its trunk commit, the gate passed or warned, and the repository's own check did not fail - 2026-10-25 15:07 ready → proposed (trunk moved): out of date: judged against trunk 68f7431d98d7, the trunk is now f27f4c8cd58c; judged again on a recheck or when it is merged - 2026-10-25 15:08 proposed → rejected (refused): a verdict names this commit and the trunk's head as its trunk commit, and the gate failed or could not run, or the repository's own check failed - 2026-10-25 16:48 rejected → proposed (recheck): its mesh/check judged it again: pass 950e37a46e8d on a85d90374195 | unit 1994 run, 2334 kept, 5 skipped | integration 2016 run, 2353 kept, 9 skipped | … - 2026-10-25 16:48 proposed → ready (accepted): a verdict names this commit and the trunk's head as its trunk commit, the gate passed or warned, and the repository's own check did not fail - 2026-10-25 17:02 ready → proposed (trunk moved): out of date: judged against trunk a85d90374195, the trunk is now 2df0503034dc; judged again on a recheck or when it is merged - 2026-10-25 17:26 proposed → closed (closed): the pull request closed unmerged The commit's note under `refs/notes/mesh-plan` keeps every transition of this change up to its merge: `git log --notes=mesh-plan`.
Author
Contributor

Merge check at 950e37a4
Judged: head 950e37a46e8d merged into trunk a44d490d974c; read beside it: mesh-controller 04730b54a8f2, mesh-controller-main 04730b54a8f2, mesh-host 1a2677882380, mesh-tools 954e1a53eef9

  • mesh/merge-gate: FAIL — 1 problem(s) the change brings; the first: modules/nats: nats is not registrable — this manifest cannot be used: - nats holds mesh-broker and declares a bus account, which is granted the bus's snapshot API and nothing else (novox/hq ADR 0235); its emits would be granted nothing (modules: nats)
  • 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 nats, sent nowhere; merging this needs a person's bus upgrade; 1 wait(s) for a person

  • tier 0: nats
  • novox: waits for a person: nats
  • merging this needs a person's bus upgrade: nats is never sent by an ordinary send, and until mesh_call mesh-controller.bus {"upgrade": "true", "why": "…", "reversible" or "irreversible": "true"} runs, nothing else is sent to novox either — unless the new build turns out the same as the one running there (issue 280)
  • nats provides mesh-bus: its consumers are sent again after it
  • nats keeps data (ADR 0233): what it holds is backed up before it moves

Run by the build seat on shanks as build-1791962410549175769 (builds --log build-1791962410549175769).

--- the gate: nats
nats: ok, 10 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)
long-running resources without health: 1
files asking for a setting without saying whether it is trusted: 0
1 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-14T07:16:52Z 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: FAIL — 1 problem(s) the change brings; the first: modules/nats: nats is not registrable — this manifest cannot be used: - nats holds mesh-broker and declares a bus account, which is granted the bus's snapshot API and nothing else (novox/hq ADR 0235); its emits would be granted nothing
judged by controller development build against the facts of 2026-10-14T07:16:52Z

fails:
  - modules/nats: nats is not registrable — this manifest cannot be used: - nats holds mesh-broker and declares a bus account, which is granted the bus's snapshot API and nothing else (novox/hq ADR 0235); its emits would be granted nothing

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): nats
mesh-controller: the change fails the merge gate
--- 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 46941 strings of 719 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/secrets	0.012s
secrets: no setting can replace a vault secret in a mergeable file (1 known, nested)
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: 62, as kept
ok  	git.novox.be/novox/mesh-catalog/checks/deps	0.212s
testing modules/nats
ok  	nats-tools/cmd/nats-tools	6.363s
--- its merge-check-typescript.sh (typescript toolchain)
**Merge check** at `950e37a4` Judged: head `950e37a46e8d` merged into trunk `a44d490d974c`; read beside it: mesh-controller `04730b54a8f2`, mesh-controller-main `04730b54a8f2`, mesh-host `1a2677882380`, mesh-tools `954e1a53eef9` - `mesh/merge-gate`: **FAIL** — 1 problem(s) the change brings; the first: modules/nats: nats is not registrable — this manifest cannot be used: - nats holds mesh-broker and declares a bus account, which is granted the bus's snapshot API and nothing else (novox/hq ADR 0235); its emits would be granted nothing (modules: nats) - `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 nats, sent nowhere; merging this needs a person's bus upgrade; 1 wait(s) for a person - tier 0: nats - novox: waits for a person: nats - merging this needs a person's bus upgrade: nats is never sent by an ordinary send, and until `mesh_call mesh-controller.bus {"upgrade": "true", "why": "…", "reversible" or "irreversible": "true"}` runs, nothing else is sent to novox either — unless the new build turns out the same as the one running there (issue 280) - nats provides mesh-bus: its consumers are sent again after it - nats keeps data (ADR 0233): what it holds is backed up before it moves Run by the build seat on shanks as `build-1791962410549175769` (`builds --log build-1791962410549175769`). ``` --- the gate: nats nats: ok, 10 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) long-running resources without health: 1 files asking for a setting without saying whether it is trusted: 0 1 manifest(s) checked. Judged against the seats this binary carries; a claim on one of the mesh's own seats is judged fully at registration, and a seat declared by a module not given here reads as unknown. Identities judged on a 6-character machine name, against the bounds of the providers given here judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-14T07:16:52Z 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: FAIL — 1 problem(s) the change brings; the first: modules/nats: nats is not registrable — this manifest cannot be used: - nats holds mesh-broker and declares a bus account, which is granted the bus's snapshot API and nothing else (novox/hq ADR 0235); its emits would be granted nothing judged by controller development build against the facts of 2026-10-14T07:16:52Z fails: - modules/nats: nats is not registrable — this manifest cannot be used: - nats holds mesh-broker and declares a bus account, which is granted the bus's snapshot API and nothing else (novox/hq ADR 0235); its emits would be granted nothing 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): nats mesh-controller: the change fails the merge gate --- 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 46941 strings of 719 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/secrets 0.012s secrets: no setting can replace a vault secret in a mergeable file (1 known, nested) 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: 62, as kept ok git.novox.be/novox/mesh-catalog/checks/deps 0.212s testing modules/nats ok nats-tools/cmd/nats-tools 6.363s --- its merge-check-typescript.sh (typescript toolchain) ```
Member

mesh-delivery: not merged. This pull request's checks passed at 950e37a46e, and now its check failed: failed: shanks: the check of novox/mesh-catalog#293 failed: beside novox/mesh-catalog: git fetch: error: | 950e37a46e on f27f4c8cd5 | u… (head 950e37a46e merged into trunk f27f4c8cd5). A new head, or a recheck that passes, asks the operator again.

mesh-delivery: **not merged.** This pull request's checks passed at 950e37a46e8dad69dec53afd68d78f46ce4d34df, and now its check failed: failed: shanks: the check of novox/mesh-catalog#293 failed: beside novox/mesh-catalog: git fetch: error: | 950e37a46e8d on f27f4c8cd58c | u… (head 950e37a46e8d merged into trunk f27f4c8cd58c). A new head, or a recheck that passes, asks the operator again.
mesh-tools closed this pull request 2026-10-25 17:26:55 +00:00

Pull request closed

Please reopen this pull request to perform a merge.
Sign in to join this conversation.
No Reviewers
3 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: novox/mesh-catalog#293