diff --git a/00-META/glossary.md b/00-META/glossary.md index 851b201..18687df 100644 --- a/00-META/glossary.md +++ b/00-META/glossary.md @@ -40,7 +40,7 @@ another — and a mesh you cannot name precisely is a mesh two people describe d - **the deprecated broker** — the lavinmq module. It was the mesh's bus and is not any more. It keeps running as an **ordinary provider** of the `amqp` provision, for modules that need a message broker of their own the way something needs a database - ([ADR 0127](../02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md)) — no seat, not foundation, + ([ADR 0127](../02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md) (superseded by [ADR 0131](../02-DECISIONS/0131-everything-on-the-mesh-speaks-to-the-broker-seat.md))) — no seat, not foundation, never raised at genesis, and a mesh that never installs it is complete. Say *the deprecated broker*, not "the compatibility broker" (it serves the mesh's own modules, diff --git a/02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md b/02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md index cdd1a08..e417e6e 100644 --- a/02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md +++ b/02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md @@ -1,6 +1,7 @@ --- topic: the mesh -status: accepted +status: superseded +superseded-by: 0131-everything-on-the-mesh-speaks-to-the-broker-seat.md date: 2026-09-26 deciders: jochen reconstructed: false diff --git a/02-DECISIONS/0128-the-mesh-bus-is-required-not-ambient.md b/02-DECISIONS/0128-the-mesh-bus-is-required-not-ambient.md index 0d2902d..138b90b 100644 --- a/02-DECISIONS/0128-the-mesh-bus-is-required-not-ambient.md +++ b/02-DECISIONS/0128-the-mesh-bus-is-required-not-ambient.md @@ -4,11 +4,18 @@ status: accepted date: 2026-09-26 deciders: jochen reconstructed: false -extends: 02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md +extends: 02-DECISIONS/0131-everything-on-the-mesh-speaks-to-the-broker-seat.md --- # 128. The mesh bus is required, not ambient + +> **Pointer repointed, 2026-09-27.** This record was written extending +> [ADR 0127](0127-amqp-is-a-provision-not-the-bus.md) (superseded by [ADR 0131](0131-everything-on-the-mesh-speaks-to-the-broker-seat.md)), which +> [ADR 0131](0131-everything-on-the-mesh-speaks-to-the-broker-seat.md) has since superseded — AMQP is +> not a provision at all. Nothing decided here changes; the frontmatter now rests on the live record, +> and the citations below are read with that in mind. + ## Context [Design 29](../03-DESIGN/01-to-be/32-what-a-module-declares.md) opened by saying the bus is @@ -72,7 +79,7 @@ process in the path and nothing waiting on a bus account to create bus accounts. whose provider is the mesh itself. **A module may also provide a NATS server of its own, and that is a different interface.** Exactly -as the AMQP broker provides `amqp` ([ADR 0127](0127-amqp-is-a-provision-not-the-bus.md)), a module +as the AMQP broker provides `amqp` ([ADR 0127](0127-amqp-is-a-provision-not-the-bus.md) (superseded by [ADR 0131](0131-everything-on-the-mesh-speaks-to-the-broker-seat.md))), a module may run its own NATS and offer it as a backing service. That interface is **`nats`**; the mesh's own bus is **`mesh-bus`**; the two are never the same name, because a manifest that said `nats` could mean either and the difference is the whole architecture. The rule from 0119 decides which @@ -109,7 +116,7 @@ is legitimate: a private bus is a backing service, never a channel to another mo - [ADR 0125](0125-the-bus-is-the-only-broker.md) — superseded by 0119; its bootstrap argument is narrowed here to the case it supports. -- [ADR 0127](0127-amqp-is-a-provision-not-the-bus.md) — a broker as a backing service; this +- [ADR 0127](0127-amqp-is-a-provision-not-the-bus.md) (superseded by [ADR 0131](0131-everything-on-the-mesh-speaks-to-the-broker-seat.md)) — a broker as a backing service; this applies the same shape to the mesh's own bus and separates the two names. - [ADR 0043](0043-a-module-broker-account-is-scoped-by-emits-and-consumes.md) — authority from declarations, which this leaves untouched. diff --git a/02-DECISIONS/0130-the-predecessor-is-ending-and-its-broker-goes-with-it.md b/02-DECISIONS/0130-the-predecessor-is-ending-and-its-broker-goes-with-it.md index 7bbdc7f..32e3a37 100644 --- a/02-DECISIONS/0130-the-predecessor-is-ending-and-its-broker-goes-with-it.md +++ b/02-DECISIONS/0130-the-predecessor-is-ending-and-its-broker-goes-with-it.md @@ -4,14 +4,21 @@ status: accepted date: 2026-09-27 deciders: jochen reconstructed: false -extends: 02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md +extends: 02-DECISIONS/0131-everything-on-the-mesh-speaks-to-the-broker-seat.md --- # 130. The predecessor is ending, and its broker goes with it + +> **Pointer repointed, 2026-09-27.** This record was written extending +> [ADR 0127](0127-amqp-is-a-provision-not-the-bus.md) (superseded by [ADR 0131](0131-everything-on-the-mesh-speaks-to-the-broker-seat.md)), which +> [ADR 0131](0131-everything-on-the-mesh-speaks-to-the-broker-seat.md) has since superseded — AMQP is +> not a provision at all. Nothing decided here changes; the frontmatter now rests on the live record, +> and the citations below are read with that in mind. + ## Context -[ADR 0127](0127-amqp-is-a-provision-not-the-bus.md) settled that the old broker is an ordinary +[ADR 0127](0127-amqp-is-a-provision-not-the-bus.md) (superseded by [ADR 0131](0131-everything-on-the-mesh-speaks-to-the-broker-seat.md)) settled that the old broker is an ordinary provider of the `amqp` provision rather than a compatibility module with an end date. It rejected giving it a retirement condition, and said why: *"its clients are not only the predecessor's, so the retirement condition describes a day that will not come."* diff --git a/02-DECISIONS/0131-everything-on-the-mesh-speaks-to-the-broker-seat.md b/02-DECISIONS/0131-everything-on-the-mesh-speaks-to-the-broker-seat.md new file mode 100644 index 0000000..5b1155b --- /dev/null +++ b/02-DECISIONS/0131-everything-on-the-mesh-speaks-to-the-broker-seat.md @@ -0,0 +1,94 @@ +--- +topic: the mesh +status: accepted +date: 2026-09-27 +deciders: jochen +reconstructed: false +supersedes: 0127-amqp-is-a-provision-not-the-bus.md +--- + +# 131. Everything on the mesh speaks to the broker seat, and AMQP is not a provision + +## Context + +[ADR 0127](0127-amqp-is-a-provision-not-the-bus.md) settled the old broker as an ordinary provider +of an ordinary provision, `amqp`, kept for whatever wanted a message broker of its own. The day the +bus moved was the day that framing was tested, and it failed in a way that took the control plane +down for an evening. + +Three things came out of the wreckage. **The protocol had leaked into the seat's contract**: for a +module to hold `mesh-broker`, it had to provide what the seat delivers, and what it delivered was +`amqp` — so the module that will carry the bus on NATS could not hold the seat that names the bus, +while the module the mesh was leaving could. **A consumer of `amqp` is not asking for AMQP.** The two +modules requiring it wanted the mesh's messaging — to emit an event, to hear a topic — and named the +wire protocol only because that was the word available. **And AMQP and NATS are not interchangeable +at the wire.** A provision named after a protocol can only ever be answered by that protocol, so once +the bus is NATS an `amqp` provision has one possible provider, and it is the thing being retired. + +The operator's position, stated during the outage: modules depend on the broker *seat*, not on a +protocol; AMQP is obsolete as anything the mesh's core knows about; a module that depends on `amqp` +is wrong; and everything should reach the mesh's bus and be able to emit events and consume topics +through it. + +## Decision + +**A module that needs messaging uses the mesh's bus, and the mesh's bus is whatever holds +`mesh-broker`.** Emitting an event and consuming a topic go through the sdk, which is handed the +bus by the mesh with the module's own credential. No manifest names a wire protocol to get it. + +**`amqp` is neither a provision nor a requirement.** Registration refuses a manifest that provides +it or requires it. The `mesh-broker` seat delivers `mesh-bus`, and its holder is the module that +provides `mesh-bus` — today the nats module, and only it. + +**The old broker's module and the two modules that required it leave the catalogue.** They are +removed, not converted: one was a proof that a grant worked end to end, the other forwards mail off a +queue, and both are re-done against the bus if wanted, as new modules under this record. + +**The controller's AMQP transport is deleted once every node reports on the new bus**, and the +switch that selects a transport goes with it — one bus, so nothing to select. + +The predecessor's own broker is outside the mesh and not this record's concern +([ADR 0130](0130-the-predecessor-is-ending-and-its-broker-goes-with-it.md)): what the predecessor's +tooling loses when it stops is accepted there. + +## Options considered + +1. **Keep 0127: AMQP stays an ordinary provision with the old broker as its provider.** Rejected. It + is what put the protocol into the seat's contract, it is why the seat could be left with no valid + holder mid-change, and it keeps two transports in the control plane indefinitely for the benefit of + two modules that did not want AMQP in the first place. +2. **Bridge it: the old broker's module also provides `mesh-bus`, so both can hold the seat during the + change.** Rejected. It makes the retiring broker a legitimate mesh bus for exactly as long as + nobody removes the line, which in practice is forever, and it leaves `amqp` as a thing the core + still knows the name of. +3. **The seat is the dependency; the protocol is nobody's business but the holder's.** Adopted. + +## Consequences + +- **The change of holder is a handover, and it needs a command.** Nothing today moves a seat from + one assignment to another as one act, and a seat the control plane dereferences cannot be empty + in between — that emptiness is the outage this record comes from. The command takes a seat and the + assignment taking it over. Designed and built before the cutover, under + [28 — Building the bus](../03-DESIGN/01-to-be/28-building-the-bus.md). +- **The seat's row moves to `mesh-bus` before the new holder registers, and that is safe.** The + control plane composes its own bus address through the seat *by name* + (`${seat:mesh-broker:…}`), and the overview derives holders by name; only registration and the + provision-to-seat resolution read what a seat delivers. So the row can change under the current + holder without unseating it, the new holder can then register its claim, and the handover happens + when both are running. Verified in the code during the outage, not assumed. +- **Registration gains two refusals**: a manifest providing `amqp`, and one requiring it. +- **The `rollout check` stops saying the old broker stays.** It said so under 0127; it now lists + unassigning it as the last step of the move. +- **What got harder**: a third party that genuinely wants an AMQP broker on a mesh node runs one as + any application module, with no provision and no seat, and nothing on the mesh routes to it. That + is the cost of the mesh not knowing the word. + +## How this is checked + +| Rule | Checked by | +|---|---| +| No manifest provides or requires `amqp` | a registration test refusing each, naming this record; and a whole-catalogue test asserting no registered manifest names it | +| `mesh-broker` delivers `mesh-bus`, and only a `mesh-bus` provider may hold it | the existing registration test for a delivering seat, with the row's value read from the store (mesh-controller#89) | +| The seat's row can change without unseating the holder | a test composing the control plane's own address and the overview under a row that the current holder does not satisfy | +| The rollout does not leave the old broker running | `rollout check` output, asserted in its test | +| The AMQP transport is gone | the package does not compile with it referenced; the switch variable is refused as unknown at start | diff --git a/02-DECISIONS/README.md b/02-DECISIONS/README.md index d7a0619..fa74c90 100644 --- a/02-DECISIONS/README.md +++ b/02-DECISIONS/README.md @@ -135,10 +135,11 @@ python3 00-META/checks/index.py fail if stale - **0116** — [The bus is built in five steps, and the protocol moves with it](0116-the-bus-is-built-in-five-steps.md) - **0119** — [A taken tunnel's predecessor is retired once the take is proven](0119-a-taken-tunnels-predecessor-is-retired.md) - **0125** — [The bus is the only broker](0125-the-bus-is-the-only-broker.md) *(superseded)* -- **0127** — [AMQP is a provision, not the bus](0127-amqp-is-a-provision-not-the-bus.md) +- **0127** — [AMQP is a provision, not the bus](0127-amqp-is-a-provision-not-the-bus.md) *(superseded)* - **0128** — [The mesh bus is required, not ambient](0128-the-mesh-bus-is-required-not-ambient.md) - **0129** — [A seat carries the protocol of its role](0129-a-seat-carries-the-protocol-of-its-role.md) - **0130** — [The predecessor is ending, and its broker goes with it](0130-the-predecessor-is-ending-and-its-broker-goes-with-it.md) +- **0131** — [Everything on the mesh speaks to the broker seat, and AMQP is not a provision](0131-everything-on-the-mesh-speaks-to-the-broker-seat.md) ### Its tiers, from the bottom up diff --git a/03-DESIGN/01-to-be/25-the-bus-on-nats.md b/03-DESIGN/01-to-be/25-the-bus-on-nats.md index 7fdd31b..40d9775 100644 --- a/03-DESIGN/01-to-be/25-the-bus-on-nats.md +++ b/03-DESIGN/01-to-be/25-the-bus-on-nats.md @@ -10,7 +10,7 @@ code: updated: 2026-09-27 decisions: - 02-DECISIONS/0106-the-bus-is-nats.md - - 02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md + - 02-DECISIONS/0131-everything-on-the-mesh-speaks-to-the-broker-seat.md - 02-DECISIONS/0116-the-bus-is-built-in-five-steps.md - 02-DECISIONS/0074-the-wire-is-specified-not-the-types.md - 02-DECISIONS/0079-the-foundation-seats-are-named-after-their-servers.md @@ -303,7 +303,7 @@ the private network. It is raised at genesis like the store, adopted as a module phase. **The deprecated broker is an ordinary module, not a compatibility layer.** Revision, second review -([ADR 0127](../../02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md)): earlier text here, and +([ADR 0127](../../02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md) (superseded by [ADR 0131](../../02-DECISIONS/0131-everything-on-the-mesh-speaks-to-the-broker-seat.md): AMQP is not a provision, and everything speaks to the `mesh-broker` seat)): earlier text here, and ADR 0106 before it, called it `lavinmq-compat` — one purpose, the predecessor's clients, and a retirement condition of no client connected for a period the operator sets. It is none of those. A module may legitimately need an AMQP broker as a **backing service**, the way it needs a @@ -534,7 +534,7 @@ find what changed and why. **Still open:** - ~~Whether EVENTS should be one stream or one per emitting module.~~ **Closed** - ([ADR 0127](../../02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md) (superseding [ADR 0125](../../02-DECISIONS/0125-the-bus-is-the-only-broker.md))): one stream, and not as a + ([ADR 0127](../../02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md) (superseded by [ADR 0131](../../02-DECISIONS/0131-everything-on-the-mesh-speaks-to-the-broker-seat.md): AMQP is not a provision, and everything speaks to the `mesh-broker` seat) (superseding [ADR 0125](../../02-DECISIONS/0125-the-bus-is-the-only-broker.md))): one stream, and not as a preference — the streams the bus is made of are composed as configuration before any module runs, because a provisioner is itself a module that needs a bus account to start. Bootstrapping decides it. diff --git a/03-DESIGN/01-to-be/28-building-the-bus.md b/03-DESIGN/01-to-be/28-building-the-bus.md index d86472c..6b7b4e3 100644 --- a/03-DESIGN/01-to-be/28-building-the-bus.md +++ b/03-DESIGN/01-to-be/28-building-the-bus.md @@ -9,7 +9,7 @@ updated: 2026-09-27 decisions: - 02-DECISIONS/0116-the-bus-is-built-in-five-steps.md - 02-DECISIONS/0106-the-bus-is-nats.md - - 02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md + - 02-DECISIONS/0131-everything-on-the-mesh-speaks-to-the-broker-seat.md - 02-DECISIONS/0126-a-module-declares-its-own-seats.md - 02-DECISIONS/0074-the-wire-is-specified-not-the-types.md - 02-DECISIONS/0079-the-foundation-seats-are-named-after-their-servers.md @@ -673,37 +673,42 @@ healthy while reacting to nothing. the question it depends on has ever been asked of something real is how the plan's own rule about beds gets broken by another route. - > **What this costs if it goes wrong, measured rather than assumed.** On the installation this is - > for, the old broker is also what a whole automation layer outside the mesh connects to — so it - > stays, as an ordinary provider of `amqp` ([ADR 0127](../../02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md)), - > and this step is not its retirement. Nothing in a served request's path goes over the mesh's own - > bus: modules serve from their own containers. What a failed move costs is the mesh's ability to - > *change* anything — pushes, tool calls, new provisioning — until it is finished or undone. That - > is worth knowing before rather than after, and it is why the operator's "as long as my services - > keep running" is a reasonable position rather than a gamble. -- [ ] 5.3 the mesh's own accounts removed from the deprecated broker, and then the broker itself: - after the rollout nothing of the mesh speaks to it, and an account nothing uses is one nobody - rotates. **It finishes now** ([ADR 0130](../../02-DECISIONS/0130-the-predecessor-is-ending-and-its-broker-goes-with-it.md)): - the predecessor is deprecated rather than kept, so once its remnants have stopped the module is - unassigned and the port is free. No retirement machinery — a provision with no consumers has its - provider unassigned, which is ADR 0127 being paid off rather than revised. - + > **What this costs if it goes wrong, measured rather than assumed.** Nothing in a served + > request's path goes over the mesh's own bus: modules serve from their own containers. What a + > failed move costs is the mesh's ability to *change* anything — pushes, tool calls, new + > provisioning — until it is finished or undone. That is worth knowing before rather than + > after, and it is why the operator's "as long as my services keep running" is a reasonable + > position rather than a gamble. **Measured on 2026-09-27**, when a seat emptied itself + > mid-change: 52 containers stayed up and the broker never stopped; the control plane + > crash-looped for two hours and nothing could be deployed until it was repaired by hand. + > An earlier version of this note said the old broker stays as an ordinary provider of + > `amqp` ([ADR 0127](../../02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md)); that is withdrawn by [ADR 0131](../../02-DECISIONS/0131-everything-on-the-mesh-speaks-to-the-broker-seat.md) — see 5.4. +- [ ] 5.3 **the seat changes hands as one act.** A command takes a seat and the assignment taking it + over, and the seat is never empty in between — the emptiness is the outage of 2026-09-27, when + the control plane, which finds its own bus through this seat, lost the address and looped. + Today only `seat rename` exists. This is what 5.2 uses to move `mesh-broker` from the old + broker's assignment to the new one's, and it is built first ([ADR 0131](../../02-DECISIONS/0131-everything-on-the-mesh-speaks-to-the-broker-seat.md)). +- [ ] 5.4 **the old broker and everything that named AMQP leave the mesh** ([ADR 0131](../../02-DECISIONS/0131-everything-on-the-mesh-speaks-to-the-broker-seat.md), + superseding [ADR 0127](../../02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md)): the two modules that + required `amqp` are removed, the broker's module is unassigned and removed, registration refuses + a manifest that provides or requires `amqp`, and a whole-catalogue check asserts none does. Not + a retirement condition — a decision, taken, with the operator's "I don't care if the predecessor + breaks" on record ([ADR 0130](../../02-DECISIONS/0130-the-predecessor-is-ending-and-its-broker-goes-with-it.md)). Retiring with it: the build outcome's second announcement under the module's own name, which - exists only so a catalogue deployed before the rename and one deployed after both hear it. + existed only so a catalogue deployed before the rename and one after both heard it. > **The remote tooling goes with it too.** The predecessor's own mesh talks over that broker, so > shutting it down ends the path that reaches this installation's machines from a workstation. - > The rollout has to be driven from the node, or driven before the broker stops — which is a - > sequencing constraint on 5.2 and not an afterthought. + > The rollout is driven from the node, or before the broker stops — a sequencing constraint on + > 5.2, not an afterthought. +- [ ] 5.5 **the AMQP transport is deleted from the control plane and the hosts**, and the variable + that selected a transport is refused at start as unknown. One bus, nothing to select ([ADR 0131](../../02-DECISIONS/0131-everything-on-the-mesh-speaks-to-the-broker-seat.md)). -> **5.4 is gone, and was wrong from ADR 0127 onward.** It read "the deprecated broker retires -> when its condition holds — no client connected for the period the operator sets", which is -> ADR 0106's framing of it as a compatibility module with an end date. -> [ADR 0127](../../02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md) settled that it is an -> **ordinary provider** of the `amqp` provision, like any module answering a backing service: -> no seat, not foundation, and **no retirement condition**, because the day its last client -> disappears is not a day anything is waiting for. Removed rather than reworded — a step that -> waits for a condition nobody set would sit open forever. +> **The old 5.4 note is history.** It recorded that a retirement *condition* was wrong from +> [ADR 0127](../../02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md) onward, which framed the old broker +> as an ordinary provider with no end. [ADR 0131](../../02-DECISIONS/0131-everything-on-the-mesh-speaks-to-the-broker-seat.md) ends that +> framing in turn: the broker is not kept as a provider either, because AMQP is not a provision. Both +> readings are kept here so the two reversals can be read in order. **Done when.** Every node reports on NATS, and nothing of the mesh's own is left connected to the deprecated broker. diff --git a/03-DESIGN/01-to-be/32-what-a-module-declares.md b/03-DESIGN/01-to-be/32-what-a-module-declares.md index cb43c6a..0d2dcdf 100644 --- a/03-DESIGN/01-to-be/32-what-a-module-declares.md +++ b/03-DESIGN/01-to-be/32-what-a-module-declares.md @@ -357,7 +357,7 @@ controller — because the bus's accounts are configuration rather than somethin creates, so there is no provisioner process in the path and nothing waiting on a bus account in order to make bus accounts. A module that runs a NATS server of its own and offers it as a backing service provides **`nats`**, exactly as the deprecated broker provides `amqp` -([ADR 0127](../../02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md)). +([ADR 0127](../../02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md) (superseded by [ADR 0131](../../02-DECISIONS/0131-everything-on-the-mesh-speaks-to-the-broker-seat.md): AMQP is not a provision, and everything speaks to the `mesh-broker` seat)). They are never the same name. A manifest saying `nats` could otherwise mean either the mesh's nervous system or a private queue, and the difference between those is the whole architecture. @@ -427,7 +427,7 @@ it as an ordinary module once the registry exists. So there are exactly two things the normal path cannot make, both at genesis, both ending the moment the mesh can mint for itself: **the bus's own accounts** (§the bootstrap argument in -[ADR 0127](../../02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md) (superseding [ADR 0125](../../02-DECISIONS/0125-the-bus-is-the-only-broker.md)) — a provisioner is a module and +[ADR 0127](../../02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md) (superseded by [ADR 0131](../../02-DECISIONS/0131-everything-on-the-mesh-speaks-to-the-broker-seat.md): AMQP is not a provision, and everything speaks to the `mesh-broker` seat) (superseding [ADR 0125](../../02-DECISIONS/0125-the-bus-is-the-only-broker.md)) — a provisioner is a module and needs an account before it can run) and **the vault's own credential**. Any third exception is a design failure, and naming these two is what makes a third one visible. diff --git a/03-DESIGN/01-to-be/README.md b/03-DESIGN/01-to-be/README.md index d69c9e7..94c194d 100644 --- a/03-DESIGN/01-to-be/README.md +++ b/03-DESIGN/01-to-be/README.md @@ -40,7 +40,7 @@ document is written and this one's status becomes `implemented`. | [`28-building-the-bus.md`](28-building-the-bus.md) | **Proposed.** The five steps of the bus work in the order their dependencies allow, each ending at a bed — with the surface measured, so no step's size is a guess | [ADR 0116](../../02-DECISIONS/0116-the-bus-is-built-in-five-steps.md), [ADR 0106](../../02-DECISIONS/0106-the-bus-is-nats.md), [ADR 0074](../../02-DECISIONS/0074-the-wire-is-specified-not-the-types.md) | | [`29-a-node-has-operator-accounts.md`](29-a-node-has-operator-accounts.md) | **Proposed.** The mesh models machines but not the humans on them: a node gains operator accounts, and a resource may live under a home owned by its account — what would own ~/.ssh, dotfiles and ~/.config when HAL retires | [ADR 0112](../../02-DECISIONS/0112-a-module-definition-names-no-node-mesh-or-path.md), [ADR 0051](../../02-DECISIONS/0051-shared-data-is-the-operators.md) | -| [`32-what-a-module-declares.md`](32-what-a-module-declares.md) | **Proposed.** What a module declares and what the bus derives from it: three namespaces, subjects from local names, queues never declared, the five relationships, and the build-publish-deploy lifecycle on one bus | [ADR 0126](../../02-DECISIONS/0126-a-module-declares-its-own-seats.md), [ADR 0127](../../02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md) (superseding [ADR 0125](../../02-DECISIONS/0125-the-bus-is-the-only-broker.md)), [ADR 0041](../../02-DECISIONS/0041-events-are-a-relationship.md) | +| [`32-what-a-module-declares.md`](32-what-a-module-declares.md) | **Proposed.** What a module declares and what the bus derives from it: three namespaces, subjects from local names, queues never declared, the five relationships, and the build-publish-deploy lifecycle on one bus | [ADR 0126](../../02-DECISIONS/0126-a-module-declares-its-own-seats.md), [ADR 0127](../../02-DECISIONS/0127-amqp-is-a-provision-not-the-bus.md), superseded by [ADR 0131](../../02-DECISIONS/0131-everything-on-the-mesh-speaks-to-the-broker-seat.md) (superseding [ADR 0125](../../02-DECISIONS/0125-the-bus-is-the-only-broker.md)), [ADR 0041](../../02-DECISIONS/0041-events-are-a-relationship.md) | ## Not yet written