From 71f8012c5b398d2cc31c760acb0a496b0ac4b961 Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 10 Sep 2026 23:43:07 +0200 Subject: [PATCH] The control plane as an ordinary module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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_, 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__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 --- modules/mesh-control/module.json | 69 ++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 modules/mesh-control/module.json diff --git a/modules/mesh-control/module.json b/modules/mesh-control/module.json new file mode 100644 index 0000000..1e65f17 --- /dev/null +++ b/modules/mesh-control/module.json @@ -0,0 +1,69 @@ +{ + "module": "mesh-control", + "version": "1", + "slug": "control", + "capabilities": [ + "container-runtime" + ], + "claims": [ + { + "name": "the-control-plane", + "scope": "mesh" + } + ], + "own-secrets": { + "inventory": "/var/lib/mesh/mesh-control/inventory", + "identity": "/var/lib/mesh/mesh-control/identity", + "licences": "/var/lib/mesh/mesh-control/licences", + "broker": "/var/lib/mesh/mesh-control/broker", + "broker-management": "/var/lib/mesh/mesh-control/broker-management" + }, + "resources": [ + { + "id": "mesh-state", + "type": "directory", + "path": "/var/lib/mesh/mesh-control", + "mode": "0700" + }, + { + "id": "broker-env", + "type": "file", + "path": "/var/lib/mesh/mesh-control/broker.env", + "mode": "0600", + "content": "MESH_BROKER_AMQP=${secret:broker}\nMESH_BROKER_MANAGEMENT=${secret:broker-management}\nMESH_BROKER_ADDRESS=${machine:at}:5671\n" + }, + { + "id": "server", + "type": "container", + "name": "mesh-control", + "image": "mesh-control@sha256:0000000000000000000000000000000000000000000000000000000000000000", + "network": "host", + "args": [ + "serve" + ], + "env-file": [ + "/var/lib/mesh/mesh-control/broker.env" + ], + "env": { + "MESH_STORE_INVENTORY_FILE": "/run/secrets/inventory", + "MESH_STORE_IDENTITY_FILE": "/run/secrets/identity", + "MESH_STORE_LICENCES_FILE": "/run/secrets/licences", + "MESH_BROKER_CERTIFICATE": "/broker-tls/tls.crt" + }, + "volumes": [ + "mesh-broker-tls:/broker-tls:ro", + "/var/lib/mesh/mesh-control/inventory:/run/secrets/inventory:ro", + "/var/lib/mesh/mesh-control/identity:/run/secrets/identity:ro", + "/var/lib/mesh/mesh-control/licences:/run/secrets/licences:ro" + ], + "restart-on": [ + "needs-inventory", + "needs-identity", + "needs-licences", + "needs-broker", + "needs-broker-management", + "broker-env" + ] + } + ] +}