Its image is FROM scratch and runs as 65534. The host writes a sealed own-secret 0600,
owned by root, which is right — but the module then bind-mounted those three files into
the container and told the process to open them. It cannot:
$ docker run --rm -v <0600 root file>:/run/secrets/inventory:ro \
-e MESH_STORE_INVENTORY_FILE=/run/secrets/inventory mesh-control:development status
MESH_STORE_INVENTORY_FILE names /run/secrets/inventory ... and it cannot be read:
open /run/secrets/inventory: permission denied
Measured on a workstation, not reasoned about. Every other module in this catalogue gets
away with the same mount because its runtime container runs as root; this one does not,
and genesis (novox/hq ADR 0067) would have stopped at step 9 with a control-plane module
that starts and cannot open a context.
The connections go through the env file this module already has instead. That file is
mode 0600 and is read by the container runtime's client, which is root — the same reason
the broker's URL has always reached the process this way. It also sidesteps the inode
that a file bind mount pins (290be37, step-ca): --env-file is read afresh at create, and
restart-on names it.
The own-secrets stay exactly as they were, because the installer delivers the substrate's
real connection strings into them with `secret accept` before the first push — the mesh
did not make those credentials and cannot invent them.
Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF
novox/hq ADR 0067 pivots genesis through a temporary control plane and then
reinstalls the control plane as an ordinary module pinned to a digest the mesh's
own registry assigned. That record notes the one thing missing: a control-plane
module manifest, which did not exist.
It could not be written honestly before now. The control plane read its store
connection from MESH_STORE_<CONTEXT>, that connection string carries a password,
and a manifest can put a sealed value into a file's `content` but has nothing
that substitutes into a container's `env`. So the manifest could carry the
password in the clear, or omit the setting. mesh-control now also accepts
MESH_STORE_<CONTEXT>_FILE, which is how every other module here is given secret
material, and the manifest follows.
What the substrate bundle gives the control-plane container today, and where
each part has gone:
MESH_STORE_INVENTORY own-secret `inventory`, mounted, named by _FILE
MESH_STORE_IDENTITY own-secret `identity`, mounted, named by _FILE
MESH_STORE_LICENCES own-secret `licences`, mounted, named by _FILE
MESH_BROKER_AMQP own-secret `broker`, through an env-file hole
MESH_BROKER_MANAGEMENT own-secret `broker-management`, likewise
MESH_BROKER_ADDRESS ${machine:at}:5671 in that same env-file
MESH_BROKER_CERTIFICATE plain env; the path is not a secret
network host, args ["serve"], the broker's TLS volume unchanged
The two broker URLs go through an env-file rather than a file of their own
because mesh-control has no MESH_BROKER_AMQP_FILE. That is the same fault one
layer over, and the same remedy would fix it; it is out of this change's scope
and is written down rather than papered over.
None of these values is in the manifest. Each is an own-secret the operator
supplies with `secret accept` — the mesh cannot invent a connection string — and
the container restarts when any of them changes.
The module claims `the-control-plane` at mesh scope, which the bundle has no way
to say: two control planes writing one inventory is a fault worth refusing at
assignment. It carries no `listens`, because `serve` dials the broker and binds
nothing. The image is the catalogue's placeholder digest for a mesh-built image,
which the installer replaces with what the registry assigned.
Checked with the real parser: all 67 manifests through catalogue.ParseManifest
and every module's CheckIdentity against all four node names — 0 problems — and
this manifest rendered through Resolution.Declaration, so the ${secret:…} names,
${machine:at}, the restart-on ids and the image pin are exercised rather than
merely parsed. Slug `control`: mesh_shanks_control is 19 of the 20 an S3 access
key keeps.
Claude-Session: https://claude.ai/code/session_01LrgweAeERJYBg88c5cKDzF