Define the control plane, which was used 79 times and defined nowhere
Nineteen files, seventy-nine mentions, no definition. That is how-we-build §5 failing on this repository's own vocabulary — ubiquitous language is checked, not assumed. The definition, and it is not arbitrary: the control plane is everything that needs to know about MORE THAN ONE NODE. It follows from ADR 0037, which has the host applying rather than deciding precisely because deciding needs knowledge the machine does not have. So the line falls exactly there — writing a file is the host's, choosing which nodes run the store is the control plane's, and anything a single machine could answer alone does not belong here at all. That last consequence is worth having: putting a single-machine concern in tier 2 is a mistake the tier rule will NOT catch, because the dependency direction stays correct. Also states what it is not — not the thing that changes machines, not a surface, not the substrate, and not privileged on a node beyond what the declaration vocabulary allows. And the property that makes tier 2 unlike the others: it is itself a consumer, with the same requirements as any module, which is the circularity the bundle exists to resolve rather than hide. Scoped deliberately: this defines the term and does not design the contexts inside it. Ten is the skeleton's claim rather than a settled list, and research 006 still asks whether the record belongs here or in the substrate.
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
---
|
||||
layer: to-be
|
||||
status: designed
|
||||
code: []
|
||||
updated: 2026-08-26
|
||||
decisions:
|
||||
- 02-DECISIONS/0037-the-host-applies-it-does-not-decide.md
|
||||
- 02-DECISIONS/0030-the-repository-structure.md
|
||||
- 02-DECISIONS/0015-mesh-brokers-nodes-host-agents-think.md
|
||||
---
|
||||
|
||||
# The control plane
|
||||
|
||||
Tier 2. The term appears seventy-nine times across this repository and was defined nowhere,
|
||||
which is `how-we-build` §5 failing on this repository's own vocabulary.
|
||||
|
||||
This document defines it. It does **not** design the contexts inside it; those are open in
|
||||
[research 006](../../01-RESEARCH/006-mesh-from-scratch/00-overview.md).
|
||||
|
||||
## The definition
|
||||
|
||||
> **The control plane is everything that needs to know about more than one node.**
|
||||
|
||||
That is the whole test, and it is not arbitrary — it follows from
|
||||
[ADR 0037](../../02-DECISIONS/0037-the-host-applies-it-does-not-decide.md). The host applies and
|
||||
does not decide *because deciding needs knowledge the machine does not have*. So the line falls
|
||||
exactly there:
|
||||
|
||||
| Question | Whose |
|
||||
|---|---|
|
||||
| write this file, with this content, with this mode | the **host** — one machine |
|
||||
| which nodes should run the store | the **control plane** — needs every node |
|
||||
| is this unit running | the **host** — one machine |
|
||||
| which peers belong in this node's overlay | the **control plane** — needs every node |
|
||||
| what does this machine have installed | the **host** reports; the control plane **records** |
|
||||
| has this node been unreachable for a week | the **control plane** — nobody else is watching |
|
||||
|
||||
A useful consequence: **anything a single machine could answer alone is not the control
|
||||
plane's.** If it needs no second node, putting it here is a mistake, and the tier rule will not
|
||||
catch it because the dependency direction is still correct.
|
||||
|
||||
## What is inside it
|
||||
|
||||
Ten contexts and one interface, from the skeleton
|
||||
([research 006](../../01-RESEARCH/006-mesh-from-scratch/skeleton.md)):
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **record** | the event log every other context integrates through |
|
||||
| **inventory** | nodes, modules, assignments, versions |
|
||||
| **config** | settings, secrets, and deriving them onto nodes |
|
||||
| **connectivity** | overlay, resolution, exposure, filtering, certificates |
|
||||
| **provisioning** | resource grants between modules |
|
||||
| **delivery** | source to artifact to node |
|
||||
| **observability** | health, logs, metrics, alerts |
|
||||
| **identity** | agents, humans, services, authorisation |
|
||||
| **work** | tasks, workflows, runs |
|
||||
| **knowledge** | memory, documents, retrieval |
|
||||
| **api** | the one interface every surface speaks to |
|
||||
|
||||
**These are contexts, not services.** They are separate in the sense that matters — each owns
|
||||
its own store, and they integrate through the record rather than by reading one another
|
||||
([`how-we-build`](../../00-META/how-we-build.md) §4). They are not separate deployables, and
|
||||
[research 011](../../01-RESEARCH/011-the-module-graph/00-overview.md) records why that
|
||||
constraint is load-bearing: a single surface can compose them only while there is one interface
|
||||
in front of them.
|
||||
|
||||
## What it is not
|
||||
|
||||
- **Not the thing that changes machines.** It decides; the host applies. It never reaches into a
|
||||
node except through the host.
|
||||
- **Not a surface.** Tier 3 is how people and agents reach it. It has one interface; the
|
||||
surfaces are what speak to that interface.
|
||||
- **Not the substrate.** It *runs on* tier 1 — a store, a broker, an object store, a registry —
|
||||
and cannot start without them, which is what makes them a lower tier.
|
||||
- **Not privileged on a node.** It has no more access to a machine than the declaration
|
||||
vocabulary allows ([ADR 0039](../../02-DECISIONS/0039-the-link-is-the-security-boundary.md)).
|
||||
|
||||
## It is also a consumer
|
||||
|
||||
The property that makes tier 2 unlike the others: **the control plane has requirements of its
|
||||
own.** It needs a database, a broker, and somewhere to keep artifacts — the same things any
|
||||
module needs, granted the same way.
|
||||
|
||||
That is the circularity the tiers exist to resolve rather than hide: the control plane cannot
|
||||
provision its own database, because it is not running yet. So its store and its virtual host are
|
||||
raised from the bundle the host carries, before there is a control plane to ask
|
||||
([ADR 0038](../../02-DECISIONS/0038-a-node-joins-by-linking-first.md),
|
||||
[research 011](../../01-RESEARCH/011-the-module-graph/worked-provider.md)).
|
||||
|
||||
## Where it runs
|
||||
|
||||
**On nodes, like anything else.** It is not a place outside the mesh; it is modules the mesh
|
||||
hosts, assigned to nodes by the same mechanism as everything else.
|
||||
|
||||
Which raises a question this document does not answer: **how many nodes run it, and what happens
|
||||
when the one running it is down.** The broker is one per mesh by decision; whether the control
|
||||
plane is, and what a node does while it cannot reach it, is
|
||||
[ADR 0036](../../02-DECISIONS/0036-a-node-is-a-managed-machine.md)'s ordinary situation seen from
|
||||
the other end — and it is not designed.
|
||||
|
||||
## Open
|
||||
|
||||
- **The contexts themselves.** Ten is the skeleton's claim, not a settled list. Research 006
|
||||
asks whether the record belongs here or in the substrate, and whether identity is a context or
|
||||
a substrate service.
|
||||
- **How far it may be split.** One deployable today. Splitting a context out costs the single
|
||||
interface a surface depends on
|
||||
([research 011](../../01-RESEARCH/011-the-module-graph/00-overview.md)).
|
||||
- **How many run, and what a node does without one.** Above.
|
||||
- **What the interface is.** One interface is stated; its shape, and whether it is request,
|
||||
subscription or both, is not
|
||||
([research 011](../../01-RESEARCH/011-the-module-graph/worked-provider.md)).
|
||||
@@ -15,6 +15,7 @@ document is written and this one's status becomes `implemented`.
|
||||
| [`03-scenario-lifecycle.md`](03-scenario-lifecycle.md) | What happens to a scenario — raise, snapshot, restore, move, destroy | [ADR 0032](../../02-DECISIONS/0032-a-scenario-is-an-isolated-address-space.md) |
|
||||
| [`04-lab-installation.md`](04-lab-installation.md) | Getting the lab onto a clean machine, and why it verifies capability rather than installation | [ADR 0008](../../02-DECISIONS/0008-a-failed-step-fails-the-job.md) |
|
||||
| [`05-the-node-host.md`](05-the-node-host.md) | Tier 0 — the one thing installed by hand, and the only thing that changes a machine | [ADR 0037](../../02-DECISIONS/0037-the-host-applies-it-does-not-decide.md) |
|
||||
| [`06-the-control-plane.md`](06-the-control-plane.md) | Tier 2 — what the term means, and the test for what belongs in it | [ADR 0037](../../02-DECISIONS/0037-the-host-applies-it-does-not-decide.md) |
|
||||
|
||||
## Not yet written
|
||||
|
||||
|
||||
Reference in New Issue
Block a user