Renumber the records 1 to 23

The consolidation left a sparse sequence -- 1, 4, 6, 7, 9, 10, 12, 15, 16, 18,
19, 25, 34, 35, 36, 37, 40, 42, 44, 45, 48, 49, 58 -- where the gaps were only
the archaeology of what used to be there.

Renumbered contiguously. Renames run in ascending order, so every target number
is already free and no two files ever collide.

The reference rewrite is one simultaneous pass rather than a sequence of
replacements. Numbers moved into slots other numbers were vacating -- the node
host went 37 to 16 while the lab went 16 to 9 -- so replacing one at a time
would have cascaded and silently pointed things at the wrong record.

Seven plain-text references survived the merges as prose rather than links,
naming records that no longer existed: the enrolment token, the link boundary,
what a declaration is, reachability, the repository structure. Each mapped to
the consolidated record that now holds it.

Verified rather than assumed: every [ADR NNNN](path) link now has matching text
and target, checked across the whole repository, and the checker passes.

Frontmatter `consolidates:` lists dropped -- they named records that are gone,
and each consolidated record already says in prose what it absorbed.
This commit is contained in:
2026-08-28 23:28:34 +02:00
parent 77f3a4cea7
commit e1febe8e0f
84 changed files with 441 additions and 449 deletions
+18 -18
View File
@@ -4,14 +4,14 @@ status: designed
code: []
updated: 2026-08-27
decisions:
- 02-DECISIONS/0019-how-this-repository-works.md
- 02-DECISIONS/0037-the-node-host.md
- 02-DECISIONS/0036-a-node-and-how-it-joins.md
- 02-DECISIONS/0048-the-substrate-and-the-control-plane.md
- 02-DECISIONS/0037-the-node-host.md
- 02-DECISIONS/0048-the-substrate-and-the-control-plane.md
- 02-DECISIONS/0049-connectivity.md
- 02-DECISIONS/0037-the-node-host.md
- 02-DECISIONS/0011-how-this-repository-works.md
- 02-DECISIONS/0016-the-node-host.md
- 02-DECISIONS/0015-a-node-and-how-it-joins.md
- 02-DECISIONS/0021-the-substrate-and-the-control-plane.md
- 02-DECISIONS/0016-the-node-host.md
- 02-DECISIONS/0021-the-substrate-and-the-control-plane.md
- 02-DECISIONS/0022-connectivity.md
- 02-DECISIONS/0016-the-node-host.md
---
# The substrate
@@ -27,7 +27,7 @@ Every module that needs a database asks the control plane's provisioning for one
plane needs a database too — and it cannot ask itself, because it is not running yet. That
circularity is not an awkwardness to work around; it *is* the definition. Anything on the wrong
side of it must be raised some other way, and the other way is the bundle the host carries
([ADR 0036](../../02-DECISIONS/0036-a-node-and-how-it-joins.md)).
([ADR 0015](../../02-DECISIONS/0015-a-node-and-how-it-joins.md)).
The test, applied:
@@ -38,11 +38,11 @@ The test, applied:
| an object store — **MinIO** | artifacts and blobs it delivers | no — it needs a bucket to hold them | **substrate** |
| an image registry — **the OCI registry** | images it delivers to nodes | no — it needs a repository | **substrate** |
| an identity provider | only if it delegates authentication | — | **conditional, below** |
| ingress — **Traefik** | not to start; only to be reached by name | — it grants itself one afterwards | **not substrate** ([ADR 0049](../../02-DECISIONS/0049-connectivity.md)) |
| ingress — **Traefik** | not to start; only to be reached by name | — it grants itself one afterwards | **not substrate** ([ADR 0022](../../02-DECISIONS/0022-connectivity.md)) |
| anything else the mesh hosts | no | — | not substrate |
**The role and the product are both written**, here and everywhere
([ADR 0048](../../02-DECISIONS/0048-the-substrate-and-the-control-plane.md)). The role is what the argument
([ADR 0021](../../02-DECISIONS/0021-the-substrate-and-the-control-plane.md)). The role is what the argument
turns on — the test above works on roles, and would give the same answers for a different store.
The product is what actually gets installed and pinned, and a design that names only the role
does not record that the choice was ever made.
@@ -96,19 +96,19 @@ Being substrate and being in the bundle are two different questions:
| PostgreSQL | yes — the control plane's own state lives in it | **yes** — there is nowhere to put that state otherwise |
| LavinMQ | yes — it cannot grant itself a virtual host | **not established** — see below |
| MinIO | yes — it cannot grant itself a bucket | no — nothing is delivered before the mesh exists |
| the OCI registry | yes — it cannot grant itself a repository | no — the first node fetches upstream ([ADR 0048](../../02-DECISIONS/0048-the-substrate-and-the-control-plane.md)) |
| the OCI registry | yes — it cannot grant itself a repository | no — the first node fetches upstream ([ADR 0021](../../02-DECISIONS/0021-the-substrate-and-the-control-plane.md)) |
The three on the bottom rows are **substrate by role and ordinary by delivery**: by the time
they are wanted there is a control plane, and it provisions them the way it provisions anything.
That keeps the bundle to roughly one image rather than four, which is what makes it small enough
for the review [ADR 0037](../../02-DECISIONS/0037-the-node-host.md)
for the review [ADR 0016](../../02-DECISIONS/0016-the-node-host.md)
requires.
**Why pinned:** the bundle is applied when no mesh exists, so nothing can resolve a version, ask
a registry, or check a constraint. What the host carries must already be exact.
**Why references and not payload:** the bundle names images by **digest** and the host fetches
them ([ADR 0048](../../02-DECISIONS/0048-the-substrate-and-the-control-plane.md)). A first node is
them ([ADR 0021](../../02-DECISIONS/0021-the-substrate-and-the-control-plane.md)). A first node is
a real machine with a network; the sealed case is the lab, and the lab places images itself.
Reproducibility comes from pinning the identity of a thing rather than carrying its bytes, which
@@ -136,7 +136,7 @@ container, so a container runtime must be working before anything else happens
is a *package*, not a container.
**Which runtime is detected, not chosen**
([ADR 0037](../../02-DECISIONS/0037-the-node-host.md)): a machine that
([ADR 0016](../../02-DECISIONS/0016-the-node-host.md)): a machine that
already has one keeps it. On a machine with none, the control plane names the package, because
what it is called differs per system. It is:
@@ -145,7 +145,7 @@ what it is called differs per system. It is:
- **adopted rather than installed** when the machine already has one with configuration somebody
chose ([research 012](../../01-RESEARCH/012-the-minimum-viable-node/00-overview.md));
- a package, which needs the machine's own package manager and a network — both permitted by
[ADR 0048](../../02-DECISIONS/0048-the-substrate-and-the-control-plane.md).
[ADR 0021](../../02-DECISIONS/0021-the-substrate-and-the-control-plane.md).
So the host's bootstrap vocabulary is six shapes: **package**, **container**, **file**,
**directory**, **service**, and **action**. **All six are built**
@@ -155,7 +155,7 @@ blocked on the host any longer.
**Steps 2 and 3 happen before there is a mesh to do them**, which is why provisioning is part of
the bootstrap rather than a service consumers use later. They are **actions** the bundle
declares and the host runs
([ADR 0037](../../02-DECISIONS/0037-the-node-host.md)) — so the
([ADR 0016](../../02-DECISIONS/0016-the-node-host.md)) — so the
host's vocabulary grows by one shape rather than by one resource type per substrate service.
## Open
@@ -170,7 +170,7 @@ host's vocabulary grows by one shape rather than by one resource type per substr
question about the control plane's internal shape, not about the substrate**, which is why it is
not answered here.
- ~~**Whether the host can do step 2.**~~ **Resolved** by
[ADR 0037](../../02-DECISIONS/0037-the-node-host.md). A service
[ADR 0016](../../02-DECISIONS/0016-the-node-host.md). A service
running on this machine is part of this machine, so the scope was never in question — the real
question was whether the host must learn what a database is, and it must not. The bundle
declares an **action**; the host runs it and verifies it, and what a database means stays with