Files
mesh-host/examples
jschoubben 8e12b3c9e4 Name the decisions these tests defend, and check the bundle at all
From auditing the decision records: of 28, only 12 were named by any
test, so "which decisions are defended" could not be answered without
reading everything. ADR 0017 says a test names the decision it defends —
that rule was itself unenforced.

Most of the gap was citation, not coverage. Drift detection was tested
in several places without naming ADR 0011; the archive refusal without
naming 0012; forged declarations without naming 0002. Named now, so the
question is answerable by grep.

The bundle was the real gap: nothing tested substrate-first-node.lock at
all. It is what a machine becomes when there is no mesh to ask — the one
declaration applied with nothing to verify it against — and it was
edited by hand and read by nothing but a running host.

Two tests now assert what it carries: exactly postgres, lavinmq and the
control plane. That defends ADR 0028, which removed the object store
from the substrate after it had been a member for months on the strength
of "it cannot grant itself a bucket" — true, and the answer to only half
the test. Nothing counted what the bundle held.

Fault-injected, and the first attempt did not bite: the injection landed
on a comment line, which stripComments discards. Injecting into the
image field fails as it should.
2026-08-31 17:33:34 +02:00
..

Examples

substrate-first-node.lock

What a machine must be before a mesh exists — the bootstrap in novox/hq 07-the-substrate.md, whole:

0  a container runtime
1  the store runs
2  a database per context        `inventory` and `identity`
3  those contexts' schemas       mesh-control migrate
4  the broker runs               with a certificate it generated itself
5  the control plane runs        mesh-control serve

A machine that applies this is a mesh — one node, with nothing joined to it yet, which is exactly what the first node is (novox/hq ADR 0004). From here it hands out tokens and everything else joins the ordinary way.

This file said it stopped at step 4 for longer than that was true, which is its own small lesson: a comment about what something does not do is a comment nobody updates.

Build a host carrying it:

make host SYSTEM=arch BUNDLE=examples/substrate-first-node.lock

The registry address and digests have to be replaced before this is useful. They are written as 192.0.2.250:5000/…@sha256:… because a digest belongs to whatever registry serves it — here, one a lab scenario raises, which reports its digests when it comes up. That is not a placeholder to be tidied away: a bundle is built for a target, and which registry that target pulls from is part of the target.

What was verified, and how

On a lab machine confirmed sealed — curl https://example.com times out, the lab registry answers 200 — the whole bundle applied from bare: eight resources, inventory created and mesh nowhere, the node table present with its indexes, the migration recorded, and LavinMQ answering lavinmqctl status with AMQP listening on 5672.

Three consecutive reconciles after that: already matches — 8 resource(s) checked, each time.

Then the machine was rebooted, and everything came back: docker from boot: enabled, both containers because the host creates every container --restart unless-stopped (internal/apply/apply.go), the schema intact in its named volume, and reconcile still finding nothing to do.

The reboot is worth doing rather than assuming. Nothing in the declaration asks for a container to return, so that it does is a property of the host, and the only way to know it holds is to take the machine away and give it back.