The mesh runs its own registry, certifies its own names, and computes its own filtering

Issue 003 is answered in both halves: manifests are parsed strictly, and a
module says what it listens on and from where rather than carrying a key
nothing reads. The design records what was built and how each part is checked.

Issue 013 is new, found by reading while writing the first module that has
both a computed file and a service that needs it. The file arrived second.
It failed, then the next reconcile fixed it, which is why nothing caught it.
This commit is contained in:
2026-08-31 00:37:34 +02:00
parent ba14e2b629
commit 778efaba8b
4 changed files with 213 additions and 7 deletions
+79 -1
View File
@@ -4,7 +4,9 @@ status: designed
code:
- mesh-control internal/builder
- mesh-control internal/catalogue/build.go
updated: 2026-08-30
- mesh-control internal/inventory/secrets.go
- mesh-control cmd/mesh-builder
updated: 2026-08-31
decisions:
- 02-DECISIONS/0009-modules-and-the-graph.md
- 02-DECISIONS/0010-delivery.md
@@ -108,6 +110,34 @@ Three properties of the builder that are decisions:
is not running, and those want completely different responses — the same rule the host follows
about a service that does not exist
### And it is a module the mesh assigns
*2026-08-31. Written after `builder issue --node`, which is the part that makes the sentence
"holding its own credential" true rather than aspirational.*
A build machine is a machine that runs the builder, and there is exactly one honest way to say
which machines those are: **assign it**. So the builder is a module like any other — an image, a
container, a working directory, and a claim so a machine does not end up running two.
The one thing that could not be a module in the ordinary way is the credential. It is not
generated, because the broker has to have been told about it, and it is not written in a manifest,
because a manifest is public and the same file goes to every machine that ever runs it. So the
mesh **creates the account, seals the URL to the machine that will use it, and discards the
plaintext** — the "given, not generated" case above, and its first user.
Nothing is printed. A credential shown on a terminal is a credential in a scrollback buffer, and
the copy that matters would then exist in two places, one of which nobody is guarding.
**What this replaces:** a builder started by hand with whatever credential was to hand, which in
practice meant the broker's administrative account. *A program documented as holding its own
credential and given somebody else's is worse than one with no story at all* — the documentation
is what stops anybody checking.
*Checked in the lab by assigning it and then asking the mesh to build a module: the credential
file arrives readable only by that machine, names the scoped account rather than the broker's own,
and the build completes — which is the only proof the credential authenticates, because a
container that is up holding a credential it cannot use looks identical from outside.*
## What is kept
**Every result, including the failures.** A failed build that leaves no trace is indistinguishable
@@ -167,6 +197,35 @@ Remade when the machine's sealing key changes. **Declared and not made is refuse
module whose own credential is silently absent starts, fails to authenticate, and the reason is
three layers from the machine reporting it.
### Some of them the mesh cannot make
*2026-08-31, from making the builder a module — the first thing to hold one.*
A generated secret is the mesh's, and remaking it costs nothing: **nothing else ever knew the old
one.** That is the assumption the paragraph above rests on, and it is not true of every secret a
module needs.
A broker account's password exists because **the broker was told about it**. A licence key exists
because somebody bought it. The mesh's job with these is to carry the value to the machine that
will use it and then be unable to read it — the same sealing, from the other direction: **given,
not generated.**
Treating the two alike is wrong in exactly one place, and it is the place nobody looks. When a
machine rejoins it has a new sealing key, and everything sealed to the old one is remade. Remaking
a *given* secret puts thirty-two random bytes where a working credential was, and every visible
signal says it worked: the mesh sealed a secret, the machine applied it, the file is there with
the right permissions. What fails is a program authenticating to something else, hours later,
with an error that names neither the mesh nor the secret.
So **where the value came from is recorded, and a given secret is never regenerated.** A rejoined
machine asking for one is refused, naming the remedy — issue it again — because the remedy is a
command somebody runs and no amount of pushing will produce a password the broker has never heard
of.
*Checked by taking a given secret, changing the machine's sealing key, and asserting the mesh
refuses rather than answers; and by asserting that two ordinary pushes hand back the same value,
without which the refusal would be a secret that never survives at all.*
## What one assignment gets you
A database module, written to see whether it could be:
@@ -203,3 +262,22 @@ access, or are not build output. None of that describes a digest-pinned archive,
second service for one kind of immutable blob is two things to run, two to back up, and two ways
for an artifact to be missing. **Overturnable without touching anything else**: a manifest carries
a URL and a digest, and neither says what served it.
### And the mesh runs it
*2026-08-31.* Which registry is a **provision**, mesh-scoped: a build machine requires
`artifact-store` and is told where it is, the same way an application is told where its database
is. Nothing is configured with an address.
This closes the last thing the mesh depended on and did not run. The registry a bootstrap pulls
from belongs to whoever raised the machine; from the moment the mesh has one of its own, an
artifact's home is somewhere the mesh can move, replace and back up.
**The chicken and egg is the bootstrap's, resolved the same way.** A registry module is an
`upstream` artifact — mirrored from a registry that already exists into the one being started. The
first copy comes from outside, exactly once, and every copy after it is the mesh's.
*Checked in the lab by assigning it and then asking for `/v2/` — on the machine, and from a second
machine across the private network, because a mesh-scoped provision that only answers locally is
not one. A container that is running is not a registry that replies, and this project has paid for
that distinction once already.*