5.7 KiB
topic, status, date, deciders, reconstructed, extends
| topic | status | date | deciders | reconstructed | extends |
|---|---|---|---|---|---|
| the mesh | accepted | 2026-10-04 | jochen | false | 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
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
- 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.
- 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.
- 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
statusuntil 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 whenstatusreports 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,pacmananddockeron 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 |