ADR 0067 — genesis is a pivot through a temporary control plane
The control plane's image is built from source and pushed nowhere, so it has no manifest digest; a registry assigns those. Pinning therefore required a registry before the thing that lets a mesh have a registry could start — a dependency the rule created by accident. The lab hid it by raising a disposable registry no production has. Proposed, not accepted. Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
---
|
||||
status: proposed
|
||||
date: 2026-09-10
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0006-the-substrate-and-the-control-plane.md
|
||||
---
|
||||
|
||||
# 67. Genesis is a pivot: a temporary control plane installs the registry that makes it permanent
|
||||
|
||||
## Context
|
||||
|
||||
**The mesh builds its own modules into its own registry, and there is no public registry for them
|
||||
— that is the point, not an omission.** A module is cloned from the forge, built, and published
|
||||
where the mesh can move, replace and back it up. Nothing about that arrangement wants a copy of the
|
||||
mesh's code hosted by somebody else.
|
||||
|
||||
**Every image must be pinned by digest** ([ADR 0006](0006-the-substrate-and-the-control-plane.md)),
|
||||
and the reasoning is exactly right: a bundle is applied where no mesh exists to check anything
|
||||
against anything, so what it names must be exact.
|
||||
|
||||
Those two sentences are individually correct and together they close a door. The digest a pin means
|
||||
is a *manifest* digest, and a manifest digest is **assigned by a registry when something is pushed
|
||||
to it**. The control plane's image is built from source and pushed nowhere, so it has no such
|
||||
digest, so it cannot be named — and a registry cannot be installed without a control plane to
|
||||
install it. That is not a pin. It is a dependency the pinning rule created by accident.
|
||||
|
||||
**It went unnoticed because the lab hid it.** The lab raised a disposable registry, stocked it from
|
||||
a workstation, and rewrote every image reference to point at it — so the lab bootstrapped along a
|
||||
path no real machine has. A first node in the lab always worked, and a first node anywhere else had
|
||||
no path at all. Every bootstrap fault found this year was found late for the same reason: **the
|
||||
install procedure existed only as a test fixture**, and a fixture is free to invent what it needs.
|
||||
|
||||
## Considered Options
|
||||
|
||||
**1. Publish the mesh's own images to a public registry.** Rejected on the premise: there is no
|
||||
public registry for the mesh's modules and there is not meant to be. It would also make raising a
|
||||
mesh depend on somebody continuing to host its code, which is the dependency the whole arrangement
|
||||
exists to remove.
|
||||
|
||||
**2. Build the control plane from source on the first machine.** Rejected. A bare machine would
|
||||
need a toolchain and a working tree — and worse, the source lives in a forge **that runs on the
|
||||
mesh**. A total rebuild would then need the mesh it is rebuilding. Acceptable for adding a node to
|
||||
a healthy mesh; useless for the case that matters.
|
||||
|
||||
**3. Keep a disposable registry as an install step.** Rejected. It exists in no production, and
|
||||
concealing this problem is precisely what it has been doing.
|
||||
|
||||
**4. Pivot through a temporary control plane.** Chosen.
|
||||
|
||||
## Decision
|
||||
|
||||
**An image may be named by the digest of its own configuration.** A bare `sha256:…` names an image
|
||||
the machine already holds — content-addressed, immutable, unforgeable, and requiring nothing to
|
||||
have served it. It satisfies what the pinning rule asks for; the rule simply never contemplated an
|
||||
image that no registry had ever seen. It is legal exactly where nothing could have served one.
|
||||
|
||||
**Genesis is a pivot**, in this order:
|
||||
|
||||
1. the installer **carries the control-plane image** and loads it onto the machine
|
||||
2. a **temporary** control plane is raised from it, named by that image's own digest
|
||||
3. the **registry module is installed** — its image is upstream and it is never built, which
|
||||
[`04-ISSUES/029`](../04-ISSUES/029-the-artifact-store-cannot-be-delivered-by-the-artifact-store/00-report.md)
|
||||
already settled: a module that provides the artifact store cannot be delivered through it
|
||||
4. the control-plane image is **pushed into the mesh's own registry**, which assigns it a manifest
|
||||
digest — the first one it has ever had
|
||||
5. the control plane is **reinstalled as an ordinary module** pinned to that digest
|
||||
|
||||
**The host performs the replacement, not the control plane.** Tier 0 outlives tier 2: the control
|
||||
plane composes a declaration naming the registry-pinned image, and the host applies it and recreates
|
||||
the container. Nothing is asked to replace itself while running, and the control plane is stateless
|
||||
— what it knows is in the store.
|
||||
|
||||
**The installer is tier 0, and a separate program from the host.** Bootstrapping is by hand and
|
||||
changes the machine, which is tier 0's definition. But the host states that it *connects to nothing
|
||||
and listens on nothing*, and that claim is what makes the one thing running forever on every
|
||||
machine auditable. An installer connects to plenty. Same tier, same delivery, different program.
|
||||
|
||||
## Consequences
|
||||
|
||||
- **The control plane stops being a special case.** It becomes an ordinary module with an ordinary
|
||||
image in the mesh's own registry — so the mesh can build and roll out **its own upgrades**, which
|
||||
is what a mesh that runs itself was always reaching for.
|
||||
- **The bundle's job shrinks** to raising a temporary control plane exactly once.
|
||||
- **The source builds the installer; it does not run it.** Cloning moves to a release machine, where
|
||||
a forge being available is an ordinary working assumption, and leaves the disaster-recovery path
|
||||
where it very much is not.
|
||||
- **The lab's disposable registry is deleted.** The lab bootstraps by running the same program a
|
||||
bare machine runs — the only arrangement in which the installer cannot quietly drift out of truth
|
||||
again.
|
||||
- **Two public images remain at genesis** — the store and the broker. An air-gapped install would
|
||||
embed those too, at a much larger artifact; that is a build variant, not a different design.
|
||||
- **A control-plane module manifest must exist**, and did not.
|
||||
- **The handover is the sharp edge.** For one moment the bundle and the module both describe the
|
||||
same container, and the host tracks what it owns. If a safe handover is not expressible with what
|
||||
exists, the install **stops before it** and says what is missing. A machine left without a control
|
||||
plane cannot be fixed remotely, so a partial install that halts cleanly is the better outcome.
|
||||
|
||||
**How each is checked** — an unenforced rule is indistinguishable from a wrong one:
|
||||
|
||||
- **Naming by its own digest:** a machine that can reach no registry at all raises a control plane.
|
||||
- **The pivot completed:** after installing, the running control plane's image is pinned by a digest
|
||||
**the mesh's own registry assigned** — not by an image id. If it is still the image id, the pivot
|
||||
did not happen and the mesh cannot upgrade itself.
|
||||
- **No fiction left in the lab:** the scenario declares no registry machine, and the bed bootstraps
|
||||
through the installer rather than around it.
|
||||
- **The handover:** a machine whose control plane has been replaced still has one, and it answers.
|
||||
|
||||
## References
|
||||
|
||||
- [ADR 0006 — the substrate and the control plane](0006-the-substrate-and-the-control-plane.md),
|
||||
which pinned images by digest and named what a first node fetches.
|
||||
- [ADR 0041 — the host depends on nothing that must be installed first](0041-the-host-depends-on-nothing.md),
|
||||
the tier 0 property this keeps true by not putting the installer inside the host.
|
||||
- [`04-ISSUES/029`](../04-ISSUES/029-the-artifact-store-cannot-be-delivered-by-the-artifact-store/00-report.md),
|
||||
the same cycle one layer down, and the rule that a registry module is named and never built.
|
||||
Reference in New Issue
Block a user