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
+18 -18
View File
@@ -47,10 +47,10 @@ mesh database, and it has no listening surface.
|---|---|
| `apply` | reconciling declared state on this machine |
| `store` | local state, authoritative while disconnected |
| `link` | the single outbound connection to the control plane |
| `link` | the single outbound connection to the controller |
| `profile` | what this machine can be asked to do |
| `inventory` | what this machine is and has |
| `substrate.lock` | the pinned tier-1 descriptor, appliable with no mesh present |
| `foundation.lock` | the pinned tier-1 descriptor, appliable with no mesh present |
### apply
@@ -74,7 +74,7 @@ the machine in whatever state it reached, and nothing must claim otherwise.
### store
Local, and **authoritative while disconnected**. Not a cache of the control plane — the record
Local, and **authoritative while disconnected**. Not a cache of the controller — the record
of what this node has applied and what it currently holds.
This is structural rather than convenient: if disconnection is an ordinary situation rather
@@ -84,7 +84,7 @@ not come back and ask what it is.
### link
The node's one connection to the control plane, and its security boundary
The node's one connection to the controller, and its security boundary
([ADR 0004](../../02-DECISIONS/0004-a-node-and-how-it-joins.md)).
It is the broker connection that already exists
@@ -137,11 +137,11 @@ One behaviour, two sources
| Situation | Source |
|---|---|
| no mesh reachable | `substrate.lock` — the pinned bundle the host carries |
| mesh reachable | the control plane, over the link |
| no mesh reachable | `foundation.lock` — the pinned bundle the host carries |
| mesh reachable | the controller, over the link |
**The first node is not a different kind of node.** It is a node whose mesh is not up yet. It
applies the bundle it carries, the control plane comes up on top of it, and from that moment it
applies the bundle it carries, the controller comes up on top of it, and from that moment it
takes declarations like every other node. Its specialness is temporary and self-erasing.
**A joining node does the minimum to be reachable and nothing else** — an identity, an address,
@@ -155,7 +155,7 @@ Settled by [ADR 0005](../../02-DECISIONS/0005-the-node-host.md).
**JSON**, because the host has no dependencies to spend and the standard library carries no
YAML. **An ordered list of typed resources**, each with a stable identity — the order is stated
rather than derived, because deriving it would be the host deciding the thing most likely to
differ from what the control plane intended.
differ from what the controller intended.
**Unknown is refused, never skipped.** An unknown version, type or field refuses the whole
declaration. A host that skipped what it did not understand would apply most of it and report
@@ -173,16 +173,16 @@ without one, applying the bundle it carries, has nothing to check against.
Staged so each stage is verifiable in the lab before the next exists.
**1 — profile and inventory.** The host runs on a machine, detects what it can do, and reports
what it is. No control plane, no declarations, no network. Verifiable immediately: the lab's
what it is. No controller, no declarations, no network. Verifiable immediately: the lab's
`place:` gains its first implementation, and a raised scenario finally contains something.
**2 — apply, from the bundle.** The host applies `substrate.lock` with no mesh present. This is
**2 — apply, from the bundle.** The host applies `foundation.lock` with no mesh present. This is
the first node's path, and it is the claim the skeleton's Move 1 rests on and has never proved:
that one host can raise the substrate alone.
that one host can raise the foundation alone.
Raising the substrate uses **four** shapes — `package`, `container`, `service`, `action` —
Raising the foundation uses **four** shapes — `package`, `container`, `service`, `action` —
counted from the bundle that exists rather than reasoned about. `file` and `directory` are listed
below because they are the cheapest to be sure of and a substrate that needed them would find them
below because they are the cheapest to be sure of and a foundation that needed them would find them
ready; the current bundle simply does not. **All of them are built:**
| | | |
@@ -225,7 +225,7 @@ container runtime. All three were instead verified against a real machine — a
labelled, replaced when its declaration changed, exec'd into and removed; an action that exits
zero and satisfies nothing failing the apply. That is lab-installation work
([`04-lab-installation.md`](04-lab-installation.md)) rather than a constraint on the design, but
until it is done the substrate bootstrap has no end-to-end test.
until it is done the foundation bootstrap has no end-to-end test.
**3 — link and store.** The node connects, receives declarations, and holds what it applied.
@@ -313,7 +313,7 @@ reported to be distinguishable from one that reported an empty list.*
## Open
- **Whether one host can raise the substrate alone.** Move 1 assumes it. Stage 2 tests it, and
- **Whether one host can raise the foundation alone.** Move 1 assumes it. Stage 2 tests it, and
if it is false the tier boundary moves.
- **What the host carries versus what it finds.** It manages `wg`, `nft`, `pacman`, `docker`;
it does not contain them, and how it obtains one it lacks is undecided —
@@ -329,15 +329,15 @@ reported to be distinguishable from one that reported an empty list.*
## What was added to the vocabulary, and why each cost was worth paying
*Written 2026-08-30. Every addition widens what a compromised control plane can express, so the
*Written 2026-08-30. Every addition widens what a compromised controller can express, so the
count is asserted by a test and a change to it is a decision rather than a convenience.*
Four shapes raise the substrate. Five more exist because most of what a person installs is not a
Four shapes raise the foundation. Five more exist because most of what a person installs is not a
service:
| | why |
|---|---|
| **file**, **directory** | the substrate needs neither, and almost everything else does |
| **file**, **directory** | the foundation needs neither, and almost everything else does |
| **user** | a shell, a terminal, a chat client, a desktop are a package plus configuration **in somebody's home**. A mesh with no user owns `/etc` and nothing anybody looks at |
| **archive** | a theme is hundreds of files. Inlining them makes every declaration enormous and rewrites all of them when one changes |
| **network** | a module of several containers has to let them reach each other by name, and doing it with an action would create something nothing could ever remove ([ADR 0029](../../02-DECISIONS/0029-a-network-is-a-shape-because-an-action-cannot-be-undone.md)) |