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.
82 lines
4.4 KiB
Markdown
82 lines
4.4 KiB
Markdown
---
|
|
topic: what runs on it
|
|
status: accepted
|
|
date: 2026-10-02
|
|
deciders: jochen
|
|
reconstructed: false
|
|
extends: 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](0040-what-a-module-is.md) 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](0126-a-module-declares-its-own-seats.md) 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](0132-a-seat-carries-the-tools-its-holder-must-serve.md)),
|
|
and [to-be 33](../03-DESIGN/01-to-be/33-the-tools-the-mesh-answers.md) 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](../03-DESIGN/01-to-be/05-the-node-host.md)).
|
|
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](0170-the-firewall-seat-serves-its-verbs.md) §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](0175-one-tool-runtime-per-node-serves-every-modules-tools-on-the-host-side.md) §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
|
|
|
|
- [Research 018](../01-RESEARCH/018-the-operators-machine-as-modules/04-the-seats-of-the-environment.md)
|
|
- [ADR 0040](0040-what-a-module-is.md), [ADR 0126](0126-a-module-declares-its-own-seats.md),
|
|
[ADR 0132](0132-a-seat-carries-the-tools-its-holder-must-serve.md), [ADR 0170](0170-the-firewall-seat-serves-its-verbs.md)
|