--- layer: to-be status: proposed code: [] updated: 2026-09-27 decisions: - 02-DECISIONS/0112-a-module-definition-names-no-node-mesh-or-path.md - 02-DECISIONS/0051-shared-data-is-the-operators.md --- # 29 — A node has operator accounts, and the mesh owns what lives under a home **The mesh models machines but not the people on them.** A node record holds its name, its address, its mode — and nothing about *who a person is* on it: `jochens` on novox, `ace` on ace, `jochen` on shanks and g14. That username is not incidental. It decides who a file under `~` is owned by, who a user service runs as, and — the case that surfaced this — which account `ssh ` logs in as. The predecessor knew it (its per-node `user:`, and the modules that wrote a person's `~/.ssh/config`, `~/.zshrc`, `~/.config`); the mesh, taking those over, kept the machine facts and dropped the human one. Two things are missing, and they are one idea: ## 1. The account is a node fact A node has one or more **operator accounts**: the human logins on it. At minimum a name; the mesh already knows the node and its address, so `@` is then a complete answer to "who am I, where." It is the mesh's to hold because everything below is derived from it, and because it is exactly the fact that was silently lost — `ssh ace` failed to `ace` because nothing in the mesh said ace's account is `ace`. It is **not** a credential. The account names a login; the key that authorises it is the operator's, placed as a secret or an operator-owned file, never minted by the mesh (ADR 0051). ## 2. A resource may live under a home, owned by its account [ADR 0112](../../02-DECISIONS/0112-a-module-definition-names-no-node-mesh-or-path.md) placed a module's *system* data — `/`, owned by the module. It has no analog for the other half of the filesystem: the things that belong under a person's home and are owned by that person. `~/.ssh/config`, `~/.ssh/config.d/mesh`, `~/.zshrc`, `~/.config/hal` — every one of these is a resource the mesh should be able to place and own, resolved against **the account's home** rather than a system root, and chowned to **the account** rather than to root or a module uid. This is the same move as `${dir:…}`, one level over: a resource says `home: ` (or names an account requirement), and the mesh resolves the home directory and the owning uid on the node that account lives on. A module that writes operator config — the eventual replacements for `hal/terminal`, `hal/claude-code`, `hal/secrets` — declares its files this way and names no `/home/...` path, exactly as a system module now names no `/var/lib` path. ## Why now, and why not yet **Why it matters:** when HAL retires, the generators that keep `~/.ssh/config`, shell config and the operator's `~/.config/hal` current retire with it. Without this, adding a node stops adding its ssh alias, and a fresh machine has no operator dotfiles at all — the mesh would run every service and leave the human unable to work on the box. The account is also load-bearing for correctness already: `ssh ` (issue 122's cousin), user-scoped systemd units, and any file a person rather than a daemon must own. **Why not build it reflexively:** it is a real addition to the node model and the resource model, and it must be gotten right, not smuggled in beside a firewall fix. Open questions to settle first: - **One account or several per node?** A workstation has one human; a shared box might have more. The model should allow more than one without forcing the common case to name it. - **Where the login key lives.** An operator-owned file (ADR 0051) or an accepted secret — never minted. The account fact and the key that authorises it are separate, and only the first is the mesh's to generate. - **The boundary with `sshd`.** The `sshd` module (server side) already exists. This is the *client* and *identity* side: the account a node offers, and the home-scoped files an operator needs. They meet at the account but are not the same module. - **Multi-operator.** Today there is one human. The model should not assume it, but the first cut may serve one and leave the shape open. **Not urgent, not blocking.** ssh and dotfiles work today because HAL's generators still run as the substrate. This becomes load-bearing in the node-by-node retirement phase, not before — which is the right time to build it, once the account model is decided here. ## References - The gap was found generating `~/.ssh/config` from the *HAL* registry (`hal/terminal`'s postConfigure hook), which the nox mesh has no equivalent for. - [ADR 0112](../../02-DECISIONS/0112-a-module-definition-names-no-node-mesh-or-path.md) — the system-path placement this mirrors for home paths. - [ADR 0051](../../02-DECISIONS/0051-shared-data-is-the-operators.md) — why the login key stays the operator's, never minted.