From 1111bd84d7ec6b4a0c918fd948387aeb8d538e0f Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 17 Sep 2026 00:04:58 +0200 Subject: [PATCH] Establish the repo for the completed Phase 0-3 build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Settles the design repository now that the self-upgrade build is on main: - Records the two decisions that shipped without a record — ADR 0077 (the controller/foundation/node vocabulary) and ADR 0078 (the store and broker are ordinary modules); accepts ADR 0075 and 0076, which shipped work rests on. - Fills issue 051's amended-design and wires ADR 0078 into 07-the-foundation. - Sweeps the repo rename (mesh-control -> mesh-controller) into the mutable docs now that the forge repo is renamed; updates the glossary note and repos.md. - Fixes the six broken links from the design-doc renames, indexes the glossary, regenerates the decisions reading order. Both checks (records.py, index.py) are green. Statuses stay honest: the build is on main and lab-proven but not deployed as the production mesh, so the to-be docs remain in-progress and the as-is layer (the hal mesh) is unchanged — graduation to implemented + as-is belongs to deployment, not merge. https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx --- 00-META/README.md | 1 + 00-META/checks/records.py | 2 +- 00-META/glossary.md | 2 +- 00-META/process/06-writing-a-module.md | 2 +- 00-META/process/07-feature-branches.md | 2 +- 00-META/repos.md | 10 +-- .../006-mesh-from-scratch/00-overview.md | 2 +- .../011-the-module-graph/00-overview.md | 4 +- ...n-names-what-the-consumer-is-coupled-to.md | 2 +- ...-the-control-plane-authenticates-nobody.md | 2 +- .../0036-bootstrap-ends-at-a-usable-mesh.md | 2 +- ...070-the-catalogue-owns-the-module-graph.md | 2 +- ...0075-two-stores-and-which-provides-what.md | 2 +- .../0076-the-sdk-is-a-published-package.md | 2 +- .../0077-the-controller-and-the-foundation.md | 61 ++++++++++++++++++ .../0078-the-store-and-broker-are-modules.md | 63 +++++++++++++++++++ 02-DECISIONS/README.md | 10 +-- 03-DESIGN/01-to-be/06-the-controller.md | 2 +- 03-DESIGN/01-to-be/07-the-foundation.md | 7 ++- 03-DESIGN/01-to-be/08-connectivity.md | 6 +- 03-DESIGN/01-to-be/09-the-node-lifecycle.md | 12 ++-- 03-DESIGN/01-to-be/10-delivery.md | 6 +- 03-DESIGN/01-to-be/11-a-board.md | 4 +- 03-DESIGN/01-to-be/12-a-module-repository.md | 8 +-- .../13-credentials-and-their-rotation.md | 6 +- 03-DESIGN/01-to-be/14-model-access.md | 4 +- 03-DESIGN/01-to-be/15-the-agent-session.md | 2 +- 03-DESIGN/01-to-be/18-building-a-module.md | 4 +- 03-DESIGN/01-to-be/19-the-module-protocol.md | 2 +- 03-DESIGN/01-to-be/20-writing-a-module.md | 2 +- .../01-to-be/21-the-installation-in-full.md | 2 +- .../00-report.md | 2 +- .../00-report.md | 2 +- 33 files changed, 188 insertions(+), 54 deletions(-) create mode 100644 02-DECISIONS/0077-the-controller-and-the-foundation.md create mode 100644 02-DECISIONS/0078-the-store-and-broker-are-modules.md diff --git a/00-META/README.md b/00-META/README.md index 6e159c1..d3c6021 100644 --- a/00-META/README.md +++ b/00-META/README.md @@ -9,6 +9,7 @@ works — plus the engineering practice that holds across everything Novox build | [`context.md`](context.md) | The environment — conditions, not aspirations | | [`effect.md`](effect.md) | What is different when the work is done | | [`how-we-build.md`](how-we-build.md) | The rules that hold across the mesh, each one earned. **The source of the mesh constitution** — the governed page the mesh injects into design sessions is derived from it. | +| [`glossary.md`](glossary.md) | One name per thing — the authority on vocabulary, and the words that were retired | | [`repos.md`](repos.md) | Where implementation lives, and what each repository owns | | [`process/`](process/) | The playbooks — how work moves through this repository, for engineers and agents alike | diff --git a/00-META/checks/records.py b/00-META/checks/records.py index 4469db8..83e3d1d 100644 --- a/00-META/checks/records.py +++ b/00-META/checks/records.py @@ -293,7 +293,7 @@ def check_status_against_code(failures): Deliberately weak, and that is the point of it being mechanical. It cannot tell whether the prose is true, only that a document has stopped claiming to be unbuilt once it points at - something. `code: [mesh-control]` — a repository with no path — is a plan and stays + something. `code: [mesh-controller]` — a repository with no path — is a plan and stays `designed`. """ for path in markdown_files(): diff --git a/00-META/glossary.md b/00-META/glossary.md index c8a5178..cba3af2 100644 --- a/00-META/glossary.md +++ b/00-META/glossary.md @@ -23,7 +23,7 @@ another — and a mesh you cannot name precisely is a mesh two people describe d control-plane/data-plane, and opaque here). - **mesh-controller** — the module that runs the controller. It **claims** the `the-controller` seat at mesh scope, which is what makes it singular. Replaces the module name **`mesh-control`**. - (The git repository is still named `mesh-control` until it is renamed on the forge; the module, + (The git repository has been renamed `mesh-control` -> `mesh-controller` on the forge; the module, container and image it produces are `mesh-controller`.) - **foundation** — the store and the broker, raised at genesis before any module system exists. Replaces **"substrate"** (a biology metaphor that landed for no one). The foundation is not a diff --git a/00-META/process/06-writing-a-module.md b/00-META/process/06-writing-a-module.md index 9edadce..b97d9c6 100644 --- a/00-META/process/06-writing-a-module.md +++ b/00-META/process/06-writing-a-module.md @@ -58,7 +58,7 @@ Three questions, answered from the machine: A **provisioner** is the exception: it reads a password file, so it mounts the `.secret` directly. - Every example module in `mesh-control` had this wrong and shipped: `own-secrets` pointing at a + Every example module in `mesh-controller` had this wrong and shipped: `own-secrets` pointing at a path *named* `.env`, mounted as `env-file`, holding a bare password. Docker reads that as a malformed line and the container starts **with no password set at all** — not a failure to start, a service running on the wrong credential. They parsed and they resolved. Two tests in diff --git a/00-META/process/07-feature-branches.md b/00-META/process/07-feature-branches.md index bb5f451..8fb9799 100644 --- a/00-META/process/07-feature-branches.md +++ b/00-META/process/07-feature-branches.md @@ -1,7 +1,7 @@ # Playbook 07 — Feature branches across repos **Trigger.** Work that changes code — in one code repo or in several at once (`mesh-sdk`, -`mesh-control`, `mesh-catalog`, `mesh-host`, `mesh-lab`, and `hq` when a decision rides along). +`mesh-controller`, `mesh-catalog`, `mesh-host`, `mesh-lab`, and `hq` when a decision rides along). **Who runs it.** Anyone who writes code, engineers and agents alike. Agents follow it exactly — it is the guard against the failure it was written for. diff --git a/00-META/repos.md b/00-META/repos.md index 315db01..a3517cd 100644 --- a/00-META/repos.md +++ b/00-META/repos.md @@ -21,15 +21,17 @@ and a forge address is an operational detail (see [`README`](../README.md)). ## What the mesh becomes [ADR 0019](../02-DECISIONS/0019-how-this-repository-works.md) records the repositories the -monorepo decomposes into. **`mesh-lab`, `mesh-host` and `mesh-control` exist so far** — the lab is built first -([ADR 0016](../02-DECISIONS/0016-the-lab.md)); the rest are the -target, not the present. +monorepo decomposes into. **`mesh-host`, `mesh-controller`, `mesh-catalog`, `mesh-lab`, `mesh-sdk` and `mesh-tools` exist +so far** — the lab was built first ([ADR 0016](../02-DECISIONS/0016-the-lab.md)). The tiered +decomposition below is the planned shape; the repositories built to date do not map onto it +one-for-one — `mesh-catalog`, `mesh-sdk` and `mesh-tools` exist where the table names +`mesh-foundation` and `mesh-surfaces`, and reconciling the two is itself still ahead. | Repository | Tier | Holds | |---|---|---| | `mesh-host` | 0 | **exists.** The node host — one statically linked binary, requiring nothing present ([ADR 0005](../02-DECISIONS/0005-the-node-host.md)) | | `mesh-foundation` | 1 | the four pinned services, as declarations | -| `mesh-control` | 2 | **exists.** The controller and its contexts — one of seven built ([ADR 0006](../02-DECISIONS/0006-the-substrate-and-the-control-plane.md)) | +| `mesh-controller` | 2 | **exists.** The controller and its contexts — one of seven built ([ADR 0006](../02-DECISIONS/0006-the-substrate-and-the-control-plane.md)) | | `mesh-surfaces` | 3 | tools, web, cli | | `mesh-sdk` | — | the stable spine modules build against — the tool-serving harness, the messaging/event framework, the contracts and core primitives. Holds nothing per-module and nothing volatile ([ADR 0039](../02-DECISIONS/0039-what-the-sdk-holds-and-refuses.md)). | | `mesh-lab` | — | **exists.** The lab — scenario lifecycle, networking, placement. Ships to nobody; runs on a workstation. | diff --git a/01-RESEARCH/006-mesh-from-scratch/00-overview.md b/01-RESEARCH/006-mesh-from-scratch/00-overview.md index 176736b..44baf1c 100644 --- a/01-RESEARCH/006-mesh-from-scratch/00-overview.md +++ b/01-RESEARCH/006-mesh-from-scratch/00-overview.md @@ -90,5 +90,5 @@ the catalogue where modules genuinely change together under one intent. The skel | One repository per tier, or per context? | Already open from ADR 0001 as "catalogue destination — one repository or many". The skeleton assumes per tier and does not settle it. | | ~~Does an unprivileged node earn a place in the inventory, or only a presence?~~ | **Answered 2026-08-25** by the operator: a node is a *managed machine inside the mesh*, not an unprivileged something — and a disconnected node is still a node, in a different situation. The question posed a class distinction; the answer is that there is none, and what varies is **state**. Recorded as [ADR 0004](../../02-DECISIONS/0004-a-node-and-how-it-joins.md). | | ~~Does absorbing overlay, filtering, packages, supervision and the container runtime make the host too large?~~ | **Answered 2026-08-25** — [`host-size.md`](host-size.md). Measured: the absorption is smaller than the machinery that already applies state, and eight of ten adapters already carry no dependency. The risk is not size but direction, and it is two modules wide. The claim survives with its scope corrected — the host carries one concern, *apply declared state on this machine*, of which the six are instances. Recorded as [ADR 0005](../../02-DECISIONS/0005-the-node-host.md), designed in [`05-the-node-host.md`](../../03-DESIGN/01-to-be/05-the-node-host.md). | -| ~~Four substrate services or five?~~ | **Answered conditionally**, which is the honest form — [`07-the-substrate.md`](../../03-DESIGN/01-to-be/07-the-substrate.md). The substrate is *what the control plane consumes and cannot grant itself*. The identity provider qualifies only if the control plane delegates authentication; if it authenticates natively it is an ordinary hosted service. The count follows from a decision not yet taken, and asserting four was asserting that decision. | +| ~~Four substrate services or five?~~ | **Answered conditionally**, which is the honest form — [`07-the-foundation.md`](../../03-DESIGN/01-to-be/07-the-foundation.md). The substrate is *what the control plane consumes and cannot grant itself*. The identity provider qualifies only if the control plane delegates authentication; if it authenticates natively it is an ordinary hosted service. The count follows from a decision not yet taken, and asserting four was asserting that decision. | | Does `feature` survive? | The skeleton splits it in two and argues the conflation is what makes the delivery pipeline hard to reason about. Unproven. | diff --git a/01-RESEARCH/011-the-module-graph/00-overview.md b/01-RESEARCH/011-the-module-graph/00-overview.md index b9a9ff0..6a77445 100644 --- a/01-RESEARCH/011-the-module-graph/00-overview.md +++ b/01-RESEARCH/011-the-module-graph/00-overview.md @@ -4,8 +4,8 @@ initiated: 2026-08-25 became: - 02-DECISIONS/0009-modules-and-the-graph.md - 02-DECISIONS/0008-a-context-owns-its-store.md - - 03-DESIGN/01-to-be/06-the-control-plane.md - - 03-DESIGN/01-to-be/07-the-substrate.md + - 03-DESIGN/01-to-be/06-the-controller.md + - 03-DESIGN/01-to-be/07-the-foundation.md touches: - 02-DECISIONS/0009-modules-and-the-graph.md - 02-DECISIONS/0009-modules-and-the-graph.md diff --git a/02-DECISIONS/0027-a-provision-names-what-the-consumer-is-coupled-to.md b/02-DECISIONS/0027-a-provision-names-what-the-consumer-is-coupled-to.md index 6e2bce4..61c9d50 100644 --- a/02-DECISIONS/0027-a-provision-names-what-the-consumer-is-coupled-to.md +++ b/02-DECISIONS/0027-a-provision-names-what-the-consumer-is-coupled-to.md @@ -104,6 +104,6 @@ Without that, this record is a convention, and a convention is what the previous ## References - [ADR 0009](0009-modules-and-the-graph.md) — provisions, and refusing on ambiguity -- [`03-DESIGN/01-to-be/07-the-substrate.md`](../03-DESIGN/01-to-be/07-the-substrate.md) — *the +- [`03-DESIGN/01-to-be/07-the-foundation.md`](../03-DESIGN/01-to-be/07-the-foundation.md) — *the provisioning model uses databases, roles and schemas as PostgreSQL means them*, which is this record's point made about the substrate before it was made about modules diff --git a/02-DECISIONS/0031-the-control-plane-authenticates-nobody.md b/02-DECISIONS/0031-the-control-plane-authenticates-nobody.md index 850bf76..ed6be7e 100644 --- a/02-DECISIONS/0031-the-control-plane-authenticates-nobody.md +++ b/02-DECISIONS/0031-the-control-plane-authenticates-nobody.md @@ -18,7 +18,7 @@ conditional, and said exactly why: |---|---|---| | identity provider | — | **conditional**: substrate only if the control plane delegates authentication, which is undecided | -[`07-the-substrate.md`](../03-DESIGN/01-to-be/07-the-substrate.md) carried it as an open question — +[`07-the-foundation.md`](../03-DESIGN/01-to-be/07-the-foundation.md) carried it as an open question — *whether identity is the fifth* — noting it followed from a decision nobody had taken. **The decision is taken: the control plane does not delegate authentication.** There is no mesh diff --git a/02-DECISIONS/0036-bootstrap-ends-at-a-usable-mesh.md b/02-DECISIONS/0036-bootstrap-ends-at-a-usable-mesh.md index 87d330d..0924818 100644 --- a/02-DECISIONS/0036-bootstrap-ends-at-a-usable-mesh.md +++ b/02-DECISIONS/0036-bootstrap-ends-at-a-usable-mesh.md @@ -12,7 +12,7 @@ extends: 02-DECISIONS/0035-one-implementation-several-surfaces.md ## Context Bootstrap currently ends when the control plane starts -([`07-the-substrate.md`](../03-DESIGN/01-to-be/07-the-substrate.md)). That is a mesh that runs and +([`07-the-foundation.md`](../03-DESIGN/01-to-be/07-the-foundation.md)). That is a mesh that runs and cannot yet be used by anybody who is not standing at the machine: the networked surfaces need an OAuth2 identity provider ([ADR 0035](0035-one-implementation-several-surfaces.md)), the provider is a module, and no module has been assigned. diff --git a/02-DECISIONS/0070-the-catalogue-owns-the-module-graph.md b/02-DECISIONS/0070-the-catalogue-owns-the-module-graph.md index f0fcc37..5c21753 100644 --- a/02-DECISIONS/0070-the-catalogue-owns-the-module-graph.md +++ b/02-DECISIONS/0070-the-catalogue-owns-the-module-graph.md @@ -16,7 +16,7 @@ claims, what each is made of — all of it lives inside the control plane becaus was first written, not because anything decided it belonged there. **The control plane's own test says it does not belong there.** -[`06-the-control-plane`](../03-DESIGN/01-to-be/06-the-control-plane.md) defines the tier as +[`06-the-control-plane`](../03-DESIGN/01-to-be/06-the-controller.md) defines the tier as *everything that needs to know about more than one node*, and states the corollary plainly: anything a single machine could answer alone is not the control plane's. What a module is, and what it needs, requires no knowledge of any node whatsoever. diff --git a/02-DECISIONS/0075-two-stores-and-which-provides-what.md b/02-DECISIONS/0075-two-stores-and-which-provides-what.md index e8dbcd2..07be4d1 100644 --- a/02-DECISIONS/0075-two-stores-and-which-provides-what.md +++ b/02-DECISIONS/0075-two-stores-and-which-provides-what.md @@ -1,6 +1,6 @@ --- topic: the tiers -status: proposed +status: accepted date: 2026-09-15 deciders: jochen reconstructed: false diff --git a/02-DECISIONS/0076-the-sdk-is-a-published-package.md b/02-DECISIONS/0076-the-sdk-is-a-published-package.md index 6038bdb..a1648a8 100644 --- a/02-DECISIONS/0076-the-sdk-is-a-published-package.md +++ b/02-DECISIONS/0076-the-sdk-is-a-published-package.md @@ -1,6 +1,6 @@ --- topic: building it -status: proposed +status: accepted date: 2026-09-16 deciders: jochen reconstructed: false diff --git a/02-DECISIONS/0077-the-controller-and-the-foundation.md b/02-DECISIONS/0077-the-controller-and-the-foundation.md new file mode 100644 index 0000000..1bdc5fd --- /dev/null +++ b/02-DECISIONS/0077-the-controller-and-the-foundation.md @@ -0,0 +1,61 @@ +--- +topic: the mesh +status: accepted +date: 2026-09-16 +deciders: jochen +reconstructed: false +extends: 0006-the-substrate-and-the-control-plane.md +--- + +# 77. The parts are named controller, foundation, node — not control plane, substrate, master + +## Context + +The words drifted. In conversation and in code the same thing was called *control plane*, +*controller*, *master*, and *hub*; the store-and-broker pair was called *substrate* and +*foundation*; a machine was a *node*, a *worker-node*, a *peer*, a *slave*. A mesh named +differently by two people is a mesh they describe differently, and the drift was worst on the +parts talked about most. + +Three of the terms carried wrong ideas. *Control plane* is borrowed from networking's +control-plane/data-plane split and means nothing here. *Master/slave* and *hub/peer* imply a +subordinate — but no node is: a node applies its own declaration and keeps running when the +control-node dies, so it is as much its own machine as any other. *Substrate* is a biology +metaphor that landed for no one. + +## Considered Options + +1. **Keep the inherited words.** Rejected: they are the source of the drift, and two of them + (control plane, substrate) are metaphors that teach the wrong shape to anyone reading them cold. +2. **master / slave, or hub / peer, for the nodes.** Rejected: both name a hierarchy the mesh does + not have. The control-node owns no other node; lose it and the rest keep running what they were + last told. +3. **controller / foundation / node + control-node.** Chosen. + +## Decision + +The component that decides what each node should be, holds the mesh's records, and tells nodes is +the **controller** — the module `mesh-controller`, which claims the mesh-scoped `the-controller` +seat. The store and broker raised at genesis are the **foundation**. Machines are **nodes**; +there are 0..n of them, and exactly one — the one running the controller — is the **control-node**. + +Retired: *control plane*, *substrate*, *master/slave*, *hub/peer*, *worker-node*. +[`00-META/glossary.md`](../00-META/glossary.md) is the authority, and a new name for an existing +thing lands there in the change that introduces it in code. + +## Consequences + +`mesh-control` became `mesh-controller` across the module, container, image, binary, `cmd/` dir and +the git repository; `substrate` became `foundation` in the embedded base bundles, the default +template and the example lock; the seat `the-control-plane` became `the-controller`. The 03-DESIGN +prose and 00-META follow the new words. + +What got harder: the records under `02-DECISIONS/` are immutable, so they keep the words they were +written with — this record included, whose own title names what it retires. A term retired here +still appears there, and the glossary is how to read it. The git repository on the forge was +renamed `mesh-control` → `mesh-controller`. + +## References + +- [`00-META/glossary.md`](../00-META/glossary.md) — one name per thing, and the words retired. +- The rename shipped across all six code repositories and hq (main). diff --git a/02-DECISIONS/0078-the-store-and-broker-are-modules.md b/02-DECISIONS/0078-the-store-and-broker-are-modules.md new file mode 100644 index 0000000..31e97ed --- /dev/null +++ b/02-DECISIONS/0078-the-store-and-broker-are-modules.md @@ -0,0 +1,63 @@ +--- +topic: the tiers +status: accepted +date: 2026-09-16 +deciders: jochen +reconstructed: false +extends: 0033-the-substrate-is-a-store-and-a-broker.md +--- + +# 78. The store and the broker are ordinary modules + +## Context + +[ADR 0033](0033-the-substrate-is-a-store-and-a-broker.md) settled that the foundation is a store +and a broker, raised at genesis; [ADR 0006](0006-the-substrate-and-the-control-plane.md) settled +that the controller cannot grant itself either, because it consumes them and is not running yet to +ask. Both were raised as bundle resources — plumbing, with no record in the mesh's module graph. + +That left two costs, named in [issue 051](../04-ISSUES/051-the-mesh-cannot-update-what-it-depends-on/00-report.md). +The foundation's own store and broker could not be upgraded — nothing owned them as modules. And a +mesh that wanted a database or a queue for its modules installed the `postgres`/`lavinmq` modules, +each of which raised a **second** server: a mesh ran two postgres and two brokers. + +## Considered Options + +1. **Leave them as bundle-only plumbing.** Rejected: they cannot be upgraded, and the second + server stays. The floor keeps a permanent specialty in it. +2. **The control-plane pivot verbatim — raise a temporary one, install the module, retire the + temporary** ([ADR 0067](0067-genesis-is-a-pivot.md)). Rejected for a *stateful* server: it means + a handover with real downtime, tearing down the store the controller is mid-read of. +3. **Adopt in place.** Chosen. + +## Decision + +The foundation's store and broker are **adopted in place** as the ordinary `postgres` and `lavinmq` +modules. Genesis still raises them first (nothing else can — ADR 0006), then each module declares a +container with the **same name, image and spec** the foundation raised, so the applier — which keys +on the container name and compares a spec digest — reconciles it rather than raising a second. The +credentials are the foundation's, made at genesis and carried in through `secret accept`, because +the mesh cannot invent a credential that already made the databases. The servers bind mesh-wide so +a consumer on any node can reach the one shared server. + +A mesh runs **one postgres and one lavinmq**, and each is upgradeable through a stated window: the +store's is a connection-pool reconnect; the broker's is the harder case of recreating the bus the +push travels over, so the mesh reconnects to the one that returns. + +## Consequences + +The twelve-module floor has no specialty left in it — the store and broker are moments in a +module's life, not a separate kind of thing. Two follow-ups are tracked: +[issue 054](../04-ISSUES/054-the-adopted-store-and-broker-are-open-before-the-filter/00-report.md) +(the adopted servers bind `0.0.0.0` before the packet filter is installed) and +[issue 055](../04-ISSUES/055-the-adopted-store-and-broker-may-be-reachable-on-one-node-only/00-report.md) +(whether a consumer on another node reaches them over the overlay). + +What got harder: a foundation upgrade recreates the very server the controller reads from, or the +bus the instruction to upgrade travels over — a window that a stateless module upgrade does not have. + +## References + +- [issue 051](../04-ISSUES/051-the-mesh-cannot-update-what-it-depends-on/00-report.md) — the gap this closes. +- [`03-DESIGN/01-to-be/07-the-foundation.md`](../03-DESIGN/01-to-be/07-the-foundation.md) — the amended design. +- Shipped across mesh-host, mesh-catalog and mesh-lab (main); proven 22/22 in the one-node lab. diff --git a/02-DECISIONS/README.md b/02-DECISIONS/README.md index bfbc670..38fb1d4 100644 --- a/02-DECISIONS/README.md +++ b/02-DECISIONS/README.md @@ -84,6 +84,7 @@ python3 00-META/checks/index.py fail if stale - **0001** — [The mesh brokers capabilities; nodes host; agents think](0001-mesh-brokers-nodes-host-agents-think.md) - **0002** — [Nodes communicate over a message broker, not over HTTP](0002-nodes-communicate-over-a-broker.md) - **0003** — [An agent is a persistent employee, not an instance of a pool](0003-agents-are-persistent-employees.md) +- **0077** — [The parts are named controller, foundation, node — not control plane, substrate, master](0077-the-controller-and-the-foundation.md) ### Its tiers, from the bottom up @@ -100,15 +101,13 @@ python3 00-META/checks/index.py fail if stale - **0036** — [Bootstrap ends at a usable mesh, and the first credential comes from a person](0036-bootstrap-ends-at-a-usable-mesh.md) - **0066** — [Public routing is name-agnostic, its names are resolved inside the mesh, and an internal authority can certify them](0066-public-routing-is-name-agnostic.md) - **0067** — [Genesis is a pivot: a temporary control plane installs the registry that makes it permanent](0067-genesis-is-a-pivot.md) -- **0068** — [The lab takes requests, one at a time, and runs each from its own copy](0068-the-lab-takes-requests.md) *(proposed)* -- **0069** — [A module is a repository and a path within it](0069-a-module-is-a-repository-and-a-path.md) - **0070** — [The catalogue owns the module graph, and genesis builds rather than carries](0070-the-catalogue-owns-the-module-graph.md) - **0071** — [Genesis clones from a mesh, and checks what it got](0071-where-genesis-gets-its-source.md) - **0072** — [Two graphs, and a build chain that orders itself](0072-two-graphs-and-the-build-chain.md) - **0073** — [The installer carries a builder, and the registry stays where it is](0073-the-installer-carries-a-builder.md) - **0074** — [The mesh defines a module protocol; an SDK is an implementation of it](0074-the-wire-is-specified-not-the-types.md) -- **0075** — [An artifact store is a provision; a package registry is a different one](0075-two-stores-and-which-provides-what.md) *(proposed)* -- **0076** — [The SDK is a published package, and the toolchain resolves it by version](0076-the-sdk-is-a-published-package.md) *(proposed)* +- **0075** — [An artifact store is a provision; a package registry is a different one](0075-two-stores-and-which-provides-what.md) +- **0078** — [The store and the broker are ordinary modules](0078-the-store-and-broker-are-modules.md) ### What runs on them, and how it gets there @@ -146,6 +145,9 @@ python3 00-META/checks/index.py fail if stale - **0016** — [The lab](0016-the-lab.md) - **0037** — [Where a module lives](0037-where-a-module-lives.md) *(proposed)* - **0039** — [What the SDK holds, and what it refuses](0039-what-the-sdk-holds-and-refuses.md) +- **0068** — [The lab takes requests, one at a time, and runs each from its own copy](0068-the-lab-takes-requests.md) *(proposed)* +- **0069** — [A module is a repository and a path within it](0069-a-module-is-a-repository-and-a-path.md) +- **0076** — [The SDK is a published package, and the toolchain resolves it by version](0076-the-sdk-is-a-published-package.md) ### How it is checked diff --git a/03-DESIGN/01-to-be/06-the-controller.md b/03-DESIGN/01-to-be/06-the-controller.md index 45ab924..28ea169 100644 --- a/03-DESIGN/01-to-be/06-the-controller.md +++ b/03-DESIGN/01-to-be/06-the-controller.md @@ -2,7 +2,7 @@ layer: to-be status: in-progress code: - - mesh-control + - mesh-controller updated: 2026-08-31 decisions: - 02-DECISIONS/0001-mesh-brokers-nodes-host-agents-think.md diff --git a/03-DESIGN/01-to-be/07-the-foundation.md b/03-DESIGN/01-to-be/07-the-foundation.md index f84d73d..2f15660 100644 --- a/03-DESIGN/01-to-be/07-the-foundation.md +++ b/03-DESIGN/01-to-be/07-the-foundation.md @@ -4,10 +4,15 @@ status: in-progress code: - mesh-host examples/foundation-first-node.lock - mesh-host internal/apply + - mesh-host internal/bootstrap/phase3.go + - mesh-catalog modules/postgres + - mesh-catalog modules/lavinmq - mesh-lab test/integration/mesh.test.ts (a bare machine becomes a mesh) -updated: 2026-08-31 +updated: 2026-09-16 decisions: - 02-DECISIONS/0004-a-node-and-how-it-joins.md + - 02-DECISIONS/0078-the-store-and-broker-are-modules.md + - 02-DECISIONS/0077-the-controller-and-the-foundation.md - 02-DECISIONS/0005-the-node-host.md - 02-DECISIONS/0006-the-substrate-and-the-control-plane.md - 02-DECISIONS/0007-connectivity.md diff --git a/03-DESIGN/01-to-be/08-connectivity.md b/03-DESIGN/01-to-be/08-connectivity.md index cc04256..4b3c116 100644 --- a/03-DESIGN/01-to-be/08-connectivity.md +++ b/03-DESIGN/01-to-be/08-connectivity.md @@ -2,9 +2,9 @@ layer: to-be status: in-progress code: - - mesh-control internal/catalogue/filtering.go - - mesh-control examples/route-proxy - - mesh-control internal/identity/authority.go + - mesh-controller internal/catalogue/filtering.go + - mesh-controller examples/route-proxy + - mesh-controller internal/identity/authority.go - mesh-host internal/identity/serving.go - mesh-host internal/apply (the service that reflects a rule set) updated: 2026-09-09 diff --git a/03-DESIGN/01-to-be/09-the-node-lifecycle.md b/03-DESIGN/01-to-be/09-the-node-lifecycle.md index 56df007..3918924 100644 --- a/03-DESIGN/01-to-be/09-the-node-lifecycle.md +++ b/03-DESIGN/01-to-be/09-the-node-lifecycle.md @@ -6,8 +6,8 @@ code: - mesh-host internal/link/enrol.go - mesh-host packaging/nox-mesh-host-resume.service - mesh-host packaging/nox-mesh-host-network.sh - - mesh-control internal/token - - mesh-control internal/inventory/nodes.go + - mesh-controller internal/token + - mesh-controller internal/inventory/nodes.go updated: 2026-08-31 decisions: - 02-DECISIONS/0004-a-node-and-how-it-joins.md @@ -223,7 +223,7 @@ The same path, with the mesh built in the middle of it. nox-mesh-host reconcile # 2 — the controller now exists, and issues the first token -mesh-control token issue +mesh-controller token issue # 3 — the machine joins the mesh it just raised nox-mesh-host enrol --token @@ -548,8 +548,8 @@ rather than left to be worked out. **A token is issued *for* a node record**, and that is where a re-enrolment is decided. ``` -mesh-control token issue --node workstation # this machine is that node again -mesh-control token issue --new # a machine the mesh has not seen +mesh-controller token issue --node workstation # this machine is that node again +mesh-controller token issue --new # a machine the mesh has not seen ``` The host does not need to know which it is. It presents a token and receives an identity; what @@ -629,7 +629,7 @@ keeps cataloguing. ### Where the enrolment token comes from -**`mesh-control token issue` prints it once**, to the person running it. Single-use, and it +**`mesh-controller token issue` prints it once**, to the person running it. Single-use, and it expires whether used or not ([ADR 0004](../../02-DECISIONS/0004-a-node-and-how-it-joins.md)). It is carried by hand — read off a screen, pasted into a terminal. That is the design rather than diff --git a/03-DESIGN/01-to-be/10-delivery.md b/03-DESIGN/01-to-be/10-delivery.md index 0a33b69..32b04d7 100644 --- a/03-DESIGN/01-to-be/10-delivery.md +++ b/03-DESIGN/01-to-be/10-delivery.md @@ -2,9 +2,9 @@ layer: to-be status: in-progress code: - - mesh-control internal/builder - - mesh-control cmd/mesh-control (build, build --behind, push, status) - - mesh-control internal/inventory/builds.go + - mesh-controller internal/builder + - mesh-controller cmd/mesh-controller (build, build --behind, push, status) + - mesh-controller internal/inventory/builds.go updated: 2026-08-31 decisions: - 02-DECISIONS/0010-delivery.md diff --git a/03-DESIGN/01-to-be/11-a-board.md b/03-DESIGN/01-to-be/11-a-board.md index fdb0dd2..2308d40 100644 --- a/03-DESIGN/01-to-be/11-a-board.md +++ b/03-DESIGN/01-to-be/11-a-board.md @@ -2,8 +2,8 @@ layer: to-be status: in-progress code: - - mesh-control cmd/mesh-control/board.go - - mesh-control cmd/mesh-control/readable.go + - mesh-controller cmd/mesh-controller/board.go + - mesh-controller cmd/mesh-controller/readable.go updated: 2026-08-31 decisions: - 02-DECISIONS/0008-a-context-owns-its-store.md diff --git a/03-DESIGN/01-to-be/12-a-module-repository.md b/03-DESIGN/01-to-be/12-a-module-repository.md index 6f7855e..d9da073 100644 --- a/03-DESIGN/01-to-be/12-a-module-repository.md +++ b/03-DESIGN/01-to-be/12-a-module-repository.md @@ -3,10 +3,10 @@ layer: to-be status: in-progress code: - mesh-catalog modules/builder - - mesh-control internal/builder - - mesh-control internal/catalogue/build.go - - mesh-control internal/inventory/secrets.go - - mesh-control cmd/mesh-builder + - mesh-controller internal/builder + - mesh-controller internal/catalogue/build.go + - mesh-controller internal/inventory/secrets.go + - mesh-controller cmd/mesh-builder updated: 2026-09-12 decisions: - 02-DECISIONS/0069-a-module-is-a-repository-and-a-path.md diff --git a/03-DESIGN/01-to-be/13-credentials-and-their-rotation.md b/03-DESIGN/01-to-be/13-credentials-and-their-rotation.md index a485adf..c2afcf1 100644 --- a/03-DESIGN/01-to-be/13-credentials-and-their-rotation.md +++ b/03-DESIGN/01-to-be/13-credentials-and-their-rotation.md @@ -2,9 +2,9 @@ layer: to-be status: in-progress code: - - mesh-control internal/inventory/secrets.go - - mesh-control cmd/mesh-control/rotate.go - - mesh-control examples/postgres-provisioner + - mesh-controller internal/inventory/secrets.go + - mesh-controller cmd/mesh-controller/rotate.go + - mesh-controller examples/postgres-provisioner updated: 2026-09-01 decisions: - 02-DECISIONS/0001-mesh-brokers-nodes-host-agents-think.md diff --git a/03-DESIGN/01-to-be/14-model-access.md b/03-DESIGN/01-to-be/14-model-access.md index bc4fa5e..5d0cf58 100644 --- a/03-DESIGN/01-to-be/14-model-access.md +++ b/03-DESIGN/01-to-be/14-model-access.md @@ -2,8 +2,8 @@ layer: to-be status: in-progress code: - - mesh-control internal/licences - - mesh-control cmd/mesh-control/licence.go + - mesh-controller internal/licences + - mesh-controller cmd/mesh-controller/licence.go updated: 2026-09-05 decisions: - 02-DECISIONS/0024-model-access-is-a-provision.md diff --git a/03-DESIGN/01-to-be/15-the-agent-session.md b/03-DESIGN/01-to-be/15-the-agent-session.md index bf42494..b1e80ab 100644 --- a/03-DESIGN/01-to-be/15-the-agent-session.md +++ b/03-DESIGN/01-to-be/15-the-agent-session.md @@ -1,7 +1,7 @@ --- layer: to-be status: designed -code: [mesh-control, mesh-host] +code: [mesh-controller, mesh-host] updated: 2026-08-31 decisions: - 02-DECISIONS/0004-a-node-and-how-it-joins.md diff --git a/03-DESIGN/01-to-be/18-building-a-module.md b/03-DESIGN/01-to-be/18-building-a-module.md index f6fe5dc..1bae04a 100644 --- a/03-DESIGN/01-to-be/18-building-a-module.md +++ b/03-DESIGN/01-to-be/18-building-a-module.md @@ -2,8 +2,8 @@ layer: to-be status: proposed code: - - mesh-control cmd/mesh-builder - - mesh-control internal/builder + - mesh-controller cmd/mesh-builder + - mesh-controller internal/builder - mesh-catalog modules/builder updated: 2026-09-15 decisions: diff --git a/03-DESIGN/01-to-be/19-the-module-protocol.md b/03-DESIGN/01-to-be/19-the-module-protocol.md index f63c2d9..09b0731 100644 --- a/03-DESIGN/01-to-be/19-the-module-protocol.md +++ b/03-DESIGN/01-to-be/19-the-module-protocol.md @@ -4,7 +4,7 @@ status: proposed code: - mesh-sdk src - mesh-tools src/broker-amqp.ts - - mesh-control internal/link + - mesh-controller internal/link updated: 2026-09-15 decisions: - 02-DECISIONS/0074-the-wire-is-specified-not-the-types.md diff --git a/03-DESIGN/01-to-be/20-writing-a-module.md b/03-DESIGN/01-to-be/20-writing-a-module.md index ccc667f..55a17d2 100644 --- a/03-DESIGN/01-to-be/20-writing-a-module.md +++ b/03-DESIGN/01-to-be/20-writing-a-module.md @@ -3,7 +3,7 @@ layer: to-be status: proposed code: - mesh-catalog modules/showcase - - mesh-control internal/builder + - mesh-controller internal/builder - mesh-sdk src updated: 2026-09-15 decisions: diff --git a/03-DESIGN/01-to-be/21-the-installation-in-full.md b/03-DESIGN/01-to-be/21-the-installation-in-full.md index d705f29..c4889e2 100644 --- a/03-DESIGN/01-to-be/21-the-installation-in-full.md +++ b/03-DESIGN/01-to-be/21-the-installation-in-full.md @@ -131,7 +131,7 @@ two. |---|---|---|---| | 1 | `postgres` | `postgres-database` | **the controller's own records and every module's.** One server, not two | | 2 | `lavinmq` | `amqp` | the broker every node dials, and what modules are granted vhosts on | -| 3 | `mesh-control` | *claims* `the-controller` | decides what runs where | +| 3 | `mesh-controller` | *claims* `the-controller` | decides what runs where | | 4 | `distribution` | `artifact-store` | what the mesh built, pinned by digest — the module is the software (Distribution), the provision is the job | | 5 | `builder` | — | turns source into artifacts | | 6 | `mesh-tools` | build inputs | the base everything with code compiles against. **Runs nowhere** | diff --git a/04-ISSUES/009-a-digest-pinned-image-cannot-be-placed-in-the-lab/00-report.md b/04-ISSUES/009-a-digest-pinned-image-cannot-be-placed-in-the-lab/00-report.md index b90a554..f1a5e40 100644 --- a/04-ISSUES/009-a-digest-pinned-image-cannot-be-placed-in-the-lab/00-report.md +++ b/04-ISSUES/009-a-digest-pinned-image-cannot-be-placed-in-the-lab/00-report.md @@ -60,7 +60,7 @@ Everything else placed in the same sealed machine works, and was verified there: ## Why it matters more than one shape The container shape is the substrate. Every step of raising a mesh past the container runtime is -a container ([`07-the-substrate.md`](../../03-DESIGN/01-to-be/07-the-substrate.md)), so the +a container ([`07-the-foundation.md`](../../03-DESIGN/01-to-be/07-the-foundation.md)), so the bootstrap cannot be tested end-to-end until this is resolved — which is the thing the lab exists for. diff --git a/04-ISSUES/051-the-mesh-cannot-update-what-it-depends-on/00-report.md b/04-ISSUES/051-the-mesh-cannot-update-what-it-depends-on/00-report.md index 5897611..2f755c8 100644 --- a/04-ISSUES/051-the-mesh-cannot-update-what-it-depends-on/00-report.md +++ b/04-ISSUES/051-the-mesh-cannot-update-what-it-depends-on/00-report.md @@ -3,7 +3,7 @@ status: fixed opened: 2026-09-14 located-in: [mesh-host, mesh-catalog] fixed-by: mesh-host 56124c3; mesh-catalog 5e4dc37; mesh-lab 440e265 -amended-design: +amended-design: 03-DESIGN/01-to-be/07-the-foundation.md --- # 051 — The mesh can update everything except what it depends on -- 2.54.0