From e4f80cc3ce8cf17b611bde955092d3a5c2ff0ff7 Mon Sep 17 00:00:00 2001 From: jochen Date: Sun, 4 Oct 2026 12:21:24 +0200 Subject: [PATCH 1/2] ADR 0207: a module depends on the node seats that apply its resources A service needs node-service-manager held on its node, a package node-package-manager, a container node-container-runtime: derived from the resources, never stated; refused at assign, reported at composition until the three holders are on every node. Glossary: depends on a seat; nothing claims a package. --- 00-META/glossary.md | 6 + ...the-node-seats-that-apply-its-resources.md | 107 ++++++++++++++++++ 02-DECISIONS/README.md | 1 + .../42-the-machines-modules-in-order.md | 7 ++ 4 files changed, 121 insertions(+) create mode 100644 02-DECISIONS/0207-a-module-depends-on-the-node-seats-that-apply-its-resources.md diff --git a/00-META/glossary.md b/00-META/glossary.md index 0a32834..5a84ad9 100644 --- a/00-META/glossary.md +++ b/00-META/glossary.md @@ -78,6 +78,12 @@ another — and a mesh you cannot name precisely is a mesh two people describe d mesh-scoped exclusive claim is how the mesh says "there is one of me". A foundation seat is named after the server it guards: the `mesh-controller`, `postgres` and `lavinmq` modules claim the `mesh-controller`, `mesh-store` and `mesh-broker` seats ([ADR 0079](../02-DECISIONS/0079-the-foundation-seats-are-named-after-their-servers.md)). +- **depends on a seat** — a module needing a seat held on its node by some module, without holding + it. Derived from the resources it declares, never stated: a `service` depends on + `node-service-manager`, a `package` on `node-package-manager`, a `container` on + `node-container-runtime` ([ADR 0207](../02-DECISIONS/0207-a-module-depends-on-the-node-seats-that-apply-its-resources.md)). + Not a claim: a module **claims** a seat it holds and **declares** resources. Nothing claims a + package. - **provision** — a service one module `provides` and others `require`; the mesh resolves a provider and wires the two with an endpoint and a credential. A provision is a service you offer, a seat is a role you occupy, and the two meet where a seat delivers a provision: occupying the seat is diff --git a/02-DECISIONS/0207-a-module-depends-on-the-node-seats-that-apply-its-resources.md b/02-DECISIONS/0207-a-module-depends-on-the-node-seats-that-apply-its-resources.md new file mode 100644 index 0000000..01a3208 --- /dev/null +++ b/02-DECISIONS/0207-a-module-depends-on-the-node-seats-that-apply-its-resources.md @@ -0,0 +1,107 @@ +--- +topic: the mesh +status: accepted +date: 2026-10-04 +deciders: jochen +reconstructed: false +extends: 02-DECISIONS/0166-the-container-runtime-is-a-node-seat-and-the-host-creates-containers-through-its-holder.md +--- + +# 207. A module depends on the node seats that apply its resources + +## Context + +A module declares resources: packages, services, containers, files. Some of those are applied +through software on the machine that is itself a module: + +- a service through the service manager; +- a package through the package manager; +- a container through the container runtime. + +Until now nothing said so. A module carried a *capability* such as `service-manager` or +`package-manager`, which the host detects on the machine. A capability says the software is +installed. It does not say that a module of the mesh holds the role and answers for it. + +The cost showed on 2026-10-04: + +- **A networking module declared the service manager's own package.** The controller allows one + declaration of a resource per node, so the module that *is* the service manager could not declare + its package and had been written without it. The networking module's real relation to the service + manager, that it needs one held on its node, was nowhere. +- **The container runtime** has had this decided for its own case since ADR 0165 and ADR 0166 + (proposed): a module that delivers a container needs the runtime seat held on its machine, derived + from the container resource, with no manifest field. +- **The operator's order for building the machines' modules** (to-be 42) is *the most core first*. + That is an order the mesh should enforce, not one a person should remember. + +## Considered Options + +1. **Keep capabilities as the only gate.** Rejected: a capability is a fact about the machine, not + about the mesh. Software installed by hand satisfies it, and nothing then answers for it. +2. **A manifest field per module naming the seats it needs.** Rejected: a module would restate what + its resources already say, and a module that adds a service but forgets the field passes. +3. **Derive the dependency from the resources,** as ADR 0165 already does for containers, and refuse + an assignment whose seats are not held on the node. Chosen. + +## Decision + +**1. Three node seats apply resources,** each in the mesh's own set: + +| resource | applied through | seat | first holder | +|---|---|---|---| +| `service` | the service manager | `node-service-manager` (ADR 0177) | `systemd` | +| `package` | the package manager | `node-package-manager` (new) | `pacman` | +| `container` | the container runtime | `node-container-runtime` (ADR 0166) | `docker` | + +`node-package-manager` is new and has no verbs yet. `node-container-runtime` is seeded now as ADR 0166 +names it. Its verbs, and the host creating containers through its holder, stay with that record's +acceptance. + +**2. A module depends on each seat its resources need.** The controller derives this from the +resource types the module declares. A module never states it. + +**3. A dependency is met when any module assigned to the same node holds the seat,** the module +itself included. The holders of these seats declare resources of each other's kinds: the service +manager's package needs the package manager, and the package manager's timer needs the service +manager. They are therefore judged as the node's whole set of assignments, never one at a time. + +**4. Where it is checked:** + +- **At `assign`,** an assignment whose dependencies are unmet by the node's assignments, including the + new one, is refused. The refusal names each seat and the modules in the catalogue that can hold it. +- **At composition,** an unmet dependency on a node is **reported** in `status` until the three holders + are assigned to every node. Then it is **refused** like any unresolved requirement. The switch is one + line in the controller, made when `status` reports none. + +**5. The mesh's own foundation is exempt.** These are the pieces genesis lays before any module exists: +the host, the private network and the bootstrap runtime. Their declarations are the installation's, +not a module's. + +## Consequences + +- The order of to-be 42 becomes the mesh's: `systemd`, `pacman` and `docker` on a node before + anything that installs, runs or contains. +- **Two modules no longer declare one shared package to say they need it.** A component's module + (networkd's) declares what it configures and depends on the seat. The component's own package + belongs to the module that holds the seat. +- Capabilities stay what they are, facts about the machine, used where a module needs the machine to + be able to do something. +- **What got harder:** a module can no longer be tried on a node that lacks the core three. That is + the point. + +## How it is checked + +| Rule | Checked by | +|---|---| +| The dependency is derived from resources: a service, a package and a container each need their seat | the controller's resolve tests | +| A node whose assignments hold the seats passes; one missing a holder is refused at `assign`, naming the seat and its possible holders | the same tests, and `assign` live | +| Mutual dependencies among the holders resolve when they are assigned together | the same tests | +| Until the switch, an unmet dependency is reported in `status` and does not refuse a push | the controller's status test | +| Foundation declarations are exempt | the composition test with genesis's declarations | + +## References + +- [ADR 0165](0165-container-runtime-is-what-a-machine-can-run-and-a-running-runtime-is-its-holders-health.md), + [ADR 0166](0166-the-container-runtime-is-a-node-seat-and-the-host-creates-containers-through-its-holder.md), + [ADR 0177](0177-a-unit-may-be-user-scoped-and-the-service-manager-is-a-node-seat.md) +- [To-be 42](../03-DESIGN/01-to-be/42-the-machines-modules-in-order.md) diff --git a/02-DECISIONS/README.md b/02-DECISIONS/README.md index 771e1ca..bd6e653 100644 --- a/02-DECISIONS/README.md +++ b/02-DECISIONS/README.md @@ -191,6 +191,7 @@ python3 00-META/checks/index.py fail if stale - **0189** — [The store keeps what the records name, and a maintenance step holds its writers still](0189-the-store-keeps-what-the-records-name.md) - **0190** — [A seat's work is shared by its holders, and building is the first such role](0190-a-seats-work-is-shared-by-its-holders-and-building-is-the-first-such-role.md) - **0202** — [A provider declares what it derives for each consumer, and the mesh tells both ends](0202-a-provider-declares-what-it-derives-for-each-consumer.md) +- **0207** — [A module depends on the node seats that apply its resources](0207-a-module-depends-on-the-node-seats-that-apply-its-resources.md) ### Its tiers, from the bottom up diff --git a/03-DESIGN/01-to-be/42-the-machines-modules-in-order.md b/03-DESIGN/01-to-be/42-the-machines-modules-in-order.md index 7708391..03cc8ea 100644 --- a/03-DESIGN/01-to-be/42-the-machines-modules-in-order.md +++ b/03-DESIGN/01-to-be/42-the-machines-modules-in-order.md @@ -13,6 +13,7 @@ decisions: - 02-DECISIONS/0203-the-accounts-environment-is-one-modules-and-every-module-contributes-to-it.md - 02-DECISIONS/0204-a-module-contributes-shell-code-to-the-login-shell-in-named-slots.md - 02-DECISIONS/0205-software-the-distribution-does-not-package-ships-as-a-pinned-archive-of-the-module.md + - 02-DECISIONS/0207-a-module-depends-on-the-node-seats-that-apply-its-resources.md --- # 42. The machines' modules, in order @@ -65,6 +66,12 @@ In order: | 10 | scripts | the operator's own scripts, shared and per role (research 027/03) | under no version control, copied by hand | | 11 | `kernel` | kernel, microcode, boot entries | two machines without microcode | +`systemd`, `pacman` and `docker` hold the three seats that apply resources +([ADR 0207](../../02-DECISIONS/0207-a-module-depends-on-the-node-seats-that-apply-its-resources.md)): +every module that declares a service, a package or a container depends on them being held on its node. +They go on every machine before the rest, and once they have, an unmet dependency is refused rather +than reported. + `kernel` is last because a mistake in it costs a boot. `docker` stays a module without the runtime seat until ADRs 0165 and 0166 are accepted. From ed5ddcdef6f8cc800988a1b05ed14d65f61fe024 Mon Sep 17 00:00:00 2001 From: jochen Date: Sun, 4 Oct 2026 12:21:40 +0200 Subject: [PATCH 2/2] ADR 0207 extends ADR 0177 (accepted); 0166 stays a reference --- ...module-depends-on-the-node-seats-that-apply-its-resources.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/02-DECISIONS/0207-a-module-depends-on-the-node-seats-that-apply-its-resources.md b/02-DECISIONS/0207-a-module-depends-on-the-node-seats-that-apply-its-resources.md index 01a3208..343636a 100644 --- a/02-DECISIONS/0207-a-module-depends-on-the-node-seats-that-apply-its-resources.md +++ b/02-DECISIONS/0207-a-module-depends-on-the-node-seats-that-apply-its-resources.md @@ -4,7 +4,7 @@ status: accepted date: 2026-10-04 deciders: jochen reconstructed: false -extends: 02-DECISIONS/0166-the-container-runtime-is-a-node-seat-and-the-host-creates-containers-through-its-holder.md +extends: 02-DECISIONS/0177-a-unit-may-be-user-scoped-and-the-service-manager-is-a-node-seat.md --- # 207. A module depends on the node seats that apply its resources