Files
hq/03-DESIGN/01-to-be/29-a-node-has-operator-accounts.md
T
jschoubben 64bbdc30c1 to-be 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 no username, and no module places anything under a home. So who
you are on each node (jochens/ace/jochen) is unknown to the mesh, and
nothing owns ~/.ssh, dotfiles or ~/.config. HAL knew it; the nox mesh
dropped it. Proposes the account as a node fact and a home-scoped
resource class (the ~/ mirror of ADR 0112's /var/lib placement), with
the login key staying the operator's (ADR 0051). Not urgent — HAL's
generators still run — load-bearing at node-by-node retirement. Found
generating ~/.ssh/config from HAL's registry, which nox has no
equivalent for.
2026-09-26 23:53:13 +02:00

4.8 KiB

layer, status, code, updated, decisions
layer status code updated decisions
to-be proposed
2026-09-27
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 <node> 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 <account>@<node> 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 placed a module's system data — <root>/<module>, 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: <account> (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 <node> (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 — the system-path placement this mirrors for home paths.
  • ADR 0051 — why the login key stays the operator's, never minted.