Files
hq/02-DECISIONS/0176-the-login-shell-is-a-node-seat-and-execute-is-its-contract.md
T
jochen 0bf70ee8b4 Graduate research 025: the environment and the shell's contributions
ADR 0203: the account's environment is one module's (seat node-environment);
every module contributes variables and PATH entries, rendered by the
controller as a POSIX file and as environment.d.
ADR 0204: shell code is contributed to the login shell in named slots, and
login-shell becomes the mesh's node-login-shell.
ADR 0205: software the distribution does not package ships as a pinned
archive of the module.
Issue 225: undeclaring a user stops a node applying; the shell is never
given back or checked.
To-be 41 carries the work packages; to-be 38 WP5 points to it.
2026-10-04 10:30:23 +02:00

5.0 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

The mechanism changed — 2026-10-04, by ADR 0204. The seat is no longer declared by the shell modules (§1). It is node-login-shell, in the mesh's own seat set, which a shell module claims. Its holder also places the shell code other modules contribute, and sources the account's environment (ADR 0203). What stands: one holder per node, the login shell set by the user shape and given back, execute as the contract, and any node may call it.

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