Reconcile: adopt initialization's consolidated HQ as canonical, re-home this session's new work #24
@@ -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