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:
@@ -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. |
|
||||
|
||||
Reference in New Issue
Block a user