rig/changelog.d
cluade-reviewer-andresmgsl 7aed6ea098 fix: preflight every admin binary a command uses, not only useradd
Addresses codex (1538) and kimi (1539): the sweep caught the reported
incident and not the class. Both are right, and there were four sites, not
three.

  forgejo-runner-install  useradd -> useradd usermod   (usermod -aG docker,
                          reached only after the token has been spent)
  users-apply             useradd usermod -> + groupadd (called two lines
                          into convergence), and visudo when a role needs it
  bootstrap-tenant        NEW site (kimi) — usermod -aG docker runs AFTER
                          docker and node are installed, so an unguarded
                          PATH fails it mid-convergence on a changed machine
  runner-install          unchanged: useradd is the only admin binary it
                          calls, and declaring more would refuse boxes that
                          are fine

visudo is checked after the sudo-install block rather than beside the root
check, because until sudo is installed its absence has an innocent cause.
Below that block it does not: sudo is present, so a missing visudo means
/usr/sbin is off PATH. That case is the quiet one — the sudoers block reads
`command -v visudo` as "no sudo on the box means no role needed it", so
apply reported success having granted roles without the escalation those
roles exist for. The other three sites at least crash.

Measured which binaries this covers (Debian 13): useradd, usermod, groupadd,
userdel, groupdel and visudo are /usr/sbin; gpasswd is /usr/bin and so is
NOT affected and deliberately not preflighted. visudo shares the directory
but ships in `sudo`, not `passwd` — which is why it needs its own treatment.

Tests: the sbin-less fixtures could only ever prove the FIRST binary is
named, since useradd wins every race. Six new checks use partial PATHs that
resolve the earlier binaries and withhold exactly one, plus the ordering
assertions (no token prompt, no group created) and the negative case — a
users file needing no sudo must NOT be refused for a missing visudo.

Refs #139
2026-08-02 00:05:02 +00:00
..
109.md docs: the changelog fragment cites bare #109 2026-07-28 09:26:17 +00:00
111.md docs: shorten changelog.d/111.md under the 300-char entry guard 2026-07-29 14:45:57 +00:00
112.md docs: the changelog fragment says what changed and stops 2026-07-29 12:22:08 +00:00
116.md fix: preserve triage across both forges 2026-07-30 18:31:16 +00:00
129.md feat(drill): a forgejo-runner lifecycle leg beside the GitHub one 2026-07-30 23:27:36 +00:00
131.md docs: README install quick start names the Forgejo channel (RIG_HOST) 2026-07-30 23:52:44 +00:00
133.md fix(forgejo-runner): 'active' is not proof the runner is fetching 2026-07-31 00:15:02 +00:00
135.md fix(forgejo-runner): the cache server can start 2026-07-31 16:59:03 +00:00
139.md fix: preflight every admin binary a command uses, not only useradd 2026-08-02 00:05:02 +00:00
144.md fix: warn only on retired default labels, not custom maps (#144) 2026-08-01 21:33:11 +00:00
152.md fix: group machine role changelog entry 2026-07-25 13:07:01 +00:00
153.md fix: group template snapshot changelog entry 2026-07-25 16:00:29 +00:00
160.md fix: scope the netmap tag read to Self 2026-07-25 16:02:54 +00:00
162.md fix: arm cron on agent tenant boxes 2026-07-25 18:54:27 +00:00
README.md feat: convert unreleased changelog to fragments 2026-07-24 13:55:28 +00:00

changelog.d/ — the next release's section, one fragment per issue

Machine-assembled by bin/changelog-assemble (#112): every PR that changes behavior writes one file here — <issue>.md, the exact prose that will be published, nothing else — and the release PR folds them all into the next ## X.Y.Z — DATE section of CHANGELOG.md, consuming them. Distinct filenames never conflict, which is this directory's whole reason to exist. This README is the marker that keeps the directory tracked when it holds no fragments (#112 D1) — changelog-armed refuses a tree without it; do not delete it.