feat(mgmtplane): break-glass privsep-dir watchdog + mgmt_plane health (TASK G1) — v0.71.0

Prerequisite for felhom-sshd (H1). Closes the SPIKE-felhom-sshd §8 lockout: a
second sshd's RuntimeDirectory=sshd removed the SHARED /run/sshd privsep dir and
took stock sshd on :22 down (sessions reset after KEXINIT).

Host artifacts (configs/, installed by felhom-host-install):
- felhom-privsep.tmpfiles: layer 1, boot-persistent /run/sshd owned by no unit
- felhom-mgmt-watchdog.sh/.service/.timer: layer 2, AGENT-INDEPENDENT ~60s heal
  (stat-first recreate + reset-failed sshd only if failed + heal-marker); never
  RuntimeDirectory=, never restarts stock sshd, never touches a healthy dir.

Go (internal/mgmtplane): read-only Reporter → additive omitempty mgmt_plane
heartbeat stanza (privsep_dir_ok/sshd_reachable/healed_recently/privsep_healed_at),
wired via Collector.SetMgmtPlaneReporter. Non-hollow tests + red-proofs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
2026-07-05 18:49:27 +02:00
parent 1c75a45a42
commit fd4e177216
11 changed files with 459 additions and 1 deletions
+23 -1
View File
@@ -1,4 +1,26 @@
## v0.70.0 — agent self-update (operator-signed, A/B slots, crash-loop auto-rollback) (2026-07-05)
## v0.71.0 — management-plane break-glass: privsep-dir watchdog + mgmt_plane health (TASK G1) (2026-07-05)
Prerequisite for the felhom-sshd OOB feature (H1). Closes the lockout from
`felhom.eu/documentation/audits/SPIKE-felhom-sshd-2026-07-05.md` §8: a second sshd's
`RuntimeDirectory=sshd` removed the SHARED `/run/sshd` privsep dir and took the stock sshd on :22 down
too (sessions reset right after SSH2_MSG_KEXINIT) — a management lockout on a healthy box. Three
independent layers; this repo ships the host artifacts + the agent reporter (hub vault + surfacing are
the felhom.eu half).
- **Host artifacts** (`configs/`, installed by felhom-host-install): `felhom-privsep.tmpfiles`
(`d /run/sshd 0755 root root -` — layer 1, boot-persistent, owned by no unit's lifecycle);
`felhom-mgmt-watchdog.sh` (layer 2 heal action — stat-first recreate `/run/sshd`, `reset-failed`
ssh ONLY when `failed`, write an RFC3339 heal-marker; NEVER restarts the stock sshd, NEVER touches a
healthy dir — shellcheck-clean); `.service` (oneshot) + `.timer` (~60s, `Persistent`). The healer is
**agent-INDEPENDENT** — it self-corrects with felhom-agent stopped (the whole point). **No unit
declares `RuntimeDirectory=`** (that IS the incident cause; the installer refuses any that does).
- **Go** (`internal/mgmtplane/`): a read-only `Reporter` (os.Stat `/run/sshd` + read the heal-marker +
a short TCP dial to sshd:22) producing the additive `mgmt_plane` heartbeat stanza
(`{privsep_dir_ok, sshd_reachable, healed_recently, privsep_healed_at}``omitempty`, the
SelfUpdatePending precedent, no hub-schema change). Wired always-on via
`Collector.SetMgmtPlaneReporter`. The hub raises a warning on a new `privsep_healed_at` so a
recurring clobber surfaces BEFORE a lockout (complements host_staleness). Touches host `/run` + the
stock sshd only — no guests.
Closes the update asymmetry: the root-adjacent agent was updated by manual SSH binary-replace while
the lower-stakes controller already auto-updates. Design provenance: