Jochen asked whether the order made sense. It did not -- it followed when things happened to be decided, which after consolidation is fictional anyway since record 5 alone folds decisions taken across a week. Concretely wrong before: the domain statement sat at 8, after five engineering rules; the constitution was scattered across 5, 12 and 17; the tiers landed at 15, 16, 21 and 22 with process records in between. Now it walks: what the mesh is (1-3), its tiers from the bottom up (4-8), what runs on them and how it gets there (9-10), how it is built (11-16), how it is checked (17-18), how we work (19-23). Two things made this safe rather than free. It is a permutation, not a compaction, so the renames go through temporary names -- otherwise two files want one slot and one is lost. And the reference rewrite is a single simultaneous pass, because almost every number moved into a slot another number was vacating; replacing one at a time would have cascaded and pointed things at the wrong record while still resolving. Verified: 284 [ADR NNNN](path) links across the repository, all with matching text and target. The ordering principle is now stated in 19 rather than left implicit -- the repository already said "the numbering is the flow" about its folders, and there was no reason for the records to be the exception.
3.5 KiB
status, opened, located-in, fixed-by, amended-design
| status | opened | located-in | fixed-by | amended-design | ||
|---|---|---|---|---|---|---|
| open | 2026-08-28 |
|
009 — A digest-pinned image cannot be placed in the lab, so container cannot be tested there
Symptom
Two accepted decisions collide, and the collision makes one resource shape untestable.
-
ADR 0006 pins images by digest, and the host refuses an image reference that is not pinned:
resource "store": image "alpine:3.20" is not pinned. Write it as name@sha256:... -
The lab cannot place a digest-pinned image. A sealed scenario cannot reach a registry, so the lab exports an image from the workstation and loads it in the machine — and that loses the digest.
So a container resource is refused by the host if it names a tag, and unusable if it names a
digest. There is no declaration the lab can currently raise that exercises the shape.
What was measured
Not inferred. docker save alpine@sha256:d9e8… produces an archive with no repo tag, because
a repo digest exists only for an image a registry served. Loading it says:
Loaded image ID: sha256:63f227… (not "Loaded image: alpine:3.20")
and docker images then lists nothing — the image is there but dangling. A container declaring
that digest therefore falls through to the registry:
Unable to find image 'alpine@sha256:d9e8…' locally
dial tcp: lookup registry-1.docker.io: no such host
which is correct behaviour on a machine with no route out.
What is not affected
Everything else placed in the same sealed machine works, and was verified there:
| shape | |
|---|---|
package |
applied, idempotent |
service incl. boot: enabled |
applied, read back as enabled |
action |
ran, verified |
container |
blocked by this issue |
Why it matters more than one shape
The container shape is the substrate. Every step of raising a mesh past the container runtime is
a container (07-the-substrate.md), so the
bootstrap cannot be tested end-to-end until this is resolved — which is the thing the lab exists
for.
The shape of a resolution
A registry inside the scenario, on its public segment, that machines pull from. That is not a workaround: it is what the real mesh does — ADR 0006 names an OCI registry as substrate, and every node after the first pulls from the mesh's own. Testing against a registry is testing the real path rather than a stand-in for it.
It also removes the lab's export-and-push mechanism rather than fixing it, which is the better outcome: pushing image tarballs over the hypervisor was always a lab-only invention.
Not decided here, because it is design rather than repair: where the registry runs, whether it is scenery like the router (ADR 0016) or a placed artifact, and how images get into it.
Incidental, and already fixed
The lab's own check on the load was too weak: it matched "Loaded image", which is a prefix of
both Loaded image: and Loaded image ID:. So a load that produced an unusable dangling image
reported success, and the failure surfaced later as a container that would not start. It now
matches Loaded image: exactly and says what the runtime actually said.
That is this repository's own subject arriving in its own tooling: a check that passes on the wrong thing is worse than no check, because it moves the failure away from its cause.