nats: say whether a user's grant is in force on the running server (review of hq issue 353) #166

Merged
mesh-admin merged 1 commits from feat/353-the-bus-says-a-grant-is-in-force into main 2026-10-12 12:13:26 +00:00
Contributor

Follow-up to the review of mesh-controller #186 (hq issue 353, hq #253). The controller needs to know whether the bus enforces its grant to ask, not only whether the list was sent: on 2026-10-09 the grant was written at 17:55:56 and enforced from the reload at 17:56:05.

What changes

  • nats_user_can keeps its answer (allowed, by) and adds in_force, file_written, server_loaded, why.
  • in_force is true only when the user list on the machine allows it and the server's config_load_time (from /varz) is at or after the list's last write (stat -c %y inside the container, to the nanosecond; checked against the pinned image, nats:2.11.17-alpine).
  • Anything not known is not in force, said in why: the write time unreadable, /varz unreadable, or a server that gives no load time.

Reviewers' checklist

  • Read only: docker exec … stat, and /varz, which the tools already read. Nothing changes the bus.
  • Fails closed: every unknown is in_force: false.
  • Test TestAGrantIsInForceOnlyWhenTheServerReloadedAfterTheListWasWritten (six cases). Mutation: taking the load-time comparison out fails the case "reloaded before the write".

Checks. MESH_GATE=<controller at main 7477346> MESH_CHECK_MODULES=nats sh merge-check.sh passes locally on the merge result (this branch contains main at ac7400d).

Order. This first, assigned and live on the machine holding the bus. Then mesh-controller's follow-up (fix/353-the-asker-judges-the-controllers-own-grant), which asks for in_force and asks the operator nothing while the bus module does not say it (an older module is not a yes). Do not merge without review.

Follow-up to the review of mesh-controller #186 (hq issue 353, hq #253). The controller needs to know whether the bus **enforces** its grant to ask, not only whether the list was sent: on 2026-10-09 the grant was written at 17:55:56 and enforced from the reload at 17:56:05. **What changes** - `nats_user_can` keeps its answer (`allowed`, `by`) and adds `in_force`, `file_written`, `server_loaded`, `why`. - `in_force` is true only when the user list on the machine allows it **and** the server's `config_load_time` (from `/varz`) is at or after the list's last write (`stat -c %y` inside the container, to the nanosecond; checked against the pinned image, `nats:2.11.17-alpine`). - Anything not known is not in force, said in `why`: the write time unreadable, `/varz` unreadable, or a server that gives no load time. **Reviewers' checklist** - Read only: `docker exec … stat`, and `/varz`, which the tools already read. Nothing changes the bus. - Fails closed: every unknown is `in_force: false`. - Test `TestAGrantIsInForceOnlyWhenTheServerReloadedAfterTheListWasWritten` (six cases). Mutation: taking the load-time comparison out fails the case "reloaded before the write". **Checks.** `MESH_GATE=<controller at main 7477346> MESH_CHECK_MODULES=nats sh merge-check.sh` passes locally on the merge result (this branch contains main at ac7400d). **Order.** This first, assigned and live on the machine holding the bus. Then mesh-controller's follow-up (`fix/353-the-asker-judges-the-controllers-own-grant`), which asks for `in_force` and asks the operator nothing while the bus module does not say it (an older module is not a yes). Do not merge without review.
Author
Contributor

Delivery novox/mesh-catalog@4fdb047cc80f — delivered since 2026-10-12T12:14:06Z

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

Transitions

  • 2026-10-12 10:13 (new) → proposed (announced): novox/mesh-catalog#166's head announced
  • 2026-10-12 10:16 proposed → checked (checked): the verdict names this commit
  • 2026-10-12 10:16 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
  • 2026-10-12 12:13 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 12:13 published → delivering (go): its walk started: let go by this owner in its group's order, by a person, or on the controller's own path — not a failed walk that carried a later commit for it, after which it waits for a walk of its own commit
  • 2026-10-12 12:14 delivering → delivered (done): its walk is done, carrying its own commit: every machine of its deploy plan passed, or was left as its policy says

