Adopt the glossary's vocabulary in the mutable design docs

"control plane" -> controller and "substrate" -> foundation throughout
03-DESIGN, 00-META and the README, with 06-the-control-plane.md and
07-the-substrate.md renamed to 06-the-controller.md and 07-the-foundation.md.
The immutable 02-DECISIONS records keep their original wording (and links to
them are unchanged) — a term retired here may still appear there, which the
glossary explains how to read.

Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx
This commit is contained in:
2026-09-16 18:48:52 +02:00
parent f9f48fbbf7
commit 33a00d5656
25 changed files with 233 additions and 233 deletions
+21 -21
View File
@@ -30,7 +30,7 @@ rules cannot all hold at once, and it is resolved by a pivot
**Joining** happens on every machine after the first, and it is ordinary. A mesh exists, so it can
be asked for a token and told what the machine should be. Joining installs the host and nothing
else: no temporary anything, no substrate raised by hand, no registry.
else: no temporary anything, no foundation raised by hand, no registry.
Confusing the two is what produced a procedure that only ever worked in a fixture. A bed that
raises four machines the same way has not tested genesis at all — it has tested joining, four
@@ -38,13 +38,13 @@ times, with the first one hand-fed.
## What changed, and what did not
*2026-09-13.* The installer carries a builder now, and builds the control plane it raises. Three
*2026-09-13.* The installer carries a builder now, and builds the controller it raises. Three
records settle it: [ADR 0070](../../02-DECISIONS/0070-the-catalogue-owns-the-module-graph.md) that
genesis builds rather than carries, [ADR 0071](../../02-DECISIONS/0071-where-genesis-gets-its-source.md)
where it clones from, and [ADR 0073](../../02-DECISIONS/0073-the-installer-carries-a-builder.md) how
the builder arrives — which also records an argument that failed. It was put that a produced image
must be published before anything can fetch it, so the registry would have to come up before the
control plane. It does not: the machine that builds the image is the machine that runs it, and a
controller. It does not: the machine that builds the image is the machine that runs it, and a
local image is named by the digest of its own configuration exactly as a carried one is. **Building
changes where the bytes came from, not where they are.**
@@ -53,7 +53,7 @@ written. What follows describes the program that exists.
## Genesis
The installer is a single program carrying **the builder** inside it — not the control plane
The installer is a single program carrying **the builder** inside it — not the controller
([ADR 0073](../../02-DECISIONS/0073-the-installer-carries-a-builder.md)). What cannot be fetched is
the thing that does the fetching, so that is what is carried; everything else is made here.
@@ -62,12 +62,12 @@ It proceeds in one direction, and every step is safe to run again.
**First it refuses to start if the machine is not ready.** A container runtime, the ability to
write where it must write, the host binary where it expects it — and a repository and a commit to
build from, because an installer told nothing would raise a store and a broker and then have
nothing to raise a control plane from. A machine that is not ready is told what is missing rather
nothing to raise a controller from. A machine that is not ready is told what is missing rather
than half-changed.
**Then it loads the carried builder and builds the control plane with it**, from a repository on a
**Then it loads the carried builder and builds the controller with it**, from a repository on a
mesh that already exists and a named commit ([ADR 0071](../../02-DECISIONS/0071-where-genesis-gets-its-source.md)).
This is the same repository and path every later rebuild of the control plane will use, so what
This is the same repository and path every later rebuild of the controller will use, so what
raises the mesh is the same thing that will maintain it.
**Then it describes what the machine will become.** The image it just made is named by the digest
@@ -75,7 +75,7 @@ of its own configuration — content-addressed and unforgeable, and requiring no
it. That is legal precisely where nothing could have served one, and it is why building here needs
no registry: the machine that made the image is the machine that will run it.
**Then it raises the substrate and a temporary control plane, and waits for that control plane to
**Then it raises the foundation and a temporary controller, and waits for that controller to
answer.** At this point the machine is a mesh of one node with nothing joined to it.
**Then the machine joins the mesh it is itself running.** It enrols, and an agent runs on it. Being
@@ -84,13 +84,13 @@ enrolling is itself the thing that makes a mesh hear from a machine.
**Then it installs a registry**, so the mesh has somewhere to keep its own images.
**Then it publishes the control plane's image to that registry**, which is the moment the image
**Then it publishes the controller's image to that registry**, which is the moment the image
first receives a digest assigned by something other than itself. This is the carrying step, and it
is the same step for all three things the build loop cannot produce for itself — the control plane,
is the same step for all three things the build loop cannot produce for itself — the controller,
the registry, and the builder. The rule and its closed list are in
[`12-a-module-repository`](12-a-module-repository.md#the-three-the-loop-cannot-build-and-there-are-only-three).
**Then it installs the control plane again, as an ordinary module pinned to that digest, and drops
**Then it installs the controller again, as an ordinary module pinned to that digest, and drops
the temporary one.** The pivot is complete: what raised the mesh is gone, and what runs is a module
like any other. From here the mesh can build and roll out its own upgrades, including to the thing
that runs it.
@@ -98,7 +98,7 @@ that runs it.
## After the pivot, and still part of installing
Genesis ends with a mesh of one that runs, and that is not the same as a mesh that works. What it
has is a control plane, a store, a queue and a registry. What it cannot yet do is **produce
has is a controller, a store, a queue and a registry. What it cannot yet do is **produce
anything** — and almost every module in the catalogue is waiting to be produced, because a manifest
names what its artifacts are and nothing has made them.
@@ -107,9 +107,9 @@ So installing continues:
**The builder arrives, and installing is what brings it.** It is a module like any other and is
assigned to a machine like any other, but it cannot be built by the thing it is — see
[`12-a-module-repository`](12-a-module-repository.md#the-three-the-loop-cannot-build-and-there-are-only-three).
So it is carried, and it is already here: it is what built the control plane. The last step of
So it is carried, and it is already here: it is what built the controller. The last step of
installing publishes it into the mesh's own registry, installs it as an ordinary module pinned to
that digest, and issues it a broker account — the same two acts the control plane went through,
that digest, and issues it a broker account — the same two acts the controller went through,
plus the one thing only a builder needs. The account is issued before the machine is sent anything,
because a builder that arrives without its credential starts, finds nothing it may read, and waits,
which looks exactly like a builder with no work.
@@ -121,12 +121,12 @@ publishes each artifact into the mesh's own registry, and hands back the module
pinned and the commit recorded. The mesh records that, and from then on the module is described by
something it made rather than by a placeholder.
**The control plane is built like the rest.** It was carried in and published once, which got the
**The controller is built like the rest.** It was carried in and published once, which got the
mesh running; building it from its own repository and path is what makes it upgradeable. The first
time that happens is the moment the mesh stops depending on the installer for anything.
**And then the catalogue.** Every module with source of its own is built the same way. Until this
has happened a mesh can install only what is public or carried, which is the substrate and little
has happened a mesh can install only what is public or carried, which is the foundation and little
else.
Only after all of that is the ordinary loop available: change a module's source, the mesh notices
@@ -138,7 +138,7 @@ What remains after *that* belongs to somebody else: adding machines, and decidin
## Joining
A machine joins with the host binary and a token. It does not raise a substrate, does not install a
A machine joins with the host binary and a token. It does not raise a foundation, does not install a
registry, and is never enrolled twice. The mesh already knows how to tell a machine what to be;
joining is the point at which a machine starts listening.
@@ -169,8 +169,8 @@ paragraphs above describing the catalogue being built are a thing somebody now t
thing that cannot happen.
**A module's declaration still has to be copied onto the machine by hand.** The installer reads the
registry's and the control plane's manifests from a checkout somebody put there. The control plane's
now lives in the control plane's own repository, which the installer clones anyway, so this is a
registry's and the controller's manifests from a checkout somebody put there. The controller's
now lives in the controller's own repository, which the installer clones anyway, so this is a
thing that can be removed rather than a thing that must be designed.
**A machine has no account for a registry that asks for one.** The mesh grants a consumer a
@@ -198,6 +198,6 @@ the SDK inside `docker build`, which is slow and names a branch head rather than
| An image is named exactly | A machine refuses a bundle naming an image by tag. The refusal is exercised, not assumed. |
| The installer is what installed this | **Nothing.** See above. |
| The builder can arrive on a fresh mesh | The installer carries it and installs it as its last step, and the genesis bed raises a machine by running the installer. A bed that raises one any other way fails its own acceptance check. |
| The control plane a mesh runs is one it built | The genesis bed asserts the running control plane is pinned to a digest this mesh's own registry serves, for an image built from a named repository and commit — not one the installer carried. |
| A core module is built rather than only carried | The control plane is rebuilt from its own repository and path, and the running mesh is upgraded to the result — the same path any module takes. |
| The controller a mesh runs is one it built | The genesis bed asserts the running controller is pinned to a digest this mesh's own registry serves, for an image built from a named repository and commit — not one the installer carried. |
| A core module is built rather than only carried | The controller is rebuilt from its own repository and path, and the running mesh is upgraded to the result — the same path any module takes. |
| Installing produced a mesh that can produce | A module with source of its own is asked for and comes back pinned to a digest this mesh's registry assigned, not to a placeholder. **Done by hand on a raised machine, not yet by a bed** — it built the shared base and then a module naming that base. Nothing automated asserts it, which makes this the weakest check on this page. |