The seats as they run, and to-be 26 implemented #120

Merged
jschoubben merged 1 commits from design/26-the-seats-implemented into main 2026-09-26 12:50:02 +00:00
3 changed files with 93 additions and 1 deletions
+91
View File
@@ -0,0 +1,91 @@
---
layer: as-is
status: implemented
code: [mesh-controller, mesh-catalog]
updated: 2026-09-26
decisions:
- 02-DECISIONS/0109-a-package-registry-seat-is-one-per-ecosystem.md
- 02-DECISIONS/0110-a-seat-is-a-module-assignment-from-a-closed-set.md
- 02-DECISIONS/0111-a-build-source-is-on-the-git-seat-or-external.md
---
# The seats, as they run
Written from the controller's code and the catalogue's manifests on their main branches. This is
the second piece of the new shape to exist, after [the lab](11-the-lab.md), and the first that the
predecessor has no equivalent of: there, any well-formed name became a seat by being claimed.
## The set is closed, and it lives in the controller
Fourteen seats are defined in the controller — seven at mesh scope, seven at node scope. Each entry
carries a name, the scope at which there may be only one holder, the provision its holder answers
for (or none), and the record that made it a seat. A person reads the set to learn what a mesh can
have; nothing else can add to it.
Five seats deliver a provision: the mesh's store delivers the relational database, the mesh's broker
the message transport, the artifact-store seat the registry, and two more the package registry for
one ecosystem and the git service. The remaining nine — the controller and catalogue seats, and the
node-scope ones for the build machine, the DNS port, the packet filter, intrusion prevention, the
private network, the resolver's configuration and the showcase — mark a role without answering for
anything a consumer requires.
## A claim is checked against the set
Parsing a manifest refuses three things, in this order: a claim that is not a usable name or not at
node, site or mesh scope; then a claim naming a seat the mesh does not define, answered with the
whole set so the writer can see what was available; then a claim at the wrong scope for that seat.
A malformed claim is refused once, for being malformed, and not a second time for being unknown.
One further refusal ties a seat to what it promises: claiming a seat that delivers a provision is
refused unless the claiming module actually provides that provision, at the seat's scope. A seat
cannot be held by something that could not answer for it.
## A seat is held by an assignment, and nothing else is recorded
The holder is a module assignment — a node and a module together. There is no separate record of
holders: what the mesh knows about one is what it already knows about that assignment. The pair is
also what tells a seat's holder apart from another module providing the same thing on another node.
## Where a seat changes resolution, and where it does not
Resolution runs in two passes. The first learns only what each node offers and takes requirements
on trust; no declaration is ever built from it. In the second:
- **nothing provides the wanted provision** — refused, naming what would answer it ("assign X to a
node");
- **one provider** — taken, unless a pin names a different node, which is refused rather than
silently overruled;
- **several providers** — a pin wins; failing that, the holder of the seat that delivers the
provision answers; failing that, refused with the candidates listed.
So a seat decides **which** of several providers answers. It does not make a requirement optional:
before the seat is held, a requirement for what it delivers is refused like any other unanswerable
one. That is the standing condition [issue 121](../../04-ISSUES/121-builders-real-package-registry-grant-deadlocks-genesis/00-report.md)
records, where the module that builds the forge's image requires a registry only the forge provides.
## The mesh can be asked
A `seats` command prints every seat with its scope, what it delivers and who holds it, in reading
order, and the same as JSON. An unheld seat prints as an answer — this mesh has no such thing — not
as a fault. Claims held that are **outside** the set are listed separately rather than hidden, so a
mesh carrying one from before the set existed says so.
## A build source may name the git seat
A module's repository is either a URL, recorded and cloned exactly as given, or a path on the forge
holding the git seat, recorded as that path plus the seat. The clone URL is composed from wherever
the holder runs at the moment of building, so the build machine is never told an address that could
go stale. Before this, a self-hosted forge's scheme, host and port were written into every module
built from it, and moving the forge made every record stale at once — noticed when a rebuild failed
to clone.
The schema column added for this defaults to empty rather than null, because "not on a seat" is a
real answer, so every row recorded before the change keeps exactly the meaning it had.
## Where this differs from the design
**Capacity is not implemented.** The design's vocabulary has a seat with a capacity, and a
higher-capacity seat is a bench several holders share. Neither exists in the code: a seat as it runs
is one role with one holder at its scope, and nothing expresses a bench. Every seat in the set today
is exclusive, so nothing has yet needed it — but a design that says capacity and an implementation
that has none is a disagreement worth reading here rather than discovering in the type.
+1
View File
@@ -20,6 +20,7 @@ Where the two disagree, the implementation wins and the disagreement is stated.
| [`09-interfaces-and-observability.md`](09-interfaces-and-observability.md) | How the mesh is reached and watched — tools, board, proxy, health, thoughts | | [`09-interfaces-and-observability.md`](09-interfaces-and-observability.md) | How the mesh is reached and watched — tools, board, proxy, health, thoughts |
| [`10-module-catalogue.md`](10-module-catalogue.md) | The catalogue's shape, and what its shape says | | [`10-module-catalogue.md`](10-module-catalogue.md) | The catalogue's shape, and what its shape says |
| [`11-the-lab.md`](11-the-lab.md) | The lab — the first piece of the new shape that exists, and what it does not yet do | | [`11-the-lab.md`](11-the-lab.md) | The lab — the first piece of the new shape that exists, and what it does not yet do |
| [`12-the-seats.md`](12-the-seats.md) | The seats the mesh defines, who holds one, and where a seat changes resolution |
## What these documents are not ## What these documents are not
+1 -1
View File
@@ -1,6 +1,6 @@
--- ---
layer: to-be layer: to-be
status: in-progress status: implemented
code: code:
- mesh-controller internal/catalogue/seats.go - mesh-controller internal/catalogue/seats.go
- mesh-controller internal/catalogue/resolve.go - mesh-controller internal/catalogue/resolve.go