Issue 076 opened: a served fact made at first start cannot be served; ADR 0097's refusal of an undeclared base is live

This commit is contained in:
2026-09-21 22:16:15 +02:00
parent 559683318b
commit bc373797c7
4 changed files with 52 additions and 6 deletions
@@ -36,10 +36,11 @@ image the manifest did not declare is refused before the build, naming the image
its own stages, declared arguments and `scratch` are not fetches. An unpinned vendor image is its own stages, declared arguments and `scratch` are not fetches. An unpinned vendor image is
refused: a tag is what somebody else can move. refused: a tag is what somebody else can move.
A recipe whose `FROM` names an undeclared base is **said, not yet refused**: the mesh's own images A recipe whose `FROM` names an undeclared base was at first said, not refused: the mesh's own
— the control plane's, the builder's, the tool runtime's — start from a public base and declare images — the control plane's, the tool runtime's, the route proxy's — started from a public base
none, and refusing those refuses genesis. They declare their bases next; until then every build and declared none, and refusing those refuses genesis. *Amended the same day:* those three declare
names the undeclared base and the remedy. their bases now, and an undeclared `FROM` is refused like an undeclared copy. The builder's own
image and the examples are built by `make`, not by the mesh, and take arguments with defaults.
The package half of the issue is not decided here: the mesh's package registry already proxies The package half of the issue is not decided here: the mesh's package registry already proxies
the public one, and the failure the report saw has to be run again to be placed. the public one, and the failure the report saw has to be run again to be placed.
+2 -2
View File
@@ -221,8 +221,8 @@ and nothing uploaded on a second copy.
entry is a module's artifact or an image published elsewhere, pinned by digest, read from one entry is a module's artifact or an image published elsewhere, pinned by digest, read from one
build argument; the image is copied into the mesh's registry before the build and the recipe is build argument; the image is copied into the mesh's registry before the build and the recipe is
handed the copy. A recipe whose `COPY --from` names a registry image the manifest did not declare handed the copy. A recipe whose `COPY --from` names a registry image the manifest did not declare
is refused before the build, naming it and the remedy; an undeclared `FROM` is said, not yet is refused before the build, naming it and the remedy, and so is an undeclared `FROM`: the mesh's
refused, because the mesh's own images start from a public base and declare none. *How it is own images declare the bases they start from. *How it is
checked:* builder tests on a declared and an unpinned vendor image, and a recipe test on what checked:* builder tests on a declared and an unpinned vendor image, and a recipe test on what
counts as a copy and what as a base. counts as a copy and what as a base.
@@ -27,3 +27,6 @@ sidecar beds proved a sidecar alone, which the module beds prove whole; the mini
grant beds proved a grant with a second store beside the foundation's, which the grant bed and grant beds proved a grant with a second store beside the foundation's, which the grant bed and
the vault bed prove against the catalogue. Retired, with their scenarios. Two remain declared: the vault bed prove against the catalogue. Retired, with their scenarios. Two remain declared:
route-forwarding, which needs the certificate authority beside the proxy, and the large mesh test. route-forwarding, which needs the certificate authority beside the proxy, and the large mesh test.
*Route-forwarding's conversion is blocked:* the catalogue's authority cannot be raised as written
([issue 076](../076-a-served-fact-made-at-first-start-cannot-be-served/00-report.md)).
@@ -0,0 +1,42 @@
---
status: located
opened: 2026-09-21
located-in: [mesh-catalog modules/step-ca, mesh-controller internal/catalogue (serves)]
fixed-by:
amended-design:
---
# A served fact made at first start cannot be served, so the catalogue's authority cannot start
## Symptom, as observed
The catalogue's certificate authority module declares its root certificate, its root key and
that key's password as its own secrets, and writes each into a file the container is told to
initialise from. The mesh mints an own secret as random bytes. Random bytes are not a
certificate: as written, the authority cannot initialise, and no bed has ever raised it — the
whole-mesh bed that names it has not run since it was converted. Found while converting the
route-forwarding bed to the catalogue's proxy, which requires the authority beside it.
The authority can make its own root at first start — the certificate bed raises it that way and
it issues within a second. What it cannot do then is tell the mesh what that root is: a
consumer of `acme-ca` is given `${bound:acme-ca:root}` from the provider's `serves`, which is
written in the manifest before anything runs.
## Why it matters beyond this instance
- **Two kinds of secret the vocabulary does not distinguish.** A value the mesh may invent (a
password) and a value only the module can produce (a key pair, a certificate) are both
"own secrets", and the mesh invents both.
- **A served fact that exists only after first start** has no way into a binding. Anything a
module generates and its consumers must trust — a root, a public key, a fingerprint — is in
the same position.
- Every consumer of `acme-ca`, which today is the route proxy, is blocked with it.
## What would close it
Either a module may say a secret is *made by the module* — the mesh reserves the name, the
module writes the value once, the mesh takes custody of it and delivers it where it is bound —
or a served fact may be *contributed at run time* by the provider's runtime rather than written
in its manifest. The first is the smaller change and covers the root certificate; the second is
what a fingerprint or a public key wants. Decided, then the authority raised in the lab beside
the proxy, which is the route-forwarding bed's conversion.