Files
hq/02-DECISIONS/0176-the-login-shell-is-a-node-seat-and-execute-is-its-contract.md
T
jochen bf39baf104 Research 018 graduates: ADRs 0173–0177 and to-be 37, the operator's machine
Every configurable thing on a node is a module, the home included, and a
module is whatever it declares (0173, extending 0040). A node varies a module
only through a setting rendered into the file or a kept region, never an edit
(0174, extending 0011; issue 168 first). One tool runtime per node serves every
module's tools on the host side, never in a container; the console is its
serving mode, renamed node-tools (0175, extending 0150; 0047/0150/0152 carry
dated notes). The login shell is a node seat held by one shell module with
`execute` as its contract (0176). A unit may be user-scoped and the service
manager is a node seat held by systemd (0177).

To-be 37 is handed off in-progress to mesh-host, mesh-controller, mesh-tools
and mesh-catalog, with the build in order: the account on every node, the
runtime, zsh, systemd, then the graphical stack. To-be 29 keeps ~/.ssh and
points at 37; 33 §6 and 34 are amended; the glossary gains node tools, bundle,
kept region, installed/holding, and retires flavor.
2026-10-02 16:34:57 +02:00

4.4 KiB

topic, status, date, deciders, reconstructed, extends
topic status date deciders reconstructed extends
what runs on it accepted 2026-10-02 jochen false 02-DECISIONS/0132-a-seat-carries-the-tools-its-holder-must-serve.md

176. The login shell is a node seat held by one shell module, and execute is its contract

Context

ADR 0040 names the shell as its example of a shared seat: bash, zsh and fish all join shell, and one may be default. The operator's reading is sharper, and it matches ADR 0126 better: installing a shell is installing software, and several may be installed; holding the seat is being the login shell, which a node has exactly one of. A definition says which seats a module can hold; the assignment says which it does.

A seat carries the tools its holder must serve (ADR 0132), and to-be 33 leaves which verbs each seat serves as a decision per seat, taken slowly. This is the first seat of the operator's environment, and the one every node has.

Considered Options

  1. A shared shell seat with a default, as 0040's example reads. Rejected: default is a second concept beside holder for the same fact, and the user shape already makes the login shell declared state (to-be 05).
  2. No seat; each shell module sets the login shell for itself. Rejected: two assigned shell modules would fight over chsh, and nothing would say which won.
  3. An exclusive node-scoped seat, login-shell, declared by the shell modules, held by one per node. Chosen.

Decision

1. login-shell is a node-scoped seat declared by the shell modules. zsh, fish and bash each declare that they can hold it; a node's assignment says which does; the controller refuses a second holder by name as for every seat. A shell module that is assigned without holding the seat is installed and nothing more.

2. Holding the seat sets the account's login shell. The holder's declaration carries the user shape with the shell it provides, so the login shell is declared state the host applies and gives back when the holding moves — chsh stops being a hook.

3. The seat's contract is execute. One verb, one argument, the command, run on the node the seat is scoped to as the operator account, answering with what it printed and how it exited. Every holder serves it; a holder may serve its own tools beside it (ADR 0170 §2) — show the rendered configuration, list the plugins, set a prompt value.

4. Any node may call it on any node. The grant is the node tools runtime's (ADR 0175 §5): run uptime on every node is five calls to one verb.

Consequences

  • The first environment module is a shell: a package, files under the home owned by the account, a seat declaration and claim, a user shape, and one tool. It proves the whole pattern on every node, servers included, before anything graphical is written.
  • ADR 0040's shell example is read as installed is not holding; a dated note in that record says so. Its decision is untouched.
  • execute is a shell on every machine, addressed over the bus. That is the point, and it is the widest verb the mesh serves; it exists because the operator decided every node may call every tool, and this record does not narrow that.

How it is checked

Rule Checked by
Two shell modules assigned to one node, one holding: one user shape in the declaration, naming the holder's shell the controller's composition tests
A second claimant is refused by name the catalogue's seat tests
execute runs as the account and answers output and exit status the module's tool tests over a fake runner, and live on every node
The seat's verb appears with its scope and machine in the node tools listing the runtime's tests (to-be 33 §4)

References