diff --git a/CONTEXT.md b/CONTEXT.md index 77c69188..2c89d254 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -16,6 +16,20 @@ > and holds nothing of its own; this file does hold its own content, namely the standing rulings below. +> **2026-10-27 night (attended to 22:40, then alone) — D60, the runtime watch, HTTP2Shell.** **Decided by CC unattended +> — operator may reverse:** (1) Home Assistant's monthly release is the same main version (one comparator) → a LANE step +> with CVE-2026-111497 (`09` §3 decision 276); (2) the watch's runtime cache is filled on DooPlex (zstd, the stored Docker +> Hub login through `sec run`) and committed in `state.json`, instead of a zstd dependency in CI (`08` §11); (3) no +> Paperless step (it decodes only replies to its own calls, R-1331); (4) RomM kept (STATUS D61, R-1330); (5) the live +> catalog changes stay PATCHES/drill commits at night — the push waits for the operator. **Done:** D60 enforced +> (cc-secrets 0.4.0 `092e282` + two review hardenings `27fd806`/`e99f937`; proven in two new CC sessions); D56–D59 +> recorded (decisions 271–275); hub `startupProbe` 180 s live on the operator's yes (`a69ddbde`, one start, 0 restarts; +> R-1326 closed); `scripts/image_runtime.py` + the watch's „runtime" source and „dooplex" group (`f5a4995d`; 154 images +> cached; positive controls HA + RomM, negative audiobookshelf); ghcr.io tag paging fixed; lane walks PROVEN on 9202 and +> written to the DRILL: Home Assistant 2026.9.4 → 2026.10.4 (`3c8ebb5`), Immich v3.2.4 → v3.3.5 (`34b14d5`); Wanderer +> hidden in the drill (`ee18bff`). Rows R-1327–R-1332 opened, R-1326 closed. Morning: the catalog push (writer on the +> live catalog), the homelab list to the homelab session. + > **2026-10-27 evening — R-1299 the clean-up window button (hub v0.174.0 + v0.174.1); cc-secrets 0.3.0 `sec rm`.** The > customer page's „Backup & DR" tab has the „Off-site clean-up window" card (`internal/web/offsite_window.go`): the > one-shot grant through a confirm step, same route and rule (`/offsite/window-grant/`, `wr(grpOffsite)`), cancel, diff --git a/STATUS.md b/STATUS.md index 2b8f2366..c211962e 100644 --- a/STATUS.md +++ b/STATUS.md @@ -2,7 +2,7 @@ **Ready for Tester 2? Yes — tell the friend go (hand-over list: `documentation/pilot/TESTER2-handover.md`).** -**Updated 2026-10-27 (evening).** On your yes: 14 apps got a tested security step, and Wishlist, Bookstack and Jellyfin a normal step; boxes take them tonight. Every box runs controller 0.346.1 with the new Traefik, file manager and cloudflared. Ten apps need a bigger step, a row each (R-1311, R-1313, R-1315–R-1322); no household runs them. +**Updated 2026-10-28 (night).** CC cannot delete from its secret store any more (D60). The watch now reads the Node and Brotli inside every image: 20 catalog apps carry HTTP2Shell; Home Assistant and Immich have tested steps waiting for your yes. The hub has 3 minutes to start. ## What works - **The Plex attack (10-17 → 10-23) did not reach Felhom's secrets** (R-1241). @@ -32,6 +32,7 @@ Newest first. CC's pick is in the „Pick" column. Each row also has its full te | # | Row | Question | Pick (why) | The other option costs | If you do nothing | Blocked | |---|---|---|---|---|---|---| +| D61 | R-1330 | RomM: keep it offered while its newest release still has the bad Node inside? Node does not run in RomM, and the setup gate is in front. | **Keep it** (no fixed release exists; the watch flags it nightly) | hide it: it leaves the catalog until RomM ships a fix | it stays offered | — | | D38 | R-1235 | Put the newest golden (637 MB) into the nightly release copy on ep0 too? | **Yes** (a new install after a DooPlex loss needs it; it fits under the 3 GB cap) | leave it out: after a loss, no new install until a golden is rebuilt and vouched | the same | — | | D37 | R-1236 | Raise Gitea's memory limit from 1 GiB to 2 GiB? It was killed for memory 4 times in 17 days, once during today's release. | **Yes** (DooPlex has the RAM; a DooPlex change, so yours) | keep 1 GiB: a restart in release hours fails box updates and CI for a minute | the same | — | | D9 | R-1062 | Split the N100's USB drive in two, for multi-drive tests? | **No — keep one drive** (the lived-in box keeps its nightly whole-box backup) | Split: the box loses its local whole-box backup, or you buy a second drive first | it stays one drive; multi-drive tests stay on Tester 1 | — | @@ -48,7 +49,7 @@ Newest first. CC's pick is in the „Pick" column. Each row also has its full te 6. BIOS: on the N100, read „After Power Loss"; on the HP, set „Bypass F1 Prompt on Configuration Changes" to Enable. (since 10-14) 7. Pin the first Facebook post (R-917), and look at the new cover in the Facebook phone app (R-919). (since 10-12) -**2026-10-27.** Done today: agent 0.167.0 vouched, the D55 token revoked, `Tester4-b5dbbd` deleted. New: a nightly security watch mails you (R-1303). +**2026-10-28 morning.** 1. Yes for the catalog push: Home Assistant and Immich (tested steps), Wanderer hidden (R-1313). If not: both keep the bad code; Wanderer stays offered. 2. Give the homelab session `audits/http2shell-2026-10-27/HOMELAB-LIST.md` (19 images, R-1328). 3. A removed store name back: `git revert` in your terminal (cc-secrets REPORT). **2026-10-23 do list.** 1. Print the break-glass sheet (`documentation/runbooks/break-glass-sheet.md`, the part from „The sheet”, one A4), fill it by hand, keep it outside the home (D32; R-923, R-924). If not: after a DooPlex loss no off-site copy opens. 2. On the hub's Hosts page: Discard appliance 49. If not: a dead entry alarms. diff --git a/documentation/audits/http2shell-2026-10-27/walks/immich/box-verdict-immich.json b/documentation/audits/http2shell-2026-10-27/walks/immich/box-verdict-immich.json new file mode 100644 index 00000000..873e282a --- /dev/null +++ b/documentation/audits/http2shell-2026-10-27/walks/immich/box-verdict-immich.json @@ -0,0 +1,313 @@ +{ + "app": "immich", + "walk": "security", + "box_walk_version": 1, + "verdict": "proven", + "venue": "box 9202 (drill catalog), the guarded Update", + "from": { + "immich-server": "ghcr.io/immich-app/immich-server:v3.2.4", + "immich-machine-learning": "ghcr.io/immich-app/immich-machine-learning:v3.2.4", + "immich-postgres": "ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0", + "immich-redis": "redis:7-alpine" + }, + "to": { + "immich-server": "ghcr.io/immich-app/immich-server:v3.3.5", + "immich-machine-learning": "ghcr.io/immich-app/immich-machine-learning:v3.3.5", + "immich-postgres": "ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0", + "immich-redis": "redis:7-alpine" + }, + "observables_before": { + "pinned_images": { + "immich-machine-learning": "ghcr.io/immich-app/immich-machine-learning:v3.2.4", + "immich-postgres": "ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0", + "immich-redis": "redis:7-alpine", + "immich-server": "ghcr.io/immich-app/immich-server:v3.2.4" + }, + "installed_images": { + "immich-machine-learning": "ghcr.io/immich-app/immich-machine-learning:v3.2.4", + "immich-postgres": "ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0", + "immich-redis": "redis:7-alpine", + "immich-server": "ghcr.io/immich-app/immich-server:v3.2.4" + }, + "catalog_images": null, + "live_compose_image_lines": [ + "image: ghcr.io/immich-app/immich-server:v3.2.4@sha256:d317916b28090c33eb36b308464ea391f8b7df1d850fcfea227a39ec879718c2", + "image: ghcr.io/immich-app/immich-machine-learning:v3.2.4@sha256:e16c2f166a8174901959fdf85e2e4c7bd1ebc4b37e0b6655de97c41408a260c4", + "image: ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0@sha256:1a078b237c1d9b420b0ee59147386b4aa60d3a07a8e6a402fc84a57e41b043a4", + "image: redis:7-alpine@sha256:858f009f9709ce576febc734aa78b8f6d624b82571f9ddb6bda4377c833b3499" + ], + "docker_inspect": [ + "immich-server ghcr.io/immich-app/immich-server:v3.2.4@sha256:d317916b28090c33eb36b308464ea391f8b7df1d850fcfea227a39ec879718c2 running=true restarts=0", + "immich-postgres ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0@sha256:1a078b237c1d9b420b0ee59147386b4aa60d3a07a8e6a402fc84a57e41b043a4 running=true restarts=0", + "immich-machine-learning ghcr.io/immich-app/immich-machine-learning:v3.2.4@sha256:e16c2f166a8174901959fdf85e2e4c7bd1ebc4b37e0b6655de97c41408a260c4 running=true restarts=0", + "immich-redis redis:7-alpine@sha256:858f009f9709ce576febc734aa78b8f6d624b82571f9ddb6bda4377c833b3499 running=true restarts=0" + ] + }, + "setup_gate_before": { + "browser": { + "status": "302", + "redirect": "https://felhom.enkisfelhom.hu/__gate/start?…" + }, + "script": { + "status": "401", + "redirect": null + } + }, + "seed": "read_back", + "drill_commit": "d992f141bbb3", + "sync_waited_s": 4.5, + "badge_before": { + "hu": [ + { + "title": "Újabb változat érhető el ehhez az alkalmazáshoz. A frissítés indításához nyomd meg a Frissítés gombot.", + "text": "Frissítés elérhető — ma" + } + ], + "en": [ + { + "title": "A newer version of this app is available. Select the Update button to start it.", + "text": "Update available — today" + } + ] + }, + "measured_at": "2026-10-27T22:17:33Z", + "update": { + "accepted": true, + "http": "202", + "phases": [ + { + "t": 0.0, + "phase": "backing-up", + "label": "Biztonsági mentés készül a frissítés előtt…", + "updating": true, + "error": null, + "hold": null + }, + { + "t": 20.5, + "phase": "safety-dump", + "label": "Adatbázis pillanatkép…", + "updating": true, + "error": null, + "hold": null + }, + { + "t": 22.5, + "phase": "pulling", + "label": "Új verzió letöltése…", + "updating": true, + "error": null, + "hold": null + }, + { + "t": 85.0, + "phase": "copying", + "label": "Az adatok másolása a frissítés előtt…", + "updating": true, + "error": null, + "hold": null + }, + { + "t": 94.2, + "phase": "starting", + "label": "Indítás az új verzióval…", + "updating": true, + "error": null, + "hold": null + }, + { + "t": 105.5, + "phase": "verifying", + "label": "Működés ellenőrzése…", + "updating": true, + "error": null, + "hold": null + }, + { + "t": 121.9, + "phase": "done", + "label": "Frissítve", + "updating": false, + "error": null, + "hold": null + } + ], + "duration_s": 121.9, + "final_phase": "done", + "update_error": null, + "hold_reason": null, + "state": "running" + }, + "observables_after": { + "pinned_images": { + "immich-machine-learning": "ghcr.io/immich-app/immich-machine-learning:v3.3.5", + "immich-postgres": "ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0", + "immich-redis": "redis:7-alpine", + "immich-server": "ghcr.io/immich-app/immich-server:v3.3.5" + }, + "installed_images": { + "immich-machine-learning": "ghcr.io/immich-app/immich-machine-learning:v3.3.5", + "immich-postgres": "ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0", + "immich-redis": "redis:7-alpine", + "immich-server": "ghcr.io/immich-app/immich-server:v3.3.5" + }, + "catalog_images": { + "immich-machine-learning": "ghcr.io/immich-app/immich-machine-learning:v3.3.5", + "immich-postgres": "ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0", + "immich-redis": "redis:7-alpine", + "immich-server": "ghcr.io/immich-app/immich-server:v3.3.5" + }, + "live_compose_image_lines": [ + "image: ghcr.io/immich-app/immich-server:v3.3.5", + "image: ghcr.io/immich-app/immich-machine-learning:v3.3.5", + "image: ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0", + "image: redis:7-alpine" + ], + "docker_inspect": [ + "immich-server ghcr.io/immich-app/immich-server:v3.3.5 running=true restarts=0", + "immich-postgres ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0 running=true restarts=0", + "immich-machine-learning ghcr.io/immich-app/immich-machine-learning:v3.3.5 running=true restarts=0", + "immich-redis redis:7-alpine running=true restarts=0" + ] + }, + "badge_after": { + "hu": [ + { + "title": "Ez az alkalmazás a legfrissebb elérhető változatot futtatja.", + "text": "Naprakész" + } + ], + "en": [ + { + "title": "This app is running the newest version available.", + "text": "Up to date" + } + ] + }, + "state_after": "running", + "hold_after": null, + "to_digests": { + "immich-server": "sha256:485d546a2e31d6a8b4db8423fcba5c109de8c218d93410af115fd1ccfc4352a6", + "immich-machine-learning": "sha256:5b28c9352c8374b8a1ed96fbdd8d6755fea6e43510ec43fdf6538aa02ea40f56", + "immich-postgres": "sha256:1a078b237c1d9b420b0ee59147386b4aa60d3a07a8e6a402fc84a57e41b043a4", + "immich-redis": "sha256:6ba19c50b56777f5c11c58eff8ddb69d0d5f27ba131cffb63f180ccfd43c66af" + }, + "four_observables": { + "pinned": { + "immich-machine-learning": "ghcr.io/immich-app/immich-machine-learning:v3.3.5", + "immich-postgres": "ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0", + "immich-redis": "redis:7-alpine", + "immich-server": "ghcr.io/immich-app/immich-server:v3.3.5" + }, + "installed": { + "immich-machine-learning": "ghcr.io/immich-app/immich-machine-learning:v3.3.5", + "immich-postgres": "ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0", + "immich-redis": "redis:7-alpine", + "immich-server": "ghcr.io/immich-app/immich-server:v3.3.5" + }, + "catalog": { + "immich-machine-learning": "ghcr.io/immich-app/immich-machine-learning:v3.3.5", + "immich-postgres": "ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0", + "immich-redis": "redis:7-alpine", + "immich-server": "ghcr.io/immich-app/immich-server:v3.3.5" + }, + "live_compose": [ + "ghcr.io/immich-app/immich-machine-learning:v3.3.5", + "ghcr.io/immich-app/immich-server:v3.3.5", + "ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0", + "redis:7-alpine" + ] + }, + "seed_read_after": true, + "setup_gate_after": { + "browser": { + "status": "200", + "redirect": null + }, + "script": { + "status": "200", + "redirect": null + } + }, + "memory": { + "soak_s": 600, + "interval_s": 10, + "samples": 228, + "containers": { + "immich-server": { + "samples": 57, + "anon_peak_bytes": 1359732736, + "limit_bytes": 3221225472, + "anon_peak_pct": 42.2, + "cgroup_peak_pct": 49.7, + "oom_kill_delta": 0, + "oom_killed_flag": false, + "restarts_delta": 0, + "running_all_samples": true, + "cgroup": "/sys/fs/cgroup/system.slice/docker-1494b4cdbecfdc28139124c97ae25f995d6619fcbe13f6c1469e917a18bcc896.scope" + }, + "immich-postgres": { + "samples": 57, + "anon_peak_bytes": 201875456, + "limit_bytes": 805306368, + "anon_peak_pct": 25.1, + "cgroup_peak_pct": 94.7, + "oom_kill_delta": 0, + "oom_killed_flag": false, + "restarts_delta": 0, + "running_all_samples": true, + "cgroup": "/sys/fs/cgroup/system.slice/docker-8a943f33c7cd70898b9668e2922e71cf04a8f88bd67d0e0c0d3d6e8f7bbab489.scope" + }, + "immich-machine-learning": { + "samples": 57, + "anon_peak_bytes": 243011584, + "limit_bytes": 2147483648, + "anon_peak_pct": 11.3, + "cgroup_peak_pct": 12.6, + "oom_kill_delta": 0, + "oom_killed_flag": false, + "restarts_delta": 0, + "running_all_samples": true, + "cgroup": "/sys/fs/cgroup/system.slice/docker-ad472ac57c05e6391116441682d0b1b3fe1b6f5908b5769e87d2931e729a6f35.scope" + }, + "immich-redis": { + "samples": 57, + "anon_peak_bytes": 6139904, + "limit_bytes": 134217728, + "anon_peak_pct": 4.6, + "cgroup_peak_pct": 16.9, + "oom_kill_delta": 0, + "oom_killed_flag": false, + "restarts_delta": 0, + "running_all_samples": true, + "cgroup": "/sys/fs/cgroup/system.slice/docker-b7c6711034b950f1d086fbbb8f2613c7777dc17d7f9986d07c231d10f735d174.scope" + } + }, + "oom_kills": 0, + "restarts": 0, + "peak_pct": 42.2 + }, + "why": "the security-fix step ran on the box through the guarded Update; healthy, TO on all four observables, no undo, no hold, a clean soak, seed read back", + "log": [ + "23:15:29 [1] required fields filled beyond DOMAIN/SUBDOMAIN: ['HDD_PATH']", + "23:15:29 [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'}", + "23:17:15 [1] deployed, controller state=running, pinned={'immich-machine-learning': 'ghcr.io/immich-app/immich-machine-learning:v3.2.4', 'immich-postgres': 'ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0', 'immich-redis': 'redis:7-alpine', 'immich-server': 'ghcr.io/immich-app/immich-server:v3.2.4'}", + "23:17:15 gate: photos is gated — passed as the household (cookie set)", + "23:17:18 [2] setup gate as installed: {'browser': {'status': '302', 'redirect': 'https://felhom.enkisfelhom.hu/__gate/start?…'}, 'script': {'status': '401', 'redirect': None}}", + "23:17:19 immich: seeded album drillalbum0382044e", + "23:17:19 immich: readback found=True (http 200, control passed)", + "23:17:20 [5] drill commit d992f141bbb3: immich ghcr.io/immich-app/immich-machine-learning:v3.2.4,ghcr.io/immich-app/immich-server:v3.2.4 -> ghcr.io/immich-app/immich-machine-learning:v3.3.5,ghcr.io/immich-app/immich-server:v3.3.5 (push rc=0)", + "23:17:29 [5] the box's drill mirror now at d992f141", + "23:17:34 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'}", + "23:17:34 + 0.0s phase=backing-up label=Biztonsági mentés készül a frissítés előtt… err=None hold=None", + "23:17:54 + 20.5s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None", + "23:17:56 + 22.5s phase=pulling label=Új verzió letöltése… err=None hold=None", + "23:18:59 + 85.0s phase=copying label=Az adatok másolása a frissítés előtt… err=None hold=None", + "23:19:08 + 94.2s phase=starting label=Indítás az új verzióval… err=None hold=None", + "23:19:19 + 105.5s phase=verifying label=Működés ellenőrzése… err=None hold=None", + "23:19:36 + 121.9s phase=done label=Frissítve err=None hold=None", + "23:19:55 immich: readback found=True (http 200, control passed)", + "23:19:55 [7] memory soak 600 s …", + "23:30:03 [7] soak: peak 42.2% of the limit (anon), kills 0, restarts 0" + ] +} \ No newline at end of file diff --git a/documentation/audits/http2shell-2026-10-27/walks/immich/immich-leftover-remove.txt b/documentation/audits/http2shell-2026-10-27/walks/immich/immich-leftover-remove.txt new file mode 100644 index 00000000..c354e4b1 --- /dev/null +++ b/documentation/audits/http2shell-2026-10-27/walks/immich/immich-leftover-remove.txt @@ -0,0 +1,11 @@ +before: deployed=True state=running pins={'immich-machine-learning': 'ghcr.io/immich-app/immich-machine-learning:v3.2.4', 'immich-postgres': 'ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0', 'immich-redis': 'redis:7-alpine', 'immich-server': 'ghcr.io/immich-app/immich-server:v3.2.4'} +23:14:23 [X] stop -> 200 {'ok': True, 'message': 'Stack immich stop completed'} +23:14:28 [X] remove (with drive data) -> 409 {'ok': False, 'error': 'A(z) /mnt/sizing-bench tárhely jelenleg nem elérhető — az alkalmazás nem távolítható el, amíg a meghajtó vissza nem csatlakozik.'} +23:14:28 [X] refused because the drive path cannot be resolved (R-442, fail-closed and right) — removing the app and KEEPING the drive data instead +23:14:56 [X] remove (keeping drive data) -> 200 {'ok': True, 'data': {'removed': 'immich', 'volumes_removed': ['immich_immich_ml_cache', 'immich_immich_postgres_data', 'immich_immich_redis_data'], 'hdd_paths_ +23:15:05 [X] after remove: deployed=False leftovers='' +after: deployed=False +leftovers: 0 +ls: cannot access '/opt/docker/stacks/immich/app.yaml': No such file or directory +0 + diff --git a/documentation/audits/http2shell-2026-10-27/walks/immich/walk.txt b/documentation/audits/http2shell-2026-10-27/walks/immich/walk.txt new file mode 100644 index 00000000..630da8c5 --- /dev/null +++ b/documentation/audits/http2shell-2026-10-27/walks/immich/walk.txt @@ -0,0 +1,25 @@ +23:15:29 [1] required fields filled beyond DOMAIN/SUBDOMAIN: ['HDD_PATH'] +23:15:29 [1] deploy -> 202 {'ok': True, 'message': 'Telepítés elindítva – az állapot a kártyán követhető'} +23:17:15 [1] deployed, controller state=running, pinned={'immich-machine-learning': 'ghcr.io/immich-app/immich-machine-learning:v3.2.4', 'immich-postgres': 'ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0', 'immich-redis': 'redis:7-alpine', 'immich-server': 'ghcr.io/immich-app/immich-server:v3.2.4'} +23:17:15 gate: photos is gated — passed as the household (cookie set) +23:17:18 [2] setup gate as installed: {'browser': {'status': '302', 'redirect': 'https://felhom.enkisfelhom.hu/__gate/start?…'}, 'script': {'status': '401', 'redirect': None}} +23:17:19 immich: seeded album drillalbum0382044e +23:17:19 immich: readback found=True (http 200, control passed) +23:17:20 [5] drill commit d992f141bbb3: immich ghcr.io/immich-app/immich-machine-learning:v3.2.4,ghcr.io/immich-app/immich-server:v3.2.4 -> ghcr.io/immich-app/immich-machine-learning:v3.3.5,ghcr.io/immich-app/immich-server:v3.3.5 (push rc=0) +23:17:29 [5] the box's drill mirror now at d992f141 +23:17:34 [6] Update -> 202 {'ok': True, 'data': {'accepted': True, 'completed': False}, 'message': 'Frissítés elindult – az állapot a kártyán követhető'} +23:17:34 + 0.0s phase=backing-up label=Biztonsági mentés készül a frissítés előtt… err=None hold=None +23:17:54 + 20.5s phase=safety-dump label=Adatbázis pillanatkép… err=None hold=None +23:17:56 + 22.5s phase=pulling label=Új verzió letöltése… err=None hold=None +23:18:59 + 85.0s phase=copying label=Az adatok másolása a frissítés előtt… err=None hold=None +23:19:08 + 94.2s phase=starting label=Indítás az új verzióval… err=None hold=None +23:19:19 + 105.5s phase=verifying label=Működés ellenőrzése… err=None hold=None +23:19:36 + 121.9s phase=done label=Frissítve err=None hold=None +23:19:55 immich: readback found=True (http 200, control passed) +23:19:55 [7] memory soak 600 s … +23:30:03 [7] soak: peak 42.2% of the limit (anon), kills 0, restarts 0 +23:30:03 [9] verdict proven -> /tmp/claude-1000/-mnt-5-hdd-felhom-eu-git/0b76c4d7-9b39-4e4e-869d-d0d2c6006331/scratchpad/p2ev/immich/verdict.json +23:30:03 RESULT proven — the security-fix step ran on the box through the guarded Update; healthy, TO on all four observables, no undo, no hold, a clean soak, seed read back +23:30:04 [X] stop -> 200 {'ok': True, 'message': 'Stack immich stop completed'} +23:30:36 [X] remove (with drive data) -> 200 {'ok': True, 'data': {'removed': 'immich', 'volumes_removed': ['immich_immich_ml_cache', 'immich_immich_postgres_data'], 'hdd_paths_removed': ['/mnt/felhom-driv +23:30:44 [X] after remove: deployed=False leftovers='' diff --git a/documentation/audits/http2shell-2026-10-27/walks/immich/writer-drill.txt b/documentation/audits/http2shell-2026-10-27/walks/immich/writer-drill.txt new file mode 100644 index 00000000..8cef04ad --- /dev/null +++ b/documentation/audits/http2shell-2026-10-27/walks/immich/writer-drill.txt @@ -0,0 +1,3 @@ +STEP immich: the superseded step {'immich-server': 'ghcr.io/immich-app/immich-server:v3.2.4', 'immich-machine-learning': 'ghcr.io/immich-app/immich-machine-learning:v3.2.4', 'immich-postgres': 'ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0', 'immich-redis': 'redis:7-alpine'} keeps its definition at steps/6e2f0f71608351ad.yml +STEP immich: … and its .felhom.yml at steps/6e2f0f71608351ad.felhom.yml +WROTE immich: {'immich-server': 'ghcr.io/immich-app/immich-server:v3.2.4', 'immich-machine-learning': 'ghcr.io/immich-app/immich-machine-learning:v3.2.4', 'immich-postgres': 'ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0', 'immich-redis': 'redis:7-alpine'} -> {'immich-server': 'ghcr.io/immich-app/immich-server:v3.3.5', 'immich-machine-learning': 'ghcr.io/immich-app/immich-machine-learning:v3.3.5', 'immich-postgres': 'ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0', 'immich-redis': 'redis:7-alpine'} peak 42.2% marks {'files_may_change': False, 'needs_person': None, 'memory_tight': False} diff --git a/documentation/backlog/OPEN-ITEMS.md b/documentation/backlog/OPEN-ITEMS.md index 3aaef922..c0faaf5e 100644 --- a/documentation/backlog/OPEN-ITEMS.md +++ b/documentation/backlog/OPEN-ITEMS.md @@ -157,7 +157,7 @@ stopping line that lies. | ID | Category | Sev | What | State | Blocked on | Next action | Owner | |---|---|---|---|---|---|---|---| -| **R-1313** | App updates | P2 | **Wanderer (v0.20.0): a critical notice with no login — any remote ActivityPub server can overwrite its records (GHSA-fprh-3pp9-68m9), and federation has no off switch; the fix is v0.21.2, a big step.** v0.21 adds a REQUIRED `POCKETBASE_PROXY_SECRET` on both services, its migration shortens rich text with no way back, and upstream wants PocketBase closed while our template publishes it on `SUBDOMAIN_DB`. No box runs Wanderer (hub 2026-10-27). `audits/security-app-updates-2026-10-27/TRIAGE.md`, `PICKS.md` pick 4 | OPEN — **RULED D59 = hide from new installs until the big step** (operator 2026-10-27 21:33, `09` §3 decision 275) — the catalog change is drilled with tonight's steps; its live push waits for the operator's yes. — filed 2026-10-27 (security app updates, Part 3: not done today) | the operator's pick 4 (hide it from new installs, or leave it offered) | the big step v0.21.2 with a new fixture field and a closed PocketBase: bench + 9202 + the undo proven, then a STOP | CC | +| **R-1313** | App updates | P2 | **Wanderer (v0.20.0): a critical notice with no login — any remote ActivityPub server can overwrite its records (GHSA-fprh-3pp9-68m9), and federation has no off switch; the fix is v0.21.2, a big step.** v0.21 adds a REQUIRED `POCKETBASE_PROXY_SECRET` on both services, its migration shortens rich text with no way back, and upstream wants PocketBase closed while our template publishes it on `SUBDOMAIN_DB`. No box runs Wanderer (hub 2026-10-27). `audits/security-app-updates-2026-10-27/TRIAGE.md`, `PICKS.md` pick 4 | **VERIFY** — 2026-10-27 night: D59 made in the DRILL (`ee18bff`, `lifecycle: hidden`) and read back on 9202 through the controller's API (`lifecycle: hidden`; Bookstack as the control: not set); the live change is `audits/http2shell-2026-10-27/wanderer-hidden.patch`, waiting for the operator's yes. **Earlier:** OPEN — **RULED D59 = hide from new installs until the big step** (operator 2026-10-27 21:33, `09` §3 decision 275) — the catalog change is drilled with tonight's steps; its live push waits for the operator's yes. — filed 2026-10-27 (security app updates, Part 3: not done today) | the operator's pick 4 (hide it from new installs, or leave it offered) | the big step v0.21.2 with a new fixture field and a closed PocketBase: bench + 9202 + the undo proven, then a STOP | CC | | **R-1315** | App updates | P2 | **Gitea 1.27.3: two critical notices for any signed-in user (7cq7, 6pv5) and two with no login (c3cr, hf55); the fix is 28.2.0 (1.28 was renamed 28.0.0 — no 1.27.4 exists).** 28.0 routes git traffic through a new proxy with egress settings. GHSA-rqhx (SSRF through migration) has no fix at all (`PICKS.md` pick 2). No box runs Gitea. `audits/security-app-updates-2026-10-27/TRIAGE.md` | OPEN — **RULED D57 = keep repository import on** (operator 2026-10-27 21:33, `09` §3 decision 273) — judged again in the big step. — filed 2026-10-27 (security app updates, Part 3: not done today) | — | the big step 28.2.0: read the 28.0 proxy settings against our template; bench + 9202 + undo; a STOP | CC | | **R-1316** | App updates | P3 | **Gokapi v1.9.6: GHSA-3c22 (high, self-XSS for the only account); the fix is v2.x, a big step** — a user system with no downgrade, and our first-boot config seed must be captured again. No box runs Gokapi. `audits/security-app-updates-2026-10-27/TRIAGE.md` | OPEN — filed 2026-10-27 (security app updates, Part 3: not done today) | — | the big step v2.2.4 with a new first-boot seed; bench + 9202 + undo; a STOP | CC | | **R-1317** | App updates | P3 | **Seerr (jellyseerr 2.7.3): GHSA-rc4w (a stranger registers, Plex setups only) and GHSA-mc6w (path traversal to code execution, needs a hostile media server); the fix is `ghcr.io/seerr-team/seerr:v3.5.1`, a big step** — a new image name, runs as UID 1000 (`/app/config` must be chowned), a config migration. No box runs it. `audits/security-app-updates-2026-10-27/TRIAGE.md` | OPEN — filed 2026-10-27 (security app updates, Part 3: not done today) | — | the big step to seerr v3.5.1: the ownership step, the image rename; bench + 9202 + undo; a STOP | CC | @@ -165,7 +165,7 @@ stopping line that lies. | **R-1319** | App updates | P3 | **Paperless-ngx 2.20.15: GHSA-2jhj (low; needs a setting we do not set — not reachable); the fix is 3.3.4, a big step** (encryption and API v1 removed, the search index rebuilt). It runs on all four test boxes. Not urgent. `audits/security-app-updates-2026-10-27/TRIAGE.md` | OPEN — filed 2026-10-27 (security app updates, Part 3: not done today) | — | the big step 3.3.4 when the catalog takes Paperless 3 for other reasons; read our API v1 use first | CC | | **R-1320** | App updates | P3 | **Homepage v1.13.2: a medium notice that needs a hand-written credentialed widget (family_gate in front); the fix is v2.7.0, a big step** (the auth rework). No box runs it. `audits/security-app-updates-2026-10-27/TRIAGE.md` | OPEN — filed 2026-10-27 (security app updates, Part 3: not done today) | — | the big step v2.7.0; bench + 9202 + undo; a STOP | CC | | **R-1321** | App updates | P3 | **Tandoor 2.6.15: GHSA-5f74 (high, an XXE file read) and GHSA-69q3 (any user); the fix is 2.7.2** — 2.7.0 removes settings and an endpoint and rewrites the login pages (our probe path — not sure), and 2.7.0/2.7.1 break invite links with sign-up off, so straight to 2.7.2. No box runs it. `audits/security-app-updates-2026-10-27/TRIAGE.md` | OPEN — filed 2026-10-27 (security app updates, Part 3: not done today) | — | a normal step to 2.7.2 with the probe path checked; bench + 9202 (+ undo if a migration); a STOP | CC | -| **R-1322** | App updates | P3 | **Immich v3.2.4 (server + ML): only the Node.js October 2026 runtime notice (CVE-2026-111497) and a CA bundle; the lane step to v3.3.5 was not walked today** (the lowest item of the lane). No household runs Immich; 9202 has a leftover install. `audits/security-app-updates-2026-10-27/TRIAGE.md` | OPEN — filed 2026-10-27 (security app updates, Part 3: not done today) | — | the security-fix lane: `box_walk.py --security immich` on 9202 (remove the leftover first), the writer, a batch STOP | CC | +| **R-1322** | App updates | P3 | **Immich v3.2.4 (server + ML): only the Node.js October 2026 runtime notice (CVE-2026-111497) and a CA bundle; the lane step to v3.3.5 was not walked today** (the lowest item of the lane). No household runs Immich; 9202 has a leftover install. `audits/security-app-updates-2026-10-27/TRIAGE.md` | **VERIFY** — 2026-10-27 night: the lane step v3.2.4 → v3.3.5 WALKED on 9202 (the old install removed through the product first): `proven` — the guarded Update 122 s, the seed read back, soak peak 42.2 %, no kill, no restart (`audits/http2shell-2026-10-27/walks/immich/`); written to the DRILL (`34b14d5`); the live push waits for the operator's yes (STATUS). **Earlier:** OPEN — filed 2026-10-27 (security app updates, Part 3: not done today) | — | the security-fix lane: `box_walk.py --security immich` on 9202 (remove the leftover first), the writer, a batch STOP | CC | | **R-1324** | App updates | P3 | **RomM 5.4's first start can run a 15–20 minute migration on a big library (upstream notes) — longer than the update's check window, so a household's night step could be undone for slowness, not for a fault.** Today's walk (9202, a small seed) took the step in seconds; demo-hp's RomM takes it tonight (security-fix step, catalog `06e603e`). `audits/security-app-updates-2026-10-27/triage-notes/romm.md` | OPEN — filed 2026-10-27; WATCH demo-hp's night leg line | — | read demo-hp's night leg line for romm (done / undone, the time); if undone for time: give the step a longer check or the `needs_person` mark | CC | | **R-1238** | App updates | P2 | **Plex has no test record and no upgrade fixture, so the night leg never updates Plex on a household box.** Filed 2026-10-23. Catalog `6cc317d` moved Plex 1.41.4.9463 → 1.43.5.11029-6bf8af3f0 (the Plex2Shell fix) on the operator's ruling, with NO `update_ladder` entry (the move gate refused; pushed `--no-verify`, the one time). With no ladder, a person's Update press pins the current compose (`stacks/ladder.go` `nextLadderStep`), but the night leg skips the app (`unattended.go` → `LegSkipNoTestRecord`), so every future Plex fix reaches a household only by a hand press. `scripts/upgrade_fixtures.py` has no Plex fixture. A likely seed route is NOT measured: an UNCLAIMED Plex answers a private-address request with no token (`architecture/13-threat-model.md`, the R-1045 row), so the bench may create and read back a library section through Plex's own API without a plex.tv account. **Needs a spike:** prove that route on the bench (seed a section, swap the image, read it back), add the fixture, then `upgrade-test.py --write-ladder` for the current pin — the box walk on 9202 needs the same route behind the setup gate. Evidence: `audits/plex-demo-boxes-2026-10-23/`. **2026-10-23 (later): the NEXT Plex fix need not wait for this** — the security-fix lane (`09` §3 decision 255, D39 = B, controller 0.341.0) takes a box-only step with `seed: "none"` at night (proven on 9202 with Plex 1.43.4 → 1.43.5, `audits/security-lane-2026-10-23/`). The bench fixture stays the aim: it is the only check that reads Plex's data back after a step. | **OPEN** | a claimed-Plex seed route on the bench | the spike above | CC | | **R-440** | App updates | P3 | **[P2-MEDIUM] 23 catalog image pins float, so an update is not reproducible.** `compose pull` on a moving tag fetches whatever upstream published that day. **MEASURED 2026-09-01 over `app-catalog-felhom.eu` @ `29edad9c5bf4`: 79 `image:` lines across 53 apps, 66 distinct; 23 of those lines carry a tag with no patch version.** `postgres:16-alpine` (8 apps), `redis:7-alpine` (6), `mariadb:11.6` (2), plus one each of `postgres:15-alpine`, `postgis/postgis:16-3.5-alpine`, `mariadb:11.4`, `mariadb:12.3`, `ghcr.io/claperco/claper:2.5`, `ghcr.io/thomiceli/opengist:1.13`, `wger/server:2.6`. **A 24th is arguable and is recorded rather than rounded away:** `ghcr.io/immich-app/postgres:16-vectorchord0.4.3-pgvectors0.2.0` pins both extensions exactly but leaves the PostgreSQL patch floating. A customer pressing Frissites can therefore swap their DATABASE ENGINE build with no catalog change and no record; two boxes updated on two days end up different. **Severity MEDIUM on its own; it becomes BLOCKING the moment a pre-update copy exists**, because "what did we upgrade from and to" must be recordable and today it is not — which is also why R-440 must be read next to the digest discipline in Rule 10 of the spike. **MEASURED LIVE 2026-09-01 — the floating pins have ALREADY moved, with a passing control.** Running digests on demo-hp compared against what the registry serves for the same tag today: **`mariadb:11.4` MOVED** (`sha256:4f1d8d20...` -> `sha256:611a2fcc...`) and **`mariadb:12.3` MOVED** (`sha256:a02fe89c...` -> `sha256:dd9b303a...`), while `postgres:16-alpine`, `redis:7-alpine`, `mariadb:11.6` and `opengist:1.13` were SAME — **and both fully-pinned CONTROLS (`rommapp/romm:5.0.0`, `privatebin/pdo:2.0.5`) were SAME.** So on a box with ZERO visible drift by tag, pressing Frissites today silently swaps the DATABASE ENGINE build under `romm` and `bookstack`, with no catalog change and no record. **Compounding fact found while reading:** the recovery unit records `ImagePins` but the manifest comment says *"image NOT stored - re-pulled on restore"*, so a RESTORE of a floating-pinned app also re-pulls whatever is current — the same non-reproducibility on the recovery path. **HALF OF THE ANSWER SHIPPED 2026-09-02 (controller v0.233.0, slice 1): `app.yaml.installed_images` now records, per compose SERVICE, the reference AND the repo digest each container was actually created from — so "what did we upgrade FROM" is answerable on any box that has taken one lifecycle action since the upgrade.** What is still missing is the other half: comparing that digest against what the registry serves for the same tag TODAY, which needs a network call the render path deliberately does not make (see R-446). **The row therefore stays OPEN and its rank is unchanged** — recording a digest does not make a floating pin reproducible; it makes the drift measurable after the fact. `audits/SPIKE-app-update-2026-09-01.md` **— NIGHT 2026-09-23:** every image moved tonight (and the 21 backfilled moves) carries its resolved digest in the catalog's test record; the floating pins themselves still float until the box pulls by digest (`09` §6.4 part 6). **-- MEASURED 2026-09-30 on demo-hp 9201: a fresh install or a guarded Update renders `name:tag@sha256` from the ladder (`digest.go` `RenderWithLadderDigests`) — 9 of 20 services there run such a definition (adventurelog, docmost, paperless-ngx). The other 11 run TAG-ONLY definitions: bookstack, kimai, opengist, privatebin, romm were installed before v0.269.0 and not updated since, and `CarryDigests` (`digest.go:141`) keeps only a digest the running definition already has; bentopdf and calibre-web have no ladder at all. So a re-pull of those (a restore) takes whatever the tag serves that day. `audits/pg-last-six-2026-09-30/E/E2-digests-demo-hp.txt`.** **-- 2026-09-30 (evening):** calibre-web now has a ladder entry (`53a4a1d`), so a new install or a guarded Update renders its tested digest; bentopdf still has none. `audits/more-night-apps-2026-09-30/` **Merged 2026-10-05 from R-446 (duplicate):** the household-visible consequence — for these apps the „Naprakész" badge can never turn „behind" (`felhom-controller controller/internal/stacks/updateorder.go:96` returns false with no catalog digests / no test date); R-740 (same-tag re-test) is closed, so floating-tag drift for laddered apps is handled. | **NARROWED 2026-09-30 — floating only for (1) apps with no ladder entry and (2) apps installed before v0.269.0 until their next guarded Update; owner: CC.** **Re-ranked 2026-10-03: P2→P3: narrowed to apps with no ladder entry and pre-v0.269 installs; each guarded update fixes the latter.** | — | — | CC | diff --git a/documentation/backlog/STATUS-HISTORY.md b/documentation/backlog/STATUS-HISTORY.md index 8a54a543..11bd8c2e 100644 --- a/documentation/backlog/STATUS-HISTORY.md +++ b/documentation/backlog/STATUS-HISTORY.md @@ -5,6 +5,12 @@ Moved here byte for byte on 2026-10-14 (night session), newest first, so that `S **Updated 2026-10-13 (night): demo-hp, demo-felhom and Tester 1 run agent 0.155.0; demo-felhom runs controller 0.310.0, the other two 0.309.0 until the floor is raised. The open-items list is at 127. Reports: `REPORT-poweroff.md`, `REPORT-plugmeter.md`, `REPORT-usenet-2026-10-12.md`, `REPORT-newapps-2026-10-12.md`, `REPORT-disk-evening-2026-10-12.md`, `REPORT-answers-2026-10-12.md`, `REPORT-m3-2026-10-11.md`, `REPORT-redesign-2026-10-10.md`, `REPORT-testers-2026-10-10.md`, `REPORT-register-shrink-2026-10-10.md`, `REPORT-new-apps-2026-10-10.md`, `REPORT-release-2026-10-10.md`, `REPORT-break-the-circle-2026-10-09.md`, `REPORT-dooplex-survival-2026-10-09.md`, `REPORT-day4-2026-10-09.md`.** +## Moved from STATUS on 2026-10-28 (night) + +**2026-10-27.** Done today: agent 0.167.0 vouched, the D55 token revoked, `Tester4-b5dbbd` deleted. New: a nightly security watch mails you (R-1303). + +**Updated 2026-10-27 (evening).** On your yes: 14 apps got a tested security step, and Wishlist, Bookstack and Jellyfin a normal step; boxes take them tonight. Every box runs controller 0.346.1 with the new Traefik, file manager and cloudflared. Ten apps need a bigger step, a row each (R-1311, R-1313, R-1315–R-1322); no household runs them. + ## Moved from STATUS on 2026-10-27 (evening) **Updated 2026-10-27 (afternoon).** Released on your yes: hub 0.173.0, agent 0.167.0 (not vouched yet), controller 0.346.0 (floor 15:37 CET). The line test on a seeding box failed first (qBittorrent keeps sending 14 s after the hold) and works since the same-day fix: 94.5 Mbit/s, the limit put back exactly. demo-hp's clean-up window removed 223 old copies, no alarm.