Merge pull request 'The seats as they run, and to-be 26 implemented' (#120) from design/26-the-seats-implemented into main
This commit was merged in pull request #120.
This commit is contained in:
@@ -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.
|
||||
@@ -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 |
|
||||
| [`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 |
|
||||
| [`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
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
layer: to-be
|
||||
status: in-progress
|
||||
status: implemented
|
||||
code:
|
||||
- mesh-controller internal/catalogue/seats.go
|
||||
- mesh-controller internal/catalogue/resolve.go
|
||||
|
||||
Reference in New Issue
Block a user