diff --git a/02-DECISIONS/0073-the-installer-carries-a-builder.md b/02-DECISIONS/0073-the-installer-carries-a-builder.md new file mode 100644 index 0000000..c61b369 --- /dev/null +++ b/02-DECISIONS/0073-the-installer-carries-a-builder.md @@ -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)). diff --git a/02-DECISIONS/README.md b/02-DECISIONS/README.md index 758393a..b9b864a 100644 --- a/02-DECISIONS/README.md +++ b/02-DECISIONS/README.md @@ -105,6 +105,7 @@ python3 00-META/checks/index.py fail if stale - **0070** — [The catalogue owns the module graph, and genesis builds rather than carries](0070-the-catalogue-owns-the-module-graph.md) - **0071** — [Genesis clones from a mesh, and checks what it got](0071-where-genesis-gets-its-source.md) - **0072** — [Two graphs, and a build chain that orders itself](0072-two-graphs-and-the-build-chain.md) +- **0073** — [The installer carries a builder, and the registry precedes the control plane](0073-the-installer-carries-a-builder.md) ### What runs on them, and how it gets there