Consolidate: 65 decision records to 23
Every remaining cluster merged. Each was one design that had been split across
several records because it was worked out over days rather than at once.
the node host 8 -> 1 applies not decides, depends on nothing,
per operating system, root service, the
launcher, episodic, what a declaration is,
actions from the bundle only
a node and how it joins 4 -> 1 what a node is, joining, the link as
security boundary, the enrolment token
modules and the graph 7 -> 1 everything is a module, no domain modules,
three edges, provisioning, the core library
substrate and control 6 -> 1 the test, seven contexts, one control plane,
plane the authority is not a database, the named
products, the pinned bundle
connectivity 3 -> 1 a route is a grant, reachability declared,
filter rules
delivery 5 -> 1 reconciliation not a pipeline, artifacts,
the three silos, a failed step, the verdict
the lab 5 -> 1 (earlier)
how this repository 10 -> 1 (earlier)
works
Nothing was dropped. Each consolidated record carries the reasoning of the ones
it absorbs -- the measurements, the incidents, the alternatives rejected --
because that reasoning is the only reason to keep a record at all. What is gone
is the fragmentation: eight files to read to understand tier 0, when tier 0 is
one component.
The four superseded records went too. They existed to point at their
successors, and the successors now contain what they said.
The checker made this safe. Each merge left dangling links -- 38 files after
the host merge alone -- and it named every one. Nothing was found by reading,
and a manual pass would certainly have missed some, including references inside
AGENTS.md which every session loads.
This commit is contained in:
@@ -5,13 +5,13 @@ code: []
|
||||
updated: 2026-08-27
|
||||
decisions:
|
||||
- 02-DECISIONS/0019-how-this-repository-works.md
|
||||
- 02-DECISIONS/0037-the-host-applies-it-does-not-decide.md
|
||||
- 02-DECISIONS/0038-a-node-joins-by-linking-first.md
|
||||
- 02-DECISIONS/0046-the-installer-fetches-what-it-pins.md
|
||||
- 02-DECISIONS/0047-the-bundle-may-carry-actions-the-link-may-not.md
|
||||
- 02-DECISIONS/0048-the-substrate-is-named.md
|
||||
- 02-DECISIONS/0049-a-route-is-a-grant.md
|
||||
- 02-DECISIONS/0060-the-host-is-built-per-operating-system.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
|
||||
---
|
||||
|
||||
# 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 0038](../../02-DECISIONS/0038-a-node-joins-by-linking-first.md)).
|
||||
([ADR 0036](../../02-DECISIONS/0036-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-a-route-is-a-grant.md)) |
|
||||
| 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)) |
|
||||
| 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-is-named.md)). The role is what the argument
|
||||
([ADR 0048](../../02-DECISIONS/0048-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 0046](../../02-DECISIONS/0046-the-installer-fetches-what-it-pins.md)) |
|
||||
| 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 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 0047](../../02-DECISIONS/0047-the-bundle-may-carry-actions-the-link-may-not.md)
|
||||
for the review [ADR 0037](../../02-DECISIONS/0037-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 0046](../../02-DECISIONS/0046-the-installer-fetches-what-it-pins.md)). A first node is
|
||||
them ([ADR 0048](../../02-DECISIONS/0048-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 0060](../../02-DECISIONS/0060-the-host-is-built-per-operating-system.md)): a machine that
|
||||
([ADR 0037](../../02-DECISIONS/0037-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 0046](../../02-DECISIONS/0046-the-installer-fetches-what-it-pins.md).
|
||||
[ADR 0048](../../02-DECISIONS/0048-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 0047](../../02-DECISIONS/0047-the-bundle-may-carry-actions-the-link-may-not.md)) — so the
|
||||
([ADR 0037](../../02-DECISIONS/0037-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 0047](../../02-DECISIONS/0047-the-bundle-may-carry-actions-the-link-may-not.md). A service
|
||||
[ADR 0037](../../02-DECISIONS/0037-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
|
||||
|
||||
Reference in New Issue
Block a user