v0.329.0: each app reaches only its own appdata folder; empty allow-list; drive retirement asks the agent first; plain no-durable-id refusal; :latest only for a release
gates / gates (push) Successful in 45s

R-1142: the HDD_PATH root is appdata/<own folder>, with a compiled-in folder map (paperless-ngx ->
paperless). R-981: the allow-list is empty (homepage's socket served no Felhom feature). R-1063:
finalizeDecommissionWith asks the agent before it marks the drive or moves the default; the 403/409
come back typed and reach the household as a plain 409. R-1069: the agent's no-durable-id format
refusal is ErrNoDurableID and a plain sentence. R-1143: build.sh carries :latest only for x.y.z.
Each pinned by a red-proofed test. MinAgent 0.158.1.
This commit is contained in:
2026-10-17 23:11:56 +02:00
parent 5d67041d6d
commit 2fe634141f
20 changed files with 504 additions and 78 deletions
+16 -23
View File
@@ -1,26 +1,19 @@
# REPORT — v0.328.0: the catalog allow-list (R-971, operator decision D2 = A) (2026-10-17)
# REPORT — controller v0.329.0 (night 2026-10-17 → 18)
Written in ASD-STE100 Simplified Technical English. Session report: felhom.eu `REPORT-agent-allowlist-rotation-2026-10-17.md`.
Evidence: felhom.eu `documentation/audits/agent-allowlist-rotation-2026-10-17/P2/`, `P5/`.
**In plain words.** Each app can now reach only its own data folder on the drive. Homepage no longer gets control of
Docker, so no app has a special right any more. When the host says „no" to retiring a drive, nothing changes on the
dashboard and the household reads why. A virtual disk that cannot be formatted gets a plain sentence instead of an
English error. Test builds no longer move the `:latest` tag. The full night report: felhom.eu
`REPORT-night-2026-10-18.md`.
- **What:** `internal/privpolicy` checks the RENDERED compose before every compose write and env decision (sync,
update/ladder step, install, two settings changes, two restores — before the stop) against `allowlist.json`
(go:embed; one entry: homepage's read-only socket, bound to its image, start and healthcheck). Refusal: nothing
written, operator event `app_definition_refused` (hub ≥ v0.157.0), app-page line, plain message. Sync never copies a
template named like an infra stack.
- **Tests:** `privpolicy_test.go` (every class, positive controls, the three review rounds, the live root finding),
`TestAllowList_IsWiredIntoEveryComposeWriter` (AST), `sync.TestR971_*`, `stacks.TestAllowList_*`,
`TestR971_AppPage_*`; full suite green on `99f9117`. Red-proofs in P2.
- **i18n:** new fixture `app_settings_definition_refused`; every other fixture byte-identical. Keys
`err.stacks.definition_refused`, `app_info.definition_refused` in both bundles.
- **Release:** rc.1–rc.5 on demo-hp 9201; 0.328.0 to Tester 1, demo-hp, demo-felhom by per-box floors (all three in
< 1 min), box walk green (0 refusals, all containers healthy, login and files 200), https-only green; global floor
0.328.0, MinAgent 0.158.1; per-box floors cleared; read back from the hub DB with its WAL.
- **9201 proof:** drill catalog with `privileged: true` on privatebin → refused; compose sha and container unchanged;
event at the hub + operator mail; page line on privatebin only; live catalog restored byte-identical.
| Row | What changed | Pinned by | Red-proof |
|---|---|---|---|
| R-1142 | `${HDD_PATH}` root = `appdata/<own folder>`; compiled-in map `paperless-ngx → paperless` | `TestAdmit_AnotherAppsAppdataFolderIsRefused`, `TestAllowList_AppdataFolderMustBeOneName` | root back at `appdata/` → 6 cases admitted |
| R-981 | allow-list EMPTY; homepage template has no socket (catalog) | `TestAllowList_HasNoExceptionAndRefusesHomepagesSocket` | old one-entry list → „1 entries" |
| R-1063 | agent asked first; 403/409 → plain 409, nothing changed | `TestFinalizeDecommission_AgentRefusalChangesNothing`, `TestDecommission_PolicyRefusalsAreTyped` | old order → drive marked, default moved |
| R-1069 | agent's no-durable-id refusal → `disk.err.no_durable_id` | `TestR1069_NoDurableIDIsAPlainRefusal`, `TestFormatDisk_NoDurableIDIsTyped` | branch removed → raw text reaches the household |
| R-1143 | `:latest` only for x.y.z | `scripts/test_build_push_once.sh` (16 cases) | every build adds `:latest` → 4 cases fail |
## Observations
1. rc.4 refused every not-installed app on the box (placeholder roots do not exist there). NOT-A-FINDING: found by this session's own live proof and fixed in rc.5 before the release, red-proved.
2. One app can still bind another app's `appdata/<name>`. FILED: R-1142.
3. `build.sh` pushes `:latest` with every build, rc included. FILED: R-1143.
Red-proof records: felhom.eu `documentation/audits/night-2026-10-18/P1/redproof-*.txt`. Green gate rc=0;
`controller_gates.py --fast` rc=0 (golden-notice advisory). i18n: three keys born as keys; every page fixture
byte-identical. MinAgent 0.158.1. Release path and box walk: the night report.