Files
hq/02-DECISIONS/0078-the-store-and-broker-are-modules.md
T
jschoubben 1111bd84d7 Establish the repo for the completed Phase 0-3 build
Settles the design repository now that the self-upgrade build is on main:
- Records the two decisions that shipped without a record — ADR 0077 (the
  controller/foundation/node vocabulary) and ADR 0078 (the store and broker are
  ordinary modules); accepts ADR 0075 and 0076, which shipped work rests on.
- Fills issue 051's amended-design and wires ADR 0078 into 07-the-foundation.
- Sweeps the repo rename (mesh-control -> mesh-controller) into the mutable docs
  now that the forge repo is renamed; updates the glossary note and repos.md.
- Fixes the six broken links from the design-doc renames, indexes the glossary,
  regenerates the decisions reading order.

Both checks (records.py, index.py) are green. Statuses stay honest: the build is
on main and lab-proven but not deployed as the production mesh, so the to-be docs
remain in-progress and the as-is layer (the hal mesh) is unchanged — graduation
to implemented + as-is belongs to deployment, not merge.

https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx
2026-09-17 00:04:58 +02:00

3.4 KiB

topic, status, date, deciders, reconstructed, extends
topic status date deciders reconstructed extends
the tiers accepted 2026-09-16 jochen false 0033-the-substrate-is-a-store-and-a-broker.md

78. The store and the broker are ordinary modules

Context

ADR 0033 settled that the foundation is a store and a broker, raised at genesis; ADR 0006 settled that the controller cannot grant itself either, because it consumes them and is not running yet to ask. Both were raised as bundle resources — plumbing, with no record in the mesh's module graph.

That left two costs, named in issue 051. The foundation's own store and broker could not be upgraded — nothing owned them as modules. And a mesh that wanted a database or a queue for its modules installed the postgres/lavinmq modules, each of which raised a second server: a mesh ran two postgres and two brokers.

Considered Options

  1. Leave them as bundle-only plumbing. Rejected: they cannot be upgraded, and the second server stays. The floor keeps a permanent specialty in it.
  2. The control-plane pivot verbatim — raise a temporary one, install the module, retire the temporary (ADR 0067). Rejected for a stateful server: it means a handover with real downtime, tearing down the store the controller is mid-read of.
  3. Adopt in place. Chosen.

Decision

The foundation's store and broker are adopted in place as the ordinary postgres and lavinmq modules. Genesis still raises them first (nothing else can — ADR 0006), then each module declares a container with the same name, image and spec the foundation raised, so the applier — which keys on the container name and compares a spec digest — reconciles it rather than raising a second. The credentials are the foundation's, made at genesis and carried in through secret accept, because the mesh cannot invent a credential that already made the databases. The servers bind mesh-wide so a consumer on any node can reach the one shared server.

A mesh runs one postgres and one lavinmq, and each is upgradeable through a stated window: the store's is a connection-pool reconnect; the broker's is the harder case of recreating the bus the push travels over, so the mesh reconnects to the one that returns.

Consequences

The twelve-module floor has no specialty left in it — the store and broker are moments in a module's life, not a separate kind of thing. Two follow-ups are tracked: issue 054 (the adopted servers bind 0.0.0.0 before the packet filter is installed) and issue 055 (whether a consumer on another node reaches them over the overlay).

What got harder: a foundation upgrade recreates the very server the controller reads from, or the bus the instruction to upgrade travels over — a window that a stateless module upgrade does not have.

References