mesh-bootstrap: the first-node procedure, as a program rather than a test

The only complete written-down copy of how a mesh is stood up was an integration
test in the lab. That is why every bootstrap gap kept being found late: an install
procedure that lives as a test fixture is exercised by whoever writes tests, never
by whoever installs. This is that procedure.

A separate binary, not a mesh-host subcommand. mesh-host says of itself that it
connects to nothing and listens on nothing and that what it applies comes from a
file, and that sentence is what makes an always-running root daemon auditable. An
installer loads images and interrogates a control plane. Same tier, different
program.

The control plane's image is carried, not built and not fetched. The forge that
holds its source runs on the mesh, so a bootstrap that had to fetch it would need
a mesh in order to raise one. Embedding breaks that cycle the way the carried
bundle breaks "copy it onto a machine and run it". The image id is read out of the
saved tar before the runtime is asked anything, which is what makes the load
idempotent: the installer can ask whether the machine already holds exactly this.

Five steps, each idempotent and each saying whether it found or changed something,
because this is run over and over by somebody getting a machine working. It stops
at a running substrate with a control plane that replies — enrolment, the module
catalogue and assignment are the next stage and are deliberately absent.

Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
This commit is contained in:
2026-09-10 23:17:30 +02:00
parent 4af9483219
commit b82ab95f74
18 changed files with 2620 additions and 2 deletions
+24 -2
View File
@@ -7,7 +7,7 @@ LDFLAGS := -s -w -X main.builtFor=$(SYSTEM) -X main.version=$(VERSION)
# a second file to arrive with it is not "copy it and run it".
BUNDLE ?=
.PHONY: check test vet fmt build clean host
.PHONY: check test vet fmt build clean host hosts bootstrap packaging-test
check: fmt vet test packaging-test build
@@ -57,5 +57,27 @@ host:
exit $$status
@echo "built for $(SYSTEM) carrying $(BUNDLE)"
# The installer, carrying the control plane's image:
# make bootstrap IMAGE=mesh-control:v1.2.3
#
# The image is BUILT ELSEWHERE and handed over — mesh-control's own `make image` — and embedded
# here at release time. Not built on the machine being bootstrapped, and not fetched: the forge
# that holds mesh-control's source runs on the mesh, so a bootstrap that had to fetch or build the
# control plane would need a mesh in order to raise one. Carrying it breaks that cycle, the same
# way carrying the bundle breaks the "copy it onto a machine and run it" one (novox/hq ADR 0005).
#
# The saved image occupies the embed slot for the length of one build and the placeholder goes
# back, exactly as `host:` does with the bundle. Nothing large is ever committed.
bootstrap:
@test -n "$(IMAGE)" || { echo "IMAGE= is required; an installer carrying no control-plane image cannot raise a mesh"; exit 1; }
@docker image inspect "$(IMAGE)" >/dev/null 2>&1 || { echo "this machine does not hold $(IMAGE) — build it in mesh-control with 'make image'"; exit 1; }
@cp internal/image/control-plane.tar internal/image/control-plane.tar.placeholder
@docker save --output internal/image/control-plane.tar "$(IMAGE)"
@CGO_ENABLED=0 go build -ldflags="-s -w -X main.version=$(VERSION)" -o mesh-bootstrap ./cmd/mesh-bootstrap; \
status=$$?; \
mv internal/image/control-plane.tar.placeholder internal/image/control-plane.tar; \
exit $$status
@echo "built mesh-bootstrap carrying $(IMAGE)"
clean:
rm -f mesh-host
rm -f mesh-host mesh-bootstrap