Settle how the builder arrives, and what it publishes into

The two questions the design record named as the one gap stopping a fresh mesh
from producing anything. They cannot be answered apart: a builder with nowhere
to publish has made a file on a disk.

The registry's role did not change — the answer to 'must it precede the control
plane' did, because the control plane's image is now produced rather than
carried, and a produced image must be put somewhere before it can be fetched.
This commit is contained in:
2026-09-13 03:20:07 +02:00
parent 3983188b8a
commit 9f5ac38662
2 changed files with 93 additions and 0 deletions
@@ -0,0 +1,92 @@
---
topic: the tiers
status: accepted
date: 2026-09-13
deciders: jochen
reconstructed: false
extends: 0070-the-catalogue-owns-the-module-graph.md
---
# 73. The installer carries a builder, and the registry precedes the control plane
## Context
[ADR 0070](0070-the-catalogue-owns-the-module-graph.md) decided that genesis builds rather than
carries, and [ADR 0071](0071-where-genesis-gets-its-source.md) settled where it clones from. Two
questions were left open, and the design record names them as the one gap that stops a fresh mesh
from being able to produce anything at all: **how the builder arrives**, and **what it publishes
into**.
They cannot be answered apart. A builder that arrives with nowhere to publish has produced a file
on a disk, and a place to publish with nothing to produce is an empty shelf.
Today the installer carries the control plane's image inside itself. That works, and it is why
genesis needs no registry: nothing is ever pulled, because the one image that matters is already
present. The cost is that the mesh which results holds an artifact it did not make, cannot rebuild,
and knows nothing about — no version, no source, no edges. That is the same shape as the fault
[issue 044](../04-ISSUES/044-the-runtime-every-module-builds-on-cannot-be-built-by-the-mesh/00-report.md)
recorded for the shared runtime, and fixing it there while shipping it here on every new mesh would
be a strange place to stop.
## Decision
**The installer carries a builder, and nothing else.** One artifact, not a growing set. It clones
the source at a named commit, checks what it got ([ADR 0071](0071-where-genesis-gets-its-source.md)),
and produces the control plane from the same repository and path that any later rebuild of it would
use. What raises the mesh is therefore the same thing that will maintain it, and there is no second
mechanism kept in step with the first.
**The registry joins the substrate, and precedes the control plane.** Not because it became more
fundamental, but because the answer to a stated question changed:
| | is it substrate? | must it precede the control plane? |
|---|---|---|
| the store | yes | yes — there is nowhere else to put the control plane's state |
| the broker | yes | yes — the control plane reaches a machine only over it |
| the image registry | yes — it cannot grant itself a repository | **yes, now** — the control plane's image is produced here, and a produced image has to be put somewhere before anything can fetch it |
[ADR 0033](0033-the-substrate-is-a-store-and-a-broker.md) answered that last cell *no*, and was
right at the time, for the reason it gave: the first machine fetched the control plane from
upstream, so nothing needed a registry until there was already a control plane to install one. That
premise is what this decision removes. The registry's role never changed; what changed is whether
anything needs it before the control plane exists.
**The substrate bundle therefore carries three services and no control plane**, where it carried
two services and a control plane. It does not grow: an image comes out as one goes in.
## Consequences
**Genesis gains a step and loses one.** The registry is raised with the substrate rather than
installed as the first act of a temporary control plane, and a build step appears before the
control plane is raised at all. The pivot described in
[ADR 0067](0067-genesis-is-a-pivot.md) survives unchanged in shape — a temporary control plane is
still what installs the permanent one — but what it installs is now something this mesh built.
**A fresh mesh can produce from the moment it exists.** The builder is present before the control
plane is, so the core modules, the catalogue and the builder's own module can be built in the
ordinary way rather than waiting for somebody to carry them in. The paragraphs in
[`17-raising-a-mesh`](../03-DESIGN/01-to-be/17-raising-a-mesh.md) that describe this were describing
something that could not start; they can start now.
**Genesis needs more of the outside world.** Carrying an image needed nothing but the installer.
Building one needs the source, and whatever the build itself reaches for. This is a real cost and
is not waved away: it makes genesis fail in more ways, all of them at a step that says what it was
doing. It is accepted because the alternative is a mesh that cannot rebuild its own control plane,
which fails in exactly one way, silently, later, and for ever.
**A pre-built bundle remains possible and is not this.** Nothing here forbids delivering artifacts
rather than building them; it fixes where they may come from. A bundle of pre-built core modules is
an **export of a mesh that built them**, carrying what the catalogue knows about each alongside the
artifact itself — so that loading one leaves the graph in the state building would have left it. A
bundle that carries images without that is the thing this decision rejects, whoever ships it.
## What this does not decide
**Whether the builder's own module is carried or built.** It builds everything else; what installs
*it* as an ordinary module afterwards, so that it too can be upgraded, is the same closed-list
question [`12-a-module-repository`](../03-DESIGN/01-to-be/12-a-module-repository.md) already holds,
and is unchanged by this.
**How a machine authenticates to a registry that asks it to.** Genesis raises its own and reaches it
over the loopback, so this remains a joining problem
([issue 042](../04-ISSUES/042-nothing-gives-a-node-an-account-for-a-registry/00-report.md)).