128 lines
6.4 KiB
Markdown
128 lines
6.4 KiB
Markdown
---
|
|
layer: to-be
|
|
status: in-progress
|
|
code:
|
|
- mesh-controller internal/catalogue/seats.go
|
|
- mesh-controller internal/catalogue/resolve.go
|
|
- mesh-controller cmd/mesh-controller/seats.go
|
|
- mesh-controller cmd/mesh-controller/source.go
|
|
- mesh-controller internal/inventory/migrations/0032-a-source-may-live-on-a-seat.sql
|
|
- mesh-catalog modules/gitea/module.json
|
|
updated: 2026-09-25
|
|
decisions:
|
|
- 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
|
|
- 02-DECISIONS/0109-a-package-registry-seat-is-one-per-ecosystem.md
|
|
---
|
|
|
|
# 26 — The seats
|
|
|
|
**What a mesh can have one of, and who fills each.** A seat is a named role at a scope, taken by a
|
|
module assignment. The mesh defines which seats exist. Occupying one may deliver a provision, and the
|
|
list of seats with their holders is the quickest answer to "what is in this mesh".
|
|
|
|
## What a seat is
|
|
|
|
A seat has four properties, fixed by the mesh rather than by any module:
|
|
|
|
| property | is |
|
|
|---|---|
|
|
| name | what a manifest claims, and what a person reads in the list |
|
|
| scope | node, site or mesh: where there may be only one holder |
|
|
| delivers | the provision its holder answers for, or nothing |
|
|
| decision | the record that made it a seat |
|
|
|
|
**A module assignment holds a seat by claiming it.** The claim is the manifest's `claims`, and it is
|
|
satisfied by assigning the module somewhere. The seat is not a second record beside the assignment.
|
|
It points at the assignment, and everything the mesh knows about the holder is what it knows about
|
|
that assignment: the node, the node's settings for the module, and what the module serves.
|
|
|
|
**The set is closed.** A claim naming a seat the mesh does not define is refused, and so is a claim at
|
|
the wrong scope. Adding a seat is a decision, recorded, for the reason every addition to the host's
|
|
vocabulary is one: the set is what a person reads to learn what a mesh can have, and an entry nobody
|
|
argued for is an entry nobody can explain.
|
|
|
|
## The set
|
|
|
|
| seat | scope | delivers | typically held by |
|
|
|---|---|---|---|
|
|
| `mesh-controller` | mesh | — | the controller |
|
|
| `mesh-store` | mesh | `postgres-database` | the store |
|
|
| `mesh-broker` | mesh | `amqp` | the broker |
|
|
| `the-artifact-store` | mesh | `artifact-store` | the artifact registry |
|
|
| `the-catalogue` | mesh | — | the catalogue |
|
|
| `npm-package-registry` | mesh | `npm-package-registry` | the forge |
|
|
| `git` | mesh | `git` | the forge |
|
|
| `the-build-machine` | node | — | a builder |
|
|
| `the-dns-port` | node | — | the local resolver |
|
|
| `the-intrusion-prevention` | node | — | an intrusion-prevention service |
|
|
| `the-packet-filter` | node | — | the packet filter |
|
|
| `the-private-network` | node | — | the private network the mesh runs over |
|
|
| `the-resolver-configuration` | node | — | whichever of the alternative resolver configurations is chosen |
|
|
| `the-showcase` | node | — | the showcase module |
|
|
|
|
The control plane holds this set in code, and a test asserts both its size and that every entry names
|
|
the record that made it a seat. This document follows the code, not the reverse. If the two disagree,
|
|
the test has been changed without this table, and the table is what is wrong.
|
|
|
|
## A seat that delivers a provision
|
|
|
|
A seat that delivers a provision may only be held by a module that provides it, at the seat's scope.
|
|
A mesh seat delivers a mesh-scoped provision.
|
|
|
|
**Its holder answers for that provision.** When a requirement for it has more than one provider in the
|
|
mesh, the control plane takes, in order:
|
|
|
|
1. the provider the consumer's node was pinned to, because a consumer coupled to one provider's
|
|
contents has said so ([23 — Choosing a provider](23-choosing-a-provider.md));
|
|
2. the holder of the seat;
|
|
3. the only provider, when there is one;
|
|
4. otherwise nothing, and the requirement is refused with the candidates named.
|
|
|
|
So a second provider can run beside the holder and harm nothing. The forge holds
|
|
`npm-package-registry`. An npm proxy may provide the same provision on another machine, and a module
|
|
requiring an npm registry is still served by the forge, without anybody pinning it. Moving the role
|
|
to the proxy is moving the seat: unassign the claim from one, assign it to the other, and every
|
|
consumer follows.
|
|
|
|
**What a consumer receives is a grant**, the same as for any provision: where the provider answers,
|
|
what it serves, and a credential where one is minted. A consumer never reads the seat directly. The
|
|
one exception is the control plane itself, which reaches the store and the broker through a narrow
|
|
seat placeholder because it made them before any module existed and cannot be their consumer.
|
|
|
|
## A seat that delivers nothing
|
|
|
|
Most node seats deliver nothing. They say which module is this machine's packet filter, or which of
|
|
two alternative resolver configurations it runs, and a second holder is refused. That is the whole of
|
|
their job, and it is a real one: it is the mesh saying what a machine is, in words a person can read.
|
|
|
|
## The overview
|
|
|
|
The control plane lists every seat in the set with its scope, what it delivers, and each holder as a
|
|
node and a module. A seat nobody holds is listed as unheld. That is an answer, "this mesh has no
|
|
forge", and not a fault.
|
|
|
|
Holdings are derived from assignments whenever they are asked for, never stored. The list is always
|
|
what the mesh is running, because it is computed from the same thing that decides what the mesh runs.
|
|
|
|
## The git seat, and where a build comes from
|
|
|
|
A module is built from a repository, a path and a ref. The repository is one of two things, and the
|
|
mesh records which:
|
|
|
|
| form | means | recorded as |
|
|
|---|---|---|
|
|
| on the `git` seat | a repository on the forge that holds the seat | its path on the forge, and the seat |
|
|
| external | a repository anywhere else, a public forge for instance | its URL, exactly as given |
|
|
|
|
For a repository on the seat, the control plane composes the clone URL at the moment of building,
|
|
from where the holder runs and the scheme and port it serves for `git`. The recorded source never
|
|
contains an address, so moving the forge changes nothing that was recorded. The build machine is not
|
|
told the difference: it receives a URL either way.
|
|
|
|
With the seat unheld, a build from the seat is refused and says why. External builds carry on.
|
|
|
|
**Not yet designed:** a credential for cloning a private repository. The mesh's own repositories are
|
|
public. The natural place for a clone credential is the `git` provision's grant, and that is a
|
|
decision still to take.
|