Glossary, the mesh-controller/foundation vocabulary, ADR 0076, Phase 3 closed #43

Merged
jschoubben merged 32 commits from issue/047-the-other-half into main 2026-09-16 21:25:51 +00:00
2 changed files with 67 additions and 0 deletions
Showing only changes of commit 87f464cc5f - Show all commits
@@ -120,3 +120,59 @@ puts the shipped unit on the machine.
**Nothing asserts a mesh was installed this way.** A claim that a machine was brought up by this
procedure cannot be contradicted by anything afterwards.
## What a finished mesh holds
**Twelve, and after the pivot none of them is a specialty.** Every row is a module the mesh built,
holds a version of, and can upgrade — which is the whole claim, and is not true today for the first
two.
| # | module | provides | note |
|---|---|---|---|
| 1 | `postgres` | `postgres-database` | **the control plane'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-control-plane` | decides what runs where |
| 4 | `registry` | `artifact-store` | what the mesh built, pinned by digest |
| 5 | `builder` | — | turns source into artifacts |
| 6 | `mesh-tools` | build inputs | the base everything with code compiles against. **Runs nowhere** |
| 7 | `mesh-catalog` | the module graph | what is held, what a change reaches, what must be rebuilt |
| 8 | `networking` | `private-network`, naming | requirements only — assigning it brings `mesh-wireguard` and `mesh-names` |
| 9 | `dnsmasq` + one of `resolved-split-dns` / `resolv-conf` | `wildcard-resolution` | names that actually resolve, on top of `mesh-resolver`'s data |
| 10 | `step-ca` | `acme-ca` | certificates for `.internal` |
| 11 | `firewall` | *claims* `the-packet-filter` | rules generated from what modules declared |
| 12 | `gitea` | `package-registry` | where a module's dependencies come from ([ADR 0014](../../02-DECISIONS/0014-no-npm-workspace.md)), and the git host |
### Why it is twelve and not thirteen
**The substrate's store and the `postgres` module are the same module.** They were two rows while the
substrate was a different *kind* of thing: a store raised from a bundle cannot provide
`postgres-database`, so anything wanting a database needed a second server. That is visible on any
mesh built today — `mesh-store` and `postgres`, two containers, **the same image**.
The naming rule settles which name survives
([ADR 0040](../../02-DECISIONS/0040-what-a-module-is.md)):
> Where the consumer **speaks a protocol** — a database's wire protocol and query dialect — the
> interface *is* the protocol. **"database" is not a capability; the protocol is.** Never false
> genericity: a name must not promise a swap the contract cannot deliver.
So there is no `store` module. The control plane is coupled to postgres — its own queries use
`distinct on` and `on conflict`, which are not portable — and calling it `store` would advertise a
swap that would fail the first time somebody tried it.
**The same applies to the broker**, with a different outcome: `amqp` *is* a protocol and more than
one implementation speaks it, so `amqp` is a legitimate provision and `lavinmq` is one provider of
it. The substrate's broker and the `lavinmq` module collapse the same way.
### What this costs, and it is the last specialty
Adopting the store and the broker as modules is [issue 051](../../04-ISSUES/051-the-mesh-cannot-update-what-it-depends-on/00-report.md),
and it is the only part of this that has not been designed. The two hard parts:
- **upgrading a store the control plane is reading from** — a rollout where the thing being replaced
is the thing holding the record of the rollout
- **upgrading a broker over the broker** — the instruction arrives on what it replaces, so the
machine must finish without being able to report progress
Both are operations with windows, and a machine rebooting inside one is an operator's problem during
an operation rather than a reason not to do it.
@@ -51,6 +51,17 @@ rather than a *kind*: how a mesh starts, not what it permanently is.
duplication as a side effect, and the control plane already reaches its three contexts through
three separate credentials — which is the shape of a consumer, not an owner.
**And the module it becomes is `postgres`, not `store`.** The naming rule settles it
([ADR 0040](../../02-DECISIONS/0040-what-a-module-is.md)): where a consumer speaks a protocol, the
interface *is* the protocol, and *"database" is not a capability*. The control plane's own queries
use `distinct on` and `on conflict`, so the coupling is to postgres and a `store` module would
promise a swap that fails the first time anybody tries it. The broker collapses the same way with a
different outcome — `amqp` **is** a protocol that several implementations speak, so `amqp` is a
legitimate provision and `lavinmq` is one provider of it.
So adoption is not only an upgrade path. It is two rows of a mesh's module list becoming one,
twice.
## What makes this harder than it looks
**The recursion is real, not incidental.** The control plane learns what modules exist by reading