Issue 1945 (L1 of design 47); decision ADR 0562 (accepted on the operator's Approve), which changes ADR 0547 §8.
Fault (met twice: 2026-10-26 13:48, 2026-10-27 21:19:51Z). Take-over was refused at the operator's yes whenever any user differed between the shadow list and the loaded list. Today 41 users differ, every difference an added right (391: stream-created advisories, the node users' reads of placement, builds, served settings and the vault), none removed. The controller's list never gains them (ADR 0547 §1), so the old rule could never hold again, and the placement seed (issue 1126) needs those reads.
Rule as coded. Decide refuses on every loss and nothing else: a user added, a loaded user dropped that placement still names, a publish or subscribe right lost, responses lost, a publish deny added (DenyAdded), a deny the loaded list cannot say for a differing user (DenyUnread, until nats_users reports denies), the loaded list unread, a user with no hash. The take-over ask names the added rights by user and kind (within the content rule, 2200 characters); when anything would be refused it says so and names the users, never 'takes none away'. The yes is bound to the added rights' digest and refused if they changed.
Quick or thorough. Thorough: the rule changed in the one guard every take-over passes, not a per-user excuse; the controller unchanged.
Tests. Rows only (mesh-delivery is over its budget): the captured live compare (no hashes) allowed and refused by the old equality; each loss kind on the captured data refused with the users named and the words checked; deny added and deny unread refused. Unit suite and go vet -tags integration clean.
Live check after delivery. grants_take_over_state; then a new take-over ask whose words list the added rights; at the yes, the bus node loads the grants part's list (60 users), and every node's 'Permissions Violation ... placement-candidates' stops.
Review: round 1 CHANGES (deny not compared; ask words could claim no loss), round 2 APPROVED. Notes kept for later on issue 1945: allow_responses compared as a boolean only; a row for equal allows with a shadow deny.
Issue 1945 (L1 of design 47); decision ADR 0562 (accepted on the operator's Approve), which changes ADR 0547 §8.
**Fault (met twice: 2026-10-26 13:48, 2026-10-27 21:19:51Z).** Take-over was refused at the operator's yes whenever any user differed between the shadow list and the loaded list. Today 41 users differ, every difference an added right (391: stream-created advisories, the node users' reads of placement, builds, served settings and the vault), none removed. The controller's list never gains them (ADR 0547 §1), so the old rule could never hold again, and the placement seed (issue 1126) needs those reads.
**Rule as coded.** Decide refuses on every loss and nothing else: a user added, a loaded user dropped that placement still names, a publish or subscribe right lost, responses lost, a publish deny added (DenyAdded), a deny the loaded list cannot say for a differing user (DenyUnread, until nats_users reports denies), the loaded list unread, a user with no hash. The take-over ask names the added rights by user and kind (within the content rule, 2200 characters); when anything would be refused it says so and names the users, never 'takes none away'. The yes is bound to the added rights' digest and refused if they changed.
**Quick or thorough.** Thorough: the rule changed in the one guard every take-over passes, not a per-user excuse; the controller unchanged.
**Tests.** Rows only (mesh-delivery is over its budget): the captured live compare (no hashes) allowed and refused by the old equality; each loss kind on the captured data refused with the users named and the words checked; deny added and deny unread refused. Unit suite and `go vet -tags integration` clean.
**Live check after delivery.** grants_take_over_state; then a new take-over ask whose words list the added rights; at the yes, the bus node loads the grants part's list (60 users), and every node's 'Permissions Violation ... placement-candidates' stops.
Review: round 1 CHANGES (deny not compared; ask words could claim no loss), round 2 APPROVED. Notes kept for later on issue 1945: allow_responses compared as a boolean only; a row for equal allows with a shadow deny.
Reviewed-by: review-takeover@shanks at 3192d89edfcb0ca0e602b283f17ff77a71fcb050
The operator's yes to take-over was refused twice (2026-10-26 13:48 and
2026-10-27 21:19 UTC) because 41 users differ, every difference a right the
grants part's list adds. The controller's list is not changed (ADR 0547 §1),
so ADR 0547 §8's equality could never hold again. ADR 0562 changes it:
take-over is allowed when no user is added or dropped, no loaded user loses a
publish, subscribe or responses right and every hash is held; the ask names
the added rights by user and kind, and a yes after they changed is refused.
Tests: rows from the captured live comparison of 21:19 (testdata, no
hashes) in the compare table, and rows in the take-over table for a right
removed, added rights changed since the ask, and only added rights recorded.
issue 1945
Review round 1 of issue 1945's fix found two ways the guard could let a loss
through or hide one from the operator.
A publish deny was never compared: grants.User carried no deny, so a widened
allow that brings a new deny (a lost publish right) passed as an added right.
The user now carries its deny; a deny the shadow adds is a loss, and while
nats_users answers no deny for the loaded list, a user whose grants differ
and whose shadow grant has a deny refuses, named as a deny the loaded list
cannot be compared on. None of today's 41 differing users carries a deny
(only the four node-tools users do, and they are the same in both lists).
The ask said "takes none away" whenever rights were added, whatever else
differed. Its words now name the added rights only when nothing else refuses
(Refusals: unread list, Removing, a missing hash), and otherwise say what the
yes would be refused for, naming the users; Decide uses the same Refusals.
issue 1945
Deliverynovox/mesh-delivery@3192d89edfcb — merged since 2026-10-27T21:36:28Z
Source — source.main moved to novox/mesh-delivery@a49fd9cc65. Whether it reached the machines is mesh-delivery-view's, derived from source.main, the wants and the haves.
Transitions
2026-10-27 21:35 (new) → proposed (announced): novox/mesh-delivery#90's head announced
2026-10-27 21:35 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; or the check gates no merge (check-gates-merge false)
2026-10-27 21:36 ready → merged (merged): on the trunk its modules follow: merged there
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-delivery@3192d89edfcb` — **merged** since 2026-10-27T21:36:28Z
**Source** — source.main moved to novox/mesh-delivery@a49fd9cc65f7. Whether it reached the machines is `mesh-delivery-view`'s, derived from `source.main`, the wants and the haves.
**Transitions**
- 2026-10-27 21:35 (new) → proposed (announced): novox/mesh-delivery#90's head announced
- 2026-10-27 21:35 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; or the check gates no merge (check-gates-merge false)
- 2026-10-27 21:36 ready → merged (merged): on the trunk its modules follow: merged there
The commit's note under `refs/notes/mesh-plan` keeps every transition of this change up to its merge: `git log --notes=mesh-plan`.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Issue 1945 (L1 of design 47); decision ADR 0562 (accepted on the operator's Approve), which changes ADR 0547 §8.
Fault (met twice: 2026-10-26 13:48, 2026-10-27 21:19:51Z). Take-over was refused at the operator's yes whenever any user differed between the shadow list and the loaded list. Today 41 users differ, every difference an added right (391: stream-created advisories, the node users' reads of placement, builds, served settings and the vault), none removed. The controller's list never gains them (ADR 0547 §1), so the old rule could never hold again, and the placement seed (issue 1126) needs those reads.
Rule as coded. Decide refuses on every loss and nothing else: a user added, a loaded user dropped that placement still names, a publish or subscribe right lost, responses lost, a publish deny added (DenyAdded), a deny the loaded list cannot say for a differing user (DenyUnread, until nats_users reports denies), the loaded list unread, a user with no hash. The take-over ask names the added rights by user and kind (within the content rule, 2200 characters); when anything would be refused it says so and names the users, never 'takes none away'. The yes is bound to the added rights' digest and refused if they changed.
Quick or thorough. Thorough: the rule changed in the one guard every take-over passes, not a per-user excuse; the controller unchanged.
Tests. Rows only (mesh-delivery is over its budget): the captured live compare (no hashes) allowed and refused by the old equality; each loss kind on the captured data refused with the users named and the words checked; deny added and deny unread refused. Unit suite and
go vet -tags integrationclean.Live check after delivery. grants_take_over_state; then a new take-over ask whose words list the added rights; at the yes, the bus node loads the grants part's list (60 users), and every node's 'Permissions Violation ... placement-candidates' stops.
Review: round 1 CHANGES (deny not compared; ask words could claim no loss), round 2 APPROVED. Notes kept for later on issue 1945: allow_responses compared as a boolean only; a row for equal allows with a shadow deny.
Reviewed-by: review-takeover@shanks at
3192d89edfDelivery
novox/mesh-delivery@3192d89edfcb— merged since 2026-10-27T21:36:28ZSource — source.main moved to novox/mesh-delivery@a49fd9cc65. Whether it reached the machines is
mesh-delivery-view's, derived fromsource.main, the wants and the haves.Transitions
The commit's note under
refs/notes/mesh-plankeeps every transition of this change up to its merge:git log --notes=mesh-plan.