Rename mesh-control -> mesh-controller, substrate -> foundation
One name per thing, per the HQ glossary: the module/container/image/binary/repo becomes mesh-controller, the seat the-controller, and the store+broker pair the foundation (embedded base bundles, default template and example lock renamed with their go:embed directives). No behaviour change — a pure vocabulary rename. Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
// Reading the manager node's PUBLIC sealing key out of the bound facts the mesh delivers, and
|
||||
// writing a sealed refresh token in the wire shape mesh-control reads.
|
||||
// writing a sealed refresh token in the wire shape mesh-controller reads.
|
||||
//
|
||||
// **The public key is delivered, not derived.** The manager module holds no node key of its own
|
||||
// (novox/hq ADR 0050) — it is deliberately never given one. To seal a refresh token to this node it
|
||||
// needs the node's PUBLIC sealing key, and mesh-control puts that in the manager holder's bound facts
|
||||
// needs the node's PUBLIC sealing key, and mesh-controller puts that in the manager holder's bound facts
|
||||
// (`serves.manager_public_key`), safe to disclose because it is public. Both adoption and every
|
||||
// rotation read it from there.
|
||||
|
||||
@@ -23,7 +23,7 @@ export function managerPublicKey(boundFile: string): string {
|
||||
return key;
|
||||
}
|
||||
|
||||
/** Write a sealed refresh token in the {sealed, manager_key} wire shape mesh-control reads. */
|
||||
/** Write a sealed refresh token in the {sealed, manager_key} wire shape mesh-controller reads. */
|
||||
export function writeSealedGrant(path: string, sealed: string, managerKey: string): void {
|
||||
mkdirSync(dirname(path), { recursive: true });
|
||||
const tmp = `${path}.tmp`;
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
// never the refresh token — which it seals per consumer holder and stores;
|
||||
// 5. poll usage with the fresh access token and record the licence-grain reading.
|
||||
//
|
||||
// mesh-control receives the products of steps 3–4 through `licence submit-refresh` (access token +
|
||||
// mesh-controller receives the products of steps 3–4 through `licence submit-refresh` (access token +
|
||||
// sealed box). The refresh token never leaves this process except as ciphertext, and it never had to
|
||||
// be opened here at all — the host did that.
|
||||
//
|
||||
// This runs as `mesh-tools run`, which connects no broker, so the outputs are written to files the
|
||||
// host mounts; the submit itself (the transport to mesh-control) is done by the caller invoking
|
||||
// `mesh-control licence submit-refresh`. In the lab that caller is the scenario; in production it is
|
||||
// host mounts; the submit itself (the transport to mesh-controller) is done by the caller invoking
|
||||
// `mesh-controller licence submit-refresh`. In the lab that caller is the scenario; in production it is
|
||||
// an authenticated call the manager node makes. The transport is the one part stubbed here — FLAGGED
|
||||
// — because a cross-node authenticated command surface is out of this module's scope.
|
||||
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
// carve-out delivers the refresh token to the manager module the way the mesh delivers every other
|
||||
// credential: sealed to the node's key, and unsealed by the *host* — never by the module. The host
|
||||
// unseals with Go's `golang.org/x/crypto/nacl/box.OpenAnonymous` (mesh-host
|
||||
// internal/identity/sealing.go), and mesh-control seals with `box.SealAnonymous`
|
||||
// (mesh-control internal/secrets/seal.go). Both are NaCl `crypto_box_seal`:
|
||||
// internal/identity/sealing.go), and mesh-controller seals with `box.SealAnonymous`
|
||||
// (mesh-controller internal/secrets/seal.go). Both are NaCl `crypto_box_seal`:
|
||||
//
|
||||
// sealed = ephemeralPub(32) ‖ crypto_box(msg, nonce, recipientPub, ephemeralSecret)
|
||||
// nonce = blake2b( ephemeralPub ‖ recipientPub , 24 bytes, unkeyed )
|
||||
//
|
||||
// When the vendor rotates the refresh token, the manager module must store the new one back the
|
||||
// same way — sealed to the manager node's own sealing key — so mesh-control keeps it without ever
|
||||
// same way — sealed to the manager node's own sealing key — so mesh-controller keeps it without ever
|
||||
// reading it and the host can later unseal it to deliver the cleartext again. That reseal happens
|
||||
// here, on the manager node, in TypeScript. It therefore has to produce the *identical* byte format
|
||||
// Go's `Open` accepts, or the host would refuse the delivery.
|
||||
@@ -27,7 +27,7 @@
|
||||
// (package.json dependencies; novox/hq ADR 0052).
|
||||
//
|
||||
// **How it is kept honest.** A cross-language test seals a fixture here and opens it in Go
|
||||
// (mesh-control internal/secrets/sealedbox_xcheck_test.go); the fixture is regenerated from this
|
||||
// (mesh-controller internal/secrets/sealedbox_xcheck_test.go); the fixture is regenerated from this
|
||||
// `seal()`. A drift between this seal and Go's box surfaces there as a seal Go cannot open, not as a
|
||||
// refresh token silently mangled in production.
|
||||
//
|
||||
|
||||
@@ -5,7 +5,7 @@ import { generateKeyPairSync } from "node:crypto";
|
||||
import { seal } from "../sealedbox.ts";
|
||||
|
||||
// The definitive proof that this seal interoperates with Go's box.OpenAnonymous (the host's Unseal
|
||||
// and mesh-control's secrets.Seal/Open) is a cross-language test in mesh-control
|
||||
// and mesh-controller's secrets.Seal/Open) is a cross-language test in mesh-controller
|
||||
// (internal/secrets/sealedbox_xcheck_test.go), which opens a fixture this module's seal() produced.
|
||||
// These tests hold the TypeScript side: the output has the crypto_box_seal shape, and it is
|
||||
// randomised so a rotation that changed nothing looks nothing like one that changed everything.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"module": "mesh-control",
|
||||
"module": "mesh-controller",
|
||||
"version": "1",
|
||||
"slug": "control",
|
||||
"capabilities": [
|
||||
@@ -7,43 +7,43 @@
|
||||
],
|
||||
"claims": [
|
||||
{
|
||||
"name": "the-control-plane",
|
||||
"name": "the-controller",
|
||||
"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",
|
||||
"broker-address": "/var/lib/mesh/mesh-control/broker-address"
|
||||
"inventory": "/var/lib/mesh/mesh-controller/inventory",
|
||||
"identity": "/var/lib/mesh/mesh-controller/identity",
|
||||
"licences": "/var/lib/mesh/mesh-controller/licences",
|
||||
"broker": "/var/lib/mesh/mesh-controller/broker",
|
||||
"broker-management": "/var/lib/mesh/mesh-controller/broker-management",
|
||||
"broker-address": "/var/lib/mesh/mesh-controller/broker-address"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"id": "mesh-state",
|
||||
"type": "directory",
|
||||
"path": "/var/lib/mesh/mesh-control",
|
||||
"path": "/var/lib/mesh/mesh-controller",
|
||||
"mode": "0700"
|
||||
},
|
||||
{
|
||||
"id": "control-env",
|
||||
"type": "file",
|
||||
"path": "/var/lib/mesh/mesh-control/control.env",
|
||||
"path": "/var/lib/mesh/mesh-controller/control.env",
|
||||
"mode": "0600",
|
||||
"content": "MESH_STORE_INVENTORY=${secret:inventory}\nMESH_STORE_IDENTITY=${secret:identity}\nMESH_STORE_LICENCES=${secret:licences}\nMESH_BROKER_AMQP=${secret:broker}\nMESH_BROKER_MANAGEMENT=${secret:broker-management}\nMESH_BROKER_ADDRESS=${secret:broker-address}\n"
|
||||
},
|
||||
{
|
||||
"id": "server",
|
||||
"type": "container",
|
||||
"name": "mesh-control",
|
||||
"image": "mesh-control@sha256:0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"name": "mesh-controller",
|
||||
"image": "mesh-controller@sha256:0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"network": "host",
|
||||
"args": [
|
||||
"serve"
|
||||
],
|
||||
"env-file": [
|
||||
"/var/lib/mesh/mesh-control/control.env"
|
||||
"/var/lib/mesh/mesh-controller/control.env"
|
||||
],
|
||||
"env": {
|
||||
"MESH_BROKER_CERTIFICATE": "/broker-tls/tls.crt"
|
||||
@@ -1,4 +1,4 @@
|
||||
// model-usage's entrypoint — the usage context store's consumer (novox/hq ADR 0054). mesh-control is
|
||||
// model-usage's entrypoint — the usage context store's consumer (novox/hq ADR 0054). mesh-controller is
|
||||
// a CLI and cannot consume events, so the store that keeps the latest usage reading is a MODULE: it
|
||||
// subscribes to `module.*.usage.*` and upserts each row. Like the audit-logger, the on(...) IS the
|
||||
// whole handshake — the runtime imports this once the broker is bound, and every usage event any
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# The route-proxy module's runtime image: the reference reverse proxy compiled into a container.
|
||||
#
|
||||
# **The proxy source is not vendored here.** The canonical proxy — the contract written as something
|
||||
# that runs — lives in the mesh-control repository at examples/route-proxy (novox/hq 08-connectivity
|
||||
# that runs — lives in the mesh-controller repository at examples/route-proxy (novox/hq 08-connectivity
|
||||
# §3). This module ships the *packaging*, not a second copy of the contract, so the build context is
|
||||
# the mesh-control repository root, and this Dockerfile compiles ./examples/route-proxy from it.
|
||||
# the mesh-controller repository root, and this Dockerfile compiles ./examples/route-proxy from it.
|
||||
#
|
||||
# docker build -f mesh-catalog/modules/route-proxy/Dockerfile \
|
||||
# -t mesh-route-proxy:development <path-to>/mesh-control
|
||||
# -t mesh-route-proxy:development <path-to>/mesh-controller
|
||||
#
|
||||
# The mesh pins the digest of what this produces; the committed module.json carries the placeholder
|
||||
# digest every mesh-built image does, replaced at publish.
|
||||
|
||||
@@ -30,9 +30,9 @@ an event. It only reads the file the mesh writes. (Contrast `redis`, which mints
|
||||
## How it ships the Go proxy
|
||||
|
||||
The proxy is a Go program, unlike the TypeScript tool-runtime modules. The canonical source is
|
||||
**not vendored here** — it lives in the mesh-control repository at `examples/route-proxy`, the
|
||||
**not vendored here** — it lives in the mesh-controller repository at `examples/route-proxy`, the
|
||||
contract written as something that runs. This module ships only the packaging: a multi-stage
|
||||
[`Dockerfile`](Dockerfile) whose build context is the mesh-control repository root and which
|
||||
[`Dockerfile`](Dockerfile) whose build context is the mesh-controller repository root and which
|
||||
compiles `./examples/route-proxy` into `mesh-route-proxy`. The committed `module.json` carries the
|
||||
placeholder digest every mesh-built image does (`@sha256:0000…`); the mesh pins the real digest at
|
||||
publish.
|
||||
|
||||
Reference in New Issue
Block a user