agent v0.146.1 REPORT
gates / gates (push) Successful in 22s

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-10-05 13:00:22 +02:00
parent e4b5cf9693
commit e06ed97fa8
+49 -11
View File
@@ -1,14 +1,52 @@
# REPORT — agent v0.145.0 (2026-10-05, afternoon): the OS update repairs itself after a power cut
# REPORT — agent v0.146.0 / v0.146.1: the agent's root grants narrowed (R-861), the step bundle (R-880) — 2026-10-05
Brief: the 2026-10-05 catch-up brief (operator), Parts C (R-874, R-875) and D (R-876). Full session report:
`felhom.eu/REPORT-catchup-2026-10-05.md`. Architecture: `11-os-updates.md` §5.4.1, §8.4–8.5; `09` decisions 117–118.
Brief: "an open-items batch … and the agent permission fix (R-861) as its own Part" (Part F). Full session report:
`felhom.eu/REPORT-hub-safety-2026-10-05.md`. Design: `felhom.eu/documentation/architecture/03-host-agent.md` §3.1.
Evidence: `felhom.eu/documentation/audits/hub-safety-2026-10-05/partF/`, delivery `…/partH/`.
| Row | Fix | Proof |
|---|---|---|
| R-876 | the wrapper reads `dpkg --audit` AND the update journal in ONE call, repairs on either; belt: repair + retry once when apt says "interrupted" | 3 tests + 3 red-proofs; **live (operator's go): crash mid-unpack on demo-hp → the next pass `REPAIR … journal=1` → `DONE rc=0 upgraded=12`, nobody touched the box** |
| R-874 | the restore-test's first due-check 30 min after start | 2 tests + red-proof; live on demo-felhom: passed restore-test at start + 30 min |
| R-875 | a kept report's reason is neutral ("sent late …") | test + red-proof |
## Baseline and commits
Released by `scripts/release-agent.sh`: v0.145.0 (`894da35c…`, bundle `78c00adc…`), verified by download; signed
`agent_update` + `agent_config_update` to demo-hp, demo-felhom, tester-1 (71/71 after each bundle); vouched with
golden 0.295.0, min_agent 0.131.0. `go test ./...` rc 0, Python suites OK, `agent_gates.py` OK.
- Baseline `61345790ed` (v0.145.0).
- `6ab1e7c` R-861 narrowing → released **v0.146.0** (binary `b860af46…`, bundle `161c737e…`) — **never vouched, never
delivered**: a background security review of that commit found three holes.
- `fdd8717` the review fixes → released **v0.146.1** (binary `badd6c9a2e40c8bfe856d2d1a203443b21b7eb92ecc35d6090ab44518d4d082a`,
bundle `42333e969028867ad8142335e6c1bc4040eec231de0d8d330c2d4b2cf7bc3442`). Two releases in one session, against "one
release per repo" — the first one was unsafe to deliver.
- `e4b5cf9` `scripts/build-step-bundle.py` (R-880, tooling). Step bundle `0.146.1-step1`, sha `8482851e…`.
## What changed
- **Exact sudo patterns** for every varying argument list (sudo regex `^…$`). Measured with real sudo 1.9.16: the
v0.145.0 sudoers allowed **23 of 29** attack lines; v0.146.1 allows **0** and still allows all **64** commands the
capability check uses (container, and live on both demo boxes).
- **`felhom-priv-apply`** (new root wrapper in the bundle) installs mount units, dnsmasq drop-ins, the WireGuard config
and the OOB sshd config + key only after checking the CONTENT against the agent's own renderers.
- **Fixed bundle files:** the guest pre-start hook and the shared drive parent (script + unit); the agent only checks
and registers / enables.
- **The signed update is checked as root:** `felhom-os-apply` mode `agent_update` (signature, host, window, nonce; the
staged bytes read once, hashed, copied to a root-owned dir); `felhom-selfupdate-guarded apply` left the agent's
sudoers and accepts only that root-owned dir.
- **The root escrow run** pins its paths, refuses a storage id that is a path, and reads its staged files by walking
the path with `openat(O_NOFOLLOW)`.
- **NFS/SMB options** gain `nosuid,nodev`.
## Tests
`go build/vet/test ./...` green; `configs/test_felhom_priv_apply.py` 32 tests, `test_felhom_config_bundle.py` (incl.
`AgentUpdate`, `SelfupdateWrapperConfinement`, `StepBundle`), `test_felhom_os_apply.py` green; Go contract tests feed each
renderer's real output to the checker (`internal/privapplytest`); `TestSudoersRefusesTheR861Injections`,
`TestManifestCoveredBySudoers` (regex-aware). Red-proofs F1–F9 and S1–S3: `partF/red-proof.txt` (F1's first run did NOT
convict — masked by the name rule — and the test was strengthened; F3's first run errored rather than failed — the test
now asserts cleanly).
## Delivered (signed jobs, key felhom-op-1)
Per box: `agent_update` 0.146.1 → `agent_config_update` 0.146.1-step1 → `agent_config_update` 0.146.1. See the session
report §5 for each box's result. Tester 2: offline (DOWN), nothing sent.
## Not done / open
- R-861 stays open, narrowed to three named residuals (`03` §3.1): the controller-swap image ref is guest-scoped; the
felhom-op SSH key is hub-delivered, unsigned (felhom-op's sudo is scoped); the escrow ceremony hands the agent R by
design.
- R-881: the installer's uninstall does not remove `felhom-priv-apply`.