From d83316326e0991e7a34621414388609e6b3941fb Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Mon, 5 Oct 2026 16:56:18 +0200 Subject: [PATCH] R-291 retention record source, R-348 restart comment (no binary change; burn-down) Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS --- CHANGELOG.md | 8 +++++ REPORT.md | 55 ++++------------------------------- internal/backup/store.go | 6 +++- scripts/retention-policy.json | 17 +++++------ 4 files changed, 25 insertions(+), 61 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b636914..b2da8a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## unreleased — comments and the retention record only, no binary change (burn-down 2026-10-05: R-291, R-348) + +- **R-291:** `scripts/retention-policy.json` names where its 10 comes from — the R-267 newest-10 prune of generic + packages, established 2026-08-10 (R-287) — instead of „observed, no located ruling"; the non-existent + `registry-retention.md` reader is dropped. `check-published-versions.py` still reads 10 (checked). +- **R-348:** `internal/backup/store.go` no longer says backups are „unaffected" by a restart: the reported backup list + reads 0 until the next backup runs; only the hub's verdict (7-day look-back) is unaffected. + ## v0.146.1 — R-861 review fixes: the signed update flips a root-owned copy; no Wants=/continuations in mount units; the escrow read follows no symlink anywhere (2026-10-05) Released by `scripts/release-agent.sh`: binary sha256 `badd6c9a2e40c8bfe856d2d1a203443b21b7eb92ecc35d6090ab44518d4d082a`, diff --git a/REPORT.md b/REPORT.md index ef8709a..c682568 100644 --- a/REPORT.md +++ b/REPORT.md @@ -1,52 +1,7 @@ -# REPORT — agent v0.146.0 / v0.146.1: the agent's root grants narrowed (R-861), the step bundle (R-880) — 2026-10-05 +# REPORT — 2026-10-05 burn-down: two record corrections (no release) -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/`. +Full session report: `felhom.eu/REPORT-burndown-2026-10-05.md`. Baseline `e06ed97` (v0.146.1). No binary, bundle or +version change; `go build`, `go vet ./internal/backup/`, `agent_gates.py --fast` green. -## Baseline and commits - -- 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`. +- R-291 — `scripts/retention-policy.json`: the source of the number (R-267 newest-10 prune, R-287) and readers corrected. +- R-348 — `internal/backup/store.go`: the restart comment says what a restart really blanks. diff --git a/internal/backup/store.go b/internal/backup/store.go index 8b4de60..7271ed3 100644 --- a/internal/backup/store.go +++ b/internal/backup/store.go @@ -25,7 +25,11 @@ import ( // merges the two — see hub.ProvenRestoreTestReporter. This store remains the ONLY place a FAILURE is // recorded, and that asymmetry is deliberate: a failing tier stays due and is retried, so a lost // failure heals itself, while a lost success leaves the system quietly less tested than it believes. -// Backups are unaffected — their freshness has a ground truth on the storage (R-84). +// Backups are NOT unaffected (corrected 2026-10-05, R-348): byTarget is in memory too, so after a restart the +// reported backup LIST reads 0 until the next backup of each tier runs (daily local, weekly offsite) — measured +// 2026-08-20, two consecutive host-reports with `0 backups` while `pvesm list` showed archives on both tiers. What +// is unaffected is the hub's VERDICT: it looks back 7 days over stored reports (felhom.eu hub/internal/monitor/ +// deadline.go backupEvidenceLookback) and the storage stays the ground truth (R-84). type Store struct { mu sync.Mutex byTarget map[string]hub.Backup // latest backup per target id diff --git a/scripts/retention-policy.json b/scripts/retention-policy.json index b9a9657..f15c515 100644 --- a/scripts/retention-policy.json +++ b/scripts/retention-policy.json @@ -10,13 +10,11 @@ "CI went red at a commit whose own run had been green the day before, on a true finding that", "no one could act on. The red will return at the next publish unless the two read one number.", "", - "HOW THE NUMBER WAS ARRIVED AT — stated honestly, because it is weaker than it looks.", - "generic_versions_kept is 10 because that is what the registry demonstrably holds today", - "(felhom-agent 0.121.0..0.128.0 = 10 versions, queried 2026-08-09). It is an OBSERVED state,", - "NOT a ruling anyone has been able to locate: no register row records a package prune, R-210", - "is WAITING-ON-OPERATOR and says 'Nothing was deleted; this is a list, not an action', and it", - "concerns local Docker images rather than this registry. Container packages currently hold 19", - "each, so there is no uniform ten-per-package cap visible either. See R-287.", + "HOW THE NUMBER WAS ARRIVED AT. generic_versions_kept is 10 because that is what the registry", + "keeps: the deleter was ESTABLISHED on 2026-08-10 (R-287) — the newest-10 prune of generic packages", + "run under R-267 (felhom-agent and felhom-golden generic held exactly 10 afterwards). Until then this", + "file called the 10 an observed state with no located ruling; that is superseded (corrected", + "2026-10-05, R-291). Container packages are not pruned by that rule.", "", "SO THIS FILE IS A FLOOR, NOT A LICENCE. It says: CI may assume nothing older than the newest", "N generic versions is still downloadable. It does NOT authorise deleting anything, and the", @@ -36,9 +34,8 @@ ], "generic_versions_kept": 10, "readers": [ - "scripts/check-published-versions.py — bounds its assertion to the newest N versions", - "documentation/runbooks/registry-retention.md (felhom.eu) — the prune procedure" + "scripts/check-published-versions.py — bounds its assertion to the newest N versions" ], "recorded": "2026-08-09", - "recorded_by": "CC, from the registry's observed state; NOT from a located operator ruling" + "recorded_by": "CC 2026-08-09; the number's source (the R-267 newest-10 prune, established 2026-08-10 by R-287) recorded 2026-10-05 (R-291)" }