Files
hq/02-DECISIONS/0073-the-installer-carries-a-builder.md
T
jschoubben 9f5ac38662 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.
2026-09-13 03:20:07 +02:00

5.4 KiB

topic, status, date, deciders, reconstructed, extends
topic status date deciders reconstructed extends
the tiers accepted 2026-09-13 jochen false 0070-the-catalogue-owns-the-module-graph.md

73. The installer carries a builder, and the registry precedes the control plane

Context

ADR 0070 decided that genesis builds rather than carries, and ADR 0071 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 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), 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 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 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 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 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).