Refuse to take over a system account as one that never becomes root
mesh/merge-gate pass: builds mesh-host → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request

The controller cannot read a machine's user database, so a name it is given
for the agents' account (hq ADR 0266) may be a service's own; taking it over
would hand agents that service's files. Refuse it, touching nothing.
This commit is contained in:
jochen
2026-10-08 20:52:44 +02:00
parent 5fc37b44a9
commit 76f3ca12b8
2 changed files with 44 additions and 0 deletions
+15
View File
@@ -21,6 +21,9 @@ import (
// are a package plus configuration **in somebody's home** — so a mesh with no notion of a user
// can manage /etc and nothing anybody looks at.
// FirstLoginUID is the first uid of a person's login on the distributions the mesh runs on (login.defs UID_MIN).
const FirstLoginUID = 1000
// applyUser makes a login match what was declared.
//
// Reconciling, like everything else here: it is not told whether the user is new. Creating,
@@ -51,6 +54,18 @@ func applyUser(ctx context.Context, sys system.System, r *declaration.User, run
return out, err
}
// **An account that must never become root is never a system account taken over** (novox/hq ADR 0266).
// The controller cannot read this machine's user database, so it cannot tell that a name it was given is a
// service's own (postgres, a module's daemon). Taking one over as the agents' account would hand agents
// that service's files and rights. Refused before anything is touched.
if r.Root == declaration.RootNever && exists {
if uid, err := strconv.Atoi(login.UID); err != nil || uid < FirstLoginUID {
return out, fmt.Errorf("%q is declared as an account that never becomes root, and it already exists "+
"here as a system account (uid %s, below %d): it is not taken over; name another account",
r.Name, login.UID, FirstLoginUID)
}
}
// **A shell is refused before anything is touched** (novox/hq issue 228). Refused after the
// account was created or its groups changed, the account would be half the declaration's; a
// refusal fails this resource and leaves the account exactly as it was.