Design 47 milestone 5, delivery 1 of 2 (issue 981; ADR 0408): builds, rollouts and assignments become keys of the buckets mesh-controller_builds, _rollouts and _assignments on the bus. They are written by the lease holder by compare-and-set, keep 64 revisions, and no key is ever removed.
This is mesh-controller#378 at the same reviewed head, on a branch of its own. #378's group feat/chain-on-the-bus was stopped when its catalogue member's plan was stopped from Telegram. The readers it needs (mesh-catalog#357) were merged and then delivered by rebuilds to novox and ace on 2026-10-18 at 11:31-11:37. shanks and g14 receive no send until their "forge-account" composition fault is fixed. mesh-sdk#32 was closed and moves to milestone 6. This pull request takes over the delivery record #378 left stopped (issue 1114, fixed by mesh-catalog#360).
1089: package internal/chain, the three buckets, and migration 0104 (chain_moved; it also drops seat_holding's foreign key to assignment).
1090, 1091: builds on the bus; a build request is the build in state asked.
1092: rollouts and the merges they hold on the bus; a merged event is acknowledged only after its write (ADR 0407 §3).
1093: assignments on the bus; an unassign writes ended (ADR 0408 §4); the store's mirror stops once the assignments have moved; route-proxy reads through mesh-sdk f185aed.
1095: each assignment names its build, artifact or package, commit and rollout, and each rollout lists the assignments it changed (acceptance 10).
The move at start: per kind, counted, re-read and settled under a share lock, refused loudly (condition chain-move-refused) on a count that differs or a value over 1 MiB. It retries every 30 s until the new bus grants arrive.
Delivery 2 (issues 1094, 1096, 1108-1111) drops the tables, once the move is read back live.
Design 47 milestone 5, delivery 1 of 2 (issue 981; ADR 0408): builds, rollouts and assignments become keys of the buckets mesh-controller_builds, _rollouts and _assignments on the bus. They are written by the lease holder by compare-and-set, keep 64 revisions, and no key is ever removed.
This is mesh-controller#378 at the same reviewed head, on a branch of its own. #378's group feat/chain-on-the-bus was stopped when its catalogue member's plan was stopped from Telegram. The readers it needs (mesh-catalog#357) were merged and then delivered by rebuilds to novox and ace on 2026-10-18 at 11:31-11:37. shanks and g14 receive no send until their "forge-account" composition fault is fixed. mesh-sdk#32 was closed and moves to milestone 6. This pull request takes over the delivery record #378 left stopped (issue 1114, fixed by mesh-catalog#360).
- 1089: package internal/chain, the three buckets, and migration 0104 (`chain_moved`; it also drops seat_holding's foreign key to assignment).
- 1090, 1091: builds on the bus; a build request is the build in state `asked`.
- 1092: rollouts and the merges they hold on the bus; a merged event is acknowledged only after its write (ADR 0407 §3).
- 1093: assignments on the bus; an unassign writes `ended` (ADR 0408 §4); the store's mirror stops once the assignments have moved; route-proxy reads through mesh-sdk f185aed.
- 1095: each assignment names its build, artifact or package, commit and rollout, and each rollout lists the assignments it changed (acceptance 10).
- The move at start: per kind, counted, re-read and settled under a share lock, refused loudly (condition chain-move-refused) on a count that differs or a value over 1 MiB. It retries every 30 s until the new bus grants arrive.
- Delivery 2 (issues 1094, 1096, 1108-1111) drops the tables, once the move is read back live.
Reviewed-by: reviewer-chain@shanks at 0149a3d7de202a983e50630e3eaf3b3f0bb075a7
internal/chain holds typed Build, Rollout and Assignment and a Backend with no delete or purge, in memory and on the bus. The builds and rollouts buckets are asserted with history 64, no age and values up to just under a mebibyte; the assignments bucket gets the same, keeping its marker age because a stream cannot be made to disallow message ages. Migration 0104 makes the one-row chain_moved switch. The controller keeps no consolidated schema, so 0104 is the whole schema change. Nothing reads the buckets yet.
Once chain_moved records the kind, RecordBuild and every build read go through the chain (reuse key and published added); before that the tables are read as before. The serving controller copies the rows at its start, holding the lease: idempotent per key, rows counted against keys, the largest value measured, a refusal (urgent condition, nothing switched) on a count that differs or a value over the bus's largest, and a re-read when the table took a row meanwhile. ForTest attaches the chain in memory with builds moved; ForTestBefore leaves it unmoved. Build requests, gates and the other kinds are still in their tables.
A request is the build's record under the id its outcome will carry, in state asked; the outcome takes its place and keeps the request beside it, so assign, the pending assignments and the planner read the builds bucket alone. The bucket removes no key, so a request past thirty days is not listed instead of deleted. The move folds build_request into the same records (one kind, builds, counted against both tables) and marks the requests never handed over to be asked again once: claimed before it is asked and settled after, so a crash loses the ask rather than making it twice. Also tests the chain buckets' options on a real bus, the assignments' mirror options included.
Once chain_moved records the kind, a plan is a key of the rollouts bucket under its id and the open batch is the same key in state assembling. A save refuses a copy another save moved since (the plan's own Revision, kept in its value, counts saves) and keeps the merges the record holds, so a copy read before a merge moved cannot lay it back. The merges a batch or walk answers are the record's held field, with the columns the table had; a merge no plan answers stays, flagged, in the record that held it last, or in the record kept for those. A merge moved to a plan is written to the receiving record first and then taken from the giving one; one found in both is read from the one it entered last and repaired at the next cut. Plans and merges are read from a view kept by one watch of the bucket. A bus that does not answer, a lease lost and a key moved are now not-now like the store being away, so a merge whose plan could not be written is held and handed over again, never acknowledged. The start moves release_plan and batched_merge into the bucket, one kind, counted against both tables.
Once chain_moved records the kind, Assign, Unassign and Assigned write and read the keys <node>.<module>, and every join of the store that read assignments is made from the bucket: where a module runs, what is behind, what a machine awaits, a given value due for replacement, taking a module, and whether a module may be forgotten (refused while a standing assignment names it). An unassignment ends the key with a marker and keeps its earlier values, as it removed the row; no ended or pending mark is written yet. The generation rises with each change, and a seat held by an assignment goes with it: the foreign key from seat_holding is dropped by migration 0104 and the controller says both. The provisioner's plan is kept in the values by a pass of the tick that writes that one field by compare-and-set; the assignment-changed event is said from what the bucket holds, whoever wrote it. The start moves the rows with what each machine was last sent, keeping a plan the mirror put in a value.
ADR 0408 section 4 says no key of the chain is removed, a delete marker included. The Backend loses Remove and the Chain RemoveAssignment. An unassignment, and the end of a value only pulled in by another, write the value again with ended set, by compare-and-set; assigning it again writes a fresh standing value over it. A value with ended or a state is no assignment (Assignment.Stands) to the assignment lists, the joins, forgetting a module, seat holdings, the given values, the move and the assignment-changed event.
A send that records what a machine was sent writes, in the assignment of each module it carried a build of, the build, what it published, the commit, the rollout that sent it and since when: filled where the assignment names nothing, replaced when the commit moved, never blanked by a push by hand. A plan's sends are made as the plan, so they name it, and the plan lists the assignments each send changed with the build and commit before and after, the builds it carried and the steps taken. The builds, plans and node verbs say the links. node.sent_builds is written and read as before; SentBuilds from the assignments follows with the delivery that drops the column. Acceptance 10 is a test that enters by a merge heard and cut into a plan and writes no key by hand.
The first try of the move to the bus is made before the controller serves, and a failure of the kind that is tried again no longer holds the start: it is tried every half minute while the controller serves from the tables. Moving the assignments looked up the build of each commit by scanning the bucket of builds for each of them; it reads the builds once.
1090/1092: the move tests pick each report by kind and expect three, all already, on the second run. 1090-1093: under the share lock the switch reads the rows again and writes every key whose value differs from its row (and ends an assignment the store dropped) before recording the kind, so an update the old controller made after the first pass is not lost. 1093: route-proxy is pinned at mesh-sdk f185aedb and vendored; the controller uses only the SDK's asks package. KeepAssignmentPlans decides each key by keepStep, which never makes or revives an assignment. AssignmentsMirrorToWrite refuses once the assignments are moved.
Review round 2. The writer's leave to write is the lease's and AssignmentsMirrorMayWrite, a flag set before the settle of the assignments' switch, kept after the commit and cleared only if the switch fails, so a pass that read its source before the switch lays and purges nothing after it.
route-proxy provides route: its consumers are sent again after it
route-proxy keeps data (ADR 0233): what it holds is backed up before it moves
build-agent keeps data (ADR 0233): what it holds is backed up before it moves
grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before route-proxy, build-agent is judged on its first machine
route-proxy provides route: its consumers are sent again after it
route-proxy keeps data (ADR 0233): what it holds is backed up before it moves
build-agent keeps data (ADR 0233): what it holds is backed up before it moves
grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before route-proxy, build-agent is judged on its first machine
Machines
mesh-controller on every machine running it: sent
route-proxy on every machine running it: sent
build-agent on every machine running it: sent
Transitions
2026-10-18 10:01 (new) → proposed (announced): novox/mesh-controller#379's head announced; #378 with the same head closed unmerged
2026-10-18 10:39 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
2026-10-18 10:39 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
2026-10-18 10:40 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
2026-10-18 10:40 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-18 11:32 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-controller@0149a3d7de20` — **delivered** since 2026-10-18T11:32:20Z
**Delivery plan** — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
- tier 0: mesh-controller, route-proxy
- tier 1: build-agent
- ace: receives route-proxy, build-agent
- g14: receives build-agent
- novox: receives mesh-controller, route-proxy, build-agent
- shanks: receives build-agent
- route-proxy provides route: its consumers are sent again after it
- route-proxy keeps data (ADR 0233): what it holds is backed up before it moves
- build-agent keeps data (ADR 0233): what it holds is backed up before it moves
- grants step: if this changes what the bus's user list says (a new tool, subject or user), novox is sent that list alone, every build there kept, before route-proxy, build-agent is judged on its first machine
**Machines**
- mesh-controller on every machine running it: sent
- route-proxy on every machine running it: sent
- build-agent on every machine running it: sent
**Transitions**
- 2026-10-18 10:01 (new) → proposed (announced): novox/mesh-controller#379's head announced; #378 with the same head closed unmerged
- 2026-10-18 10:39 proposed → checked (checked): a verdict names this commit and the trunk's head as its trunk commit
- 2026-10-18 10:39 checked → ready (accepted): the gate passed or warned, and the repository's own check did not fail
- 2026-10-18 10:40 ready → published (merged): on the trunk its modules follow: merged there, and its walk opened — or nothing for a walk to move
- 2026-10-18 10:40 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-18 11:32 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`.
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.
Design 47 milestone 5, delivery 1 of 2 (issue 981; ADR 0408): builds, rollouts and assignments become keys of the buckets mesh-controller_builds, _rollouts and _assignments on the bus. They are written by the lease holder by compare-and-set, keep 64 revisions, and no key is ever removed.
This is mesh-controller#378 at the same reviewed head, on a branch of its own. #378's group feat/chain-on-the-bus was stopped when its catalogue member's plan was stopped from Telegram. The readers it needs (mesh-catalog#357) were merged and then delivered by rebuilds to novox and ace on 2026-10-18 at 11:31-11:37. shanks and g14 receive no send until their "forge-account" composition fault is fixed. mesh-sdk#32 was closed and moves to milestone 6. This pull request takes over the delivery record #378 left stopped (issue 1114, fixed by mesh-catalog#360).
chain_moved; it also drops seat_holding's foreign key to assignment).asked.ended(ADR 0408 §4); the store's mirror stops once the assignments have moved; route-proxy reads through mesh-sdk f185aed.Reviewed-by: reviewer-chain@shanks at
0149a3d7deMerge check at
0149a3d7Judged: head
0149a3d7de20merged into trunk54070f5bc32b; read beside it: mesh-cataloge40ec47058e6, mesh-controller-main54070f5bc32b, mesh-host6469e8238443, mesh-tools7412c5b6c9c5mesh/merge-gate: PASS — every machine composes with the change as it did without (4 of 4 compose) (modules: build-agent, mesh-controller, route-proxy)mesh/repo-check: PASS — its merge-check.sh passedDelivery plan — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
Run by the build seat on shanks as
build-1792316622626365259(builds --log build-1792316622626365259).Delivery
novox/mesh-controller@0149a3d7de20— delivered since 2026-10-18T11:32:20ZDelivery plan — builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus step
Machines
Transitions
The commit's note under
refs/notes/mesh-plankeeps every transition:git log --notes=mesh-plan.