The commit's note under refs/notes/mesh-plan keeps every transition: git log --notes=mesh-plan.

<!-- mesh-delivery:view --> **Delivery** `novox/mesh-catalog@4fdb047cc80f` — **delivered** since 2026-10-12T12:14:06Z **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 **Transitions** - 2026-10-12 10:13 (new) → proposed (announced): novox/mesh-catalog#166's head announced - 2026-10-12 10:16 proposed → checked (checked): the verdict names this commit - 2026-10-12 10:16 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail - 2026-10-12 12:13 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 12:13 published → delivering (go): its walk started: let go by this owner in its group's order, by a person, or on the controller's own path — not a failed walk that carried a later commit for it, after which it waits for a walk of its own commit - 2026-10-12 12:14 delivering → delivered (done): its walk is done, carrying its own commit: every machine of its deploy plan passed, or was left as its policy says The commit's note under `refs/notes/mesh-plan` keeps every transition: `git log --notes=mesh-plan`.
Author
Contributor

Merge check at 2a2759ab

  • mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (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 novox as build-1791567752070504502 (builds --log build-1791567752070504502).

--- the gate: nats
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
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-09T17:36:02Z 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-09T17:36:02Z

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
--- 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 36212 strings of 627 files
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: 70, as kept
testing modules/nats
ok  	nats-tools/cmd/nats-tools	6.348s
--- its merge-check-typescript.sh (typescript toolchain)
**Merge check** at `2a2759ab` - `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (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 novox as `build-1791567752070504502` (`builds --log build-1791567752070504502`). ``` --- the gate: nats 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 judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-09T17:36:02Z 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-09T17:36:02Z 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 --- 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 36212 strings of 627 files 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: 70, as kept testing modules/nats ok nats-tools/cmd/nats-tools 6.348s --- its merge-check-typescript.sh (typescript toolchain) ```
jschoubben added 1 commit 2026-10-12 10:13:23 +00:00
nats: say whether a user's grant is in force on the running server, not only written (hq issue 353)
mesh/merge-gate pass: builds nats, sent nowhere; merging this needs a person's bus upgrade; 1 wait(s) for a person; every machine composes with the change …
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery delivered
4fdb047cc8
nats_user_can read the user list on the machine. A list written is not a list the bus enforces until
the server reloads it: on 2026-10-09 the controller asked between the write and the reload's effect.
The answer now carries in_force — allowed in the file, and the server's config_load_time after the
file's write — with why when it is not, and anything not known is not in force.
jschoubben force-pushed feat/353-the-bus-says-a-grant-is-in-force from 2a2759abe9 to 4fdb047cc8 2026-10-12 10:13:23 +00:00 Compare
Author
Contributor

Merge check at 4fdb047c

  • mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (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 novox as build-1791800028730561806 (builds --log build-1791800028730561806).

--- the gate: nats
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
judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-12T10:08:43Z 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-12T10:08:43Z

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
--- 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 42354 strings of 682 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
testing modules/nats
ok  	nats-tools/cmd/nats-tools	6.138s
--- its merge-check-typescript.sh (typescript toolchain)
**Merge check** at `4fdb047c` - `mesh/merge-gate`: **PASS** — every machine composes with the change as it did without (4 of 4 compose) (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 novox as `build-1791800028730561806` (`builds --log build-1791800028730561806`). ``` --- the gate: nats 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 judging 0 module(s) changed against 4 machine(s), as the snapshot of 2026-10-12T10:08:43Z 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-12T10:08:43Z 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 --- 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 42354 strings of 682 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 testing modules/nats ok nats-tools/cmd/nats-tools 6.138s --- its merge-check-typescript.sh (typescript toolchain) ```
mesh-admin left a comment
Author
Contributor

Verdict: approve, at head 4fdb047 (rebased onto main da296ca; the old head was 2a2759a, which was 200 commits behind main; main changed nothing under modules/nats, and the rebase was clean).

Independent review for hq issue 353.

What I checked:

  • The change touches only modules/nats/cmd/nats-tools (main.go, monitor.go, tools.go, tools_test.go). The Dockerfile, entrypoint.sh, module.json and build.on are untouched, so the server stays nats 2.11.17-alpine at the same pinned digest. Only the nats-tools bundle changes.
  • It reads only: docker exec ... stat -c %y on the user list, and /varz. It changes nothing on the bus.
  • It fails closed. An unknown write time, an unreadable /varz, or a server that gives no config_load_time each give in_force false, with the reason in why. allowed and by are unchanged, so the old answer stays readable.
  • The comparison is correct for how the list arrives. The node-engine writes the file only when its content differs (applyFile, contentSame) and writes it atomically into the mounted directory. The entrypoint sends SIGHUP within 5 s of a digest change. So in_force turns true at most about 5 s after a real change.
  • go test -race ./... in modules/nats passes. Mutation: replacing the load-time comparison with true fails "reloaded before the write", as the PR says.
  • Checks at 4fdb047: mesh/merge-gate pass, mesh/repo-check pass, mesh/delivery ready.

What merging this costs (for whoever merges it):

  • mesh-delivery.what-if says "merging this needs a person's bus upgrade: nats is never sent by an ordinary send, and until mesh-controller.bus upgrade runs, nothing else is sent to novox either". So after the merge, every delivery to the control node waits until the operator runs the bus upgrade. That is the operator's decision. The merge should happen only when they are ready to run it soon after.
  • The upgrade can be undone: revert this commit and run a bus upgrade again. No stream or stored data changes. I did not verify whether the upgrade recreates the server container when only the tools bundle changed.

Minor, not blocking:

  • Suppose the list changes and changes back inside one 5-second poll. Its digest then equals the last one, so the server is not reloaded, but the file's write time is newer than the last load. in_force then stays false until the next real change. It fails closed and is rare. I note it because the controller (#188) holds every ask while in_force is false.
Verdict: approve, at head 4fdb047 (rebased onto main da296ca; the old head was 2a2759a, which was 200 commits behind main; main changed nothing under modules/nats, and the rebase was clean). Independent review for hq issue 353. What I checked: - The change touches only modules/nats/cmd/nats-tools (main.go, monitor.go, tools.go, tools_test.go). The Dockerfile, entrypoint.sh, module.json and build.on are untouched, so the server stays nats 2.11.17-alpine at the same pinned digest. Only the nats-tools bundle changes. - It reads only: `docker exec ... stat -c %y` on the user list, and /varz. It changes nothing on the bus. - It fails closed. An unknown write time, an unreadable /varz, or a server that gives no config_load_time each give in_force false, with the reason in why. `allowed` and `by` are unchanged, so the old answer stays readable. - The comparison is correct for how the list arrives. The node-engine writes the file only when its content differs (applyFile, contentSame) and writes it atomically into the mounted directory. The entrypoint sends SIGHUP within 5 s of a digest change. So in_force turns true at most about 5 s after a real change. - `go test -race ./...` in modules/nats passes. Mutation: replacing the load-time comparison with `true` fails "reloaded before the write", as the PR says. - Checks at 4fdb047: mesh/merge-gate pass, mesh/repo-check pass, mesh/delivery ready. What merging this costs (for whoever merges it): - mesh-delivery.what-if says "merging this needs a person's bus upgrade: nats is never sent by an ordinary send, and until `mesh-controller.bus upgrade` runs, nothing else is sent to novox either". So after the merge, every delivery to the control node waits until the operator runs the bus upgrade. That is the operator's decision. The merge should happen only when they are ready to run it soon after. - The upgrade can be undone: revert this commit and run a bus upgrade again. No stream or stored data changes. I did not verify whether the upgrade recreates the server container when only the tools bundle changed. Minor, not blocking: - Suppose the list changes and changes back inside one 5-second poll. Its digest then equals the last one, so the server is not reloaded, but the file's write time is newer than the last load. in_force then stays false until the next real change. It fails closed and is rare. I note it because the controller (#188) holds every ask while in_force is false.
mesh-admin merged commit 0366208274 into main 2026-10-12 12:13:26 +00:00
mesh-admin deleted branch feat/353-the-bus-says-a-grant-is-in-force 2026-10-12 12:13:26 +00:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: novox/mesh-catalog#166