diff --git a/03-DESIGN/00-as-is/12-the-seats.md b/03-DESIGN/00-as-is/12-the-seats.md new file mode 100644 index 0000000..025b6b6 --- /dev/null +++ b/03-DESIGN/00-as-is/12-the-seats.md @@ -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. diff --git a/03-DESIGN/00-as-is/README.md b/03-DESIGN/00-as-is/README.md index bfe18f9..041652a 100644 --- a/03-DESIGN/00-as-is/README.md +++ b/03-DESIGN/00-as-is/README.md @@ -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 diff --git a/03-DESIGN/01-to-be/26-the-seats.md b/03-DESIGN/01-to-be/26-the-seats.md index facbfae..65dc1b9 100644 --- a/03-DESIGN/01-to-be/26-the-seats.md +++ b/03-DESIGN/01-to-be/26-the-seats.md @@ -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