Merge pull request 'ADR 0210: a tool's configuration is its seat holder's, and every other module extends it through the seat' (#361) from decision/0210-a-contribution-depends-on-the-seat-that-receives-it into main

This commit was merged in pull request #361.
This commit is contained in:
2026-10-04 13:42:56 +00:00
5 changed files with 135 additions and 0 deletions
@@ -93,6 +93,11 @@ A node with contributions and no holder writes them nowhere. The holder's absenc
node's assignments, and no contributor is refused for it, because a missing `PATH` entry is a gap, not
a broken machine.
> **The mechanism changed — 2026-10-04, by [ADR 0210](0210-a-tools-configuration-is-its-seat-holders-and-every-other-module-extends-it-through-the-seat.md).** A contribution is now a dependency on
> node-environment, met and refused as ADR 0207 says, so a node without the holder refuses the
> contributor instead of writing the contribution nowhere. The rest of this section, and the
> decision, stand.
## Consequences
- A shell's part in the environment is one line in its always-read startup file, sourcing the
@@ -87,6 +87,12 @@ reports, `graphical-session`, still gates the display server itself.
The holder of `node-display-server` places them with `${shell:xinitrc:<slot>}` and
`${shell:xresources:<slot>}`.
> **The mechanism changed — 2026-10-04, by [ADR 0210](0210-a-tools-configuration-is-its-seat-holders-and-every-other-module-extends-it-through-the-seat.md).** A contributor no longer places its own
> file in another tool's directory. It contributes to the tool's seat, and the seat's holder places it,
> in that directory or through a placeholder. Every contribution, the `xinitrc` and `xresources` slots
> included, is a dependency on the seat that receives it. What a contribution contains still follows
> the tool's grain.
**5. The display server's module writes the session's start.** It writes a block at the start of
`~/.xinitrc`, in this order:
@@ -0,0 +1,115 @@
---
topic: the mesh
status: accepted
date: 2026-10-04
deciders: jochen
reconstructed: false
extends: 02-DECISIONS/0207-a-module-depends-on-the-node-seats-that-apply-its-resources.md
---
# 210. A tool's configuration is its seat holder's, and every other module extends it through the seat
## Context
One fault kept coming back while the machines' modules were rolled out
([to-be 42](../03-DESIGN/01-to-be/42-the-machines-modules-in-order.md)): two modules want the same
thing on a node.
- The bar module and the package manager's module both declared the package that brings the
package manager's helper scripts. The node stopped resolving
([issue 235](../04-ISSUES/235-an-assignment-that-cannot-be-composed-is-recorded-anyway/00-report.md)).
- The launcher, the clipboard manager, the wallpaper and the bar each wrote a file of their own into
the window manager's include directory, as [ADR 0208](0208-the-graphical-session-is-one-module-per-piece-on-the-meshs-seats.md)
§4 allowed. Nothing says those modules need the window manager. Assigned without it, they write
configuration nothing reads. Assigned with a different session holder, they write into a directory
that holder does not own.
- [ADR 0203](0203-the-accounts-environment-is-one-modules-and-every-module-contributes-to-it.md) §5
lets a module contribute to the environment on a node that has no holder: the contribution is
written nowhere, and nothing says so.
The mesh already has the piece that answers this.
[ADR 0207](0207-a-module-depends-on-the-node-seats-that-apply-its-resources.md) made a module depend on
the seat that applies its resources, derived from what it declares. A contribution is the same kind
of need. It is configuration that only the seat's holder can apply.
## Considered Options
1. **Let the first module to declare a file or package own it,** and refuse the second. Rejected:
ownership then depends on the order modules were written, and the second module has no lawful way
to say what it needs.
2. **Allow shared declarations** of one package or file by several modules, merged by the host.
Rejected: a shared file has no owner to answer for it, and removing one module cannot tell what it
alone put there.
3. **Each tool's configuration belongs to the module holding the tool's seat. Every other module
extends it with a contribution to that seat, and a contribution is a dependency on the seat.**
Chosen. It is the operator's statement of the rule.
## Decision
**1. One owner.** A tool's configuration files, and the tool's package, belong to the module that
holds the tool's seat on the node. Only that module writes them.
- The package manager's configuration and helper packages are the package manager's module's.
- The account's environment is node-environment's holder's.
- The window manager's configuration is node-display-session's holder's.
**2. Other modules extend, never write.** A module that needs something in another tool's
configuration declares a **contribution to that tool's seat**:
- its content, in the grain the seat defines (variables and paths, shell code for a named shell and
slot, a window-manager configuration fragment, a notifier rule);
- never a path inside the holder's files or directories.
The holder places what it receives:
- the controller renders the contributions into the holder's files through the holder's placeholders,
as [ADR 0203](0203-the-accounts-environment-is-one-modules-and-every-module-contributes-to-it.md) and
[ADR 0204](0204-a-module-contributes-shell-code-to-the-login-shell-in-named-slots.md) already do;
- or the holder writes each contribution to its tool's own drop-in directory. That directory is then
the holder's resource, not the contributor's.
**3. A contribution is a dependency on the seat that receives it.** The controller derives it from the
contribution, as ADR 0207 derives one from a resource. It is met, checked and refused exactly as ADR
0207 §3 and §4 say:
- refused at `assign` when no module on the node holds the seat and the catalogue has a holder;
- refused at composition after the switch.
**4. Needing what another module's package delivers is the same.** A module that needs a program
another seat's holder installs does not declare that package. It depends on the seat, and through
the seat's verbs where they exist. One package is declared by one module on a node.
**5. A seat says what it receives.** A seat lists the contribution kinds its holder accepts. A
contribution of a kind the seat does not list is refused at registration.
## Consequences
- **ADR 0203 §5** no longer holds: a module contributing to the environment depends on
node-environment, and a node without the holder refuses it. The rest of that record stands.
- **ADR 0208 §4**: its first list, contributors placing their own files in another tool's directory,
is replaced by §2 above. The tool's grain stays the guide for what a contribution contains. The
`xinitrc` and `xresources` slots already work this way, and now carry a dependency on
node-display-server.
- **The desktop modules change:** the launcher, the clipboard manager, the wallpaper and the bar
contribute their window-manager lines to node-display-session instead of writing into the include
directory. The bar keeps relying on the package manager's helper scripts through node-package-manager.
- **The two kinds of collision cannot recur:**
- two modules declaring one package or one file;
- a contribution to a seat nobody on the node holds.
A composition that finds either is a fault in a module, not a state a node can be left in.
- **What got harder:** a seat that receives contributions must define their grain, and its holder must
place them. Each new kind is a small change to the controller's renderer or to the holder.
## How it is checked
| Rule | Checked by |
|---|---|
| A contribution derives a dependency on the seat that receives it | the controller's resolve tests |
| A contribution to a seat with no holder on the node is refused at `assign` when the catalogue has a holder | the same tests, and `assign` live |
| One package or file is declared by one module on a node | the controller's composition test, and `module check` across the catalogue |
| A contribution of a kind its seat does not list is refused | the catalogue check, which registration runs |
| No module declares a path inside another module's files or directories | the catalogue check |
## References
- [ADR 0203](0203-the-accounts-environment-is-one-modules-and-every-module-contributes-to-it.md),
[ADR 0204](0204-a-module-contributes-shell-code-to-the-login-shell-in-named-slots.md),
[ADR 0207](0207-a-module-depends-on-the-node-seats-that-apply-its-resources.md),
[ADR 0208](0208-the-graphical-session-is-one-module-per-piece-on-the-meshs-seats.md)
- [Issue 235](../04-ISSUES/235-an-assignment-that-cannot-be-composed-is-recorded-anyway/00-report.md)
+1
View File
@@ -192,6 +192,7 @@ python3 00-META/checks/index.py fail if stale
- **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)
- **0210** — [A tool's configuration is its seat holder's, and every other module extends it through the seat](0210-a-tools-configuration-is-its-seat-holders-and-every-other-module-extends-it-through-the-seat.md)
### Its tiers, from the bottom up
@@ -15,6 +15,7 @@ decisions:
- 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
- 02-DECISIONS/0208-the-graphical-session-is-one-module-per-piece-on-the-meshs-seats.md
- 02-DECISIONS/0210-a-tools-configuration-is-its-seat-holders-and-every-other-module-extends-it-through-the-seat.md
---
# 42. The machines' modules, in order
@@ -93,6 +94,13 @@ In order:
The seats, gating, contributions and session start are [ADR 0208](../../02-DECISIONS/0208-the-graphical-session-is-one-module-per-piece-on-the-meshs-seats.md).
**Who writes what** is [ADR 0210](../../02-DECISIONS/0210-a-tools-configuration-is-its-seat-holders-and-every-other-module-extends-it-through-the-seat.md): a tool's configuration belongs to the
holder of its seat. The launcher, the clipboard manager, the wallpaper and the bar contribute their
window-manager lines to `node-display-session`, and the window manager's module places them. They do
not write into its include directory. Each contribution is a dependency on the seat that receives it,
so assigning one of them without a window manager is refused. The first versions, which still write
the include files themselves, move to contributions once the controller derives the dependency.
## Phase 3 — one machine model
The laptop's hardware module (vendor daemon, GPU mode, charge limit, logind, brightness and vendor keys)