From cac92a407e098ad9051260d177ff0943cfca21ec Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Thu, 15 Oct 2026 10:48:58 +0200 Subject: [PATCH] =?UTF-8?q?v0.313.0:=20media=20apps=20on=20every=20drive,?= =?UTF-8?q?=20drive=20events,=20a=20real=20restart,=20Plex=20without=20the?= =?UTF-8?q?=20race=20=E2=80=94=20release=20notes=20(MinAgent=200.155.0);?= =?UTF-8?q?=20golden=20next=20(bake=20=E2=86=92=20vouch=20=E2=86=92=20floo?= =?UTF-8?q?r)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS --- CHANGELOG.md | 9 ++++++--- CONTEXT.md | 12 +++++++++++- REPORT.md | 40 +++++++++++++++++++++++++++++++--------- controller/README.md | 23 +++++++++++++++++++++++ 4 files changed, 71 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4691b16..28bc7b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,10 @@ -## Unreleased → v0.313.0 (2026-10-15, in progress) — the media build, part 1: a real restart, media apps on every drive +## v0.313.0 — media apps on every drive; drive events; a real restart; Plex without the race (R-1023, R-1024, R-1026, R-1027, R-1028, R-1031, R-1032, R-1037, R-1038, R-1044, R-1045, R-1047) (2026-10-15) -Not released yet (bake → vouch → floor, `09` §3 decision 247). Design: felhom.eu `architecture/15-media-library.md` §2, -§3, §7–§10. +**MinAgent: 0.155.0** (unchanged — the eject, guest-attach and disk calls already exist). **Hub:** v0.151.0 mails a returned +drive (R-1049; deployed separately, on the operator's „yes"). **Catalog:** `0188430`, `b6986eb`, `0f1e78b` (the +`media_library` marker, `after_start`). Released only with its golden (bake → vouch → floor, `09` §3 decision 247). +Design: felhom.eu `architecture/15-media-library.md` §2, §3, §7–§10. Proven on Tester 1 (rc.1–rc.3) and demo-hp 9201 +(rc.4): felhom.eu `documentation/audits/media-build-2026-10-15/`. - **A real restart (R-1026).** `RestartStack` runs `up -d --force-recreate` with the stack's environment, reads every container's start time before and after, logs what started again, and FAILS when nothing started again (it logged diff --git a/CONTEXT.md b/CONTEXT.md index 7d4e43a..ea1e546 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -7,7 +7,17 @@ > > Ask Claude Code: "Please update CONTEXT.md with what we did today" -Last updated: 2026-10-04 (v0.293.0 — the Docker-socket self-heal, R-860) +Last updated: 2026-10-15 (v0.313.0 — media apps on every drive, R-1023) + +> **2026-10-15 — v0.313.0, the media build (R-1023 and the rows under it; `09` §3 decisions 245, 247, 248).** Media apps bind +> every PRESENT drive through an owned `docker-compose.override.yml` (`media_library:` marker in the template); a real +> restart (force-recreate + start times); the drive wiring (`internal/mediawire`, keys read at use — Plex's own token, +> decision 248; Jellyfin's key named „felhom"); drive events with the notice, „restart now/later" and a stream check; safe +> removal keeps the drive; Plex's code asked after the start (`after_start`). Released only with golden 0.313.0 (bake → +> vouch → floor, decision 247). Traps found on Tester 1 and fixed: qBittorrent 5 logs in with 204; the agent's disk +> `state` stays „attached" for a pulled registered disk (presence = backing device); the drive gate raced a safe removal. +> A Plex status probe (`/library/sections`, 401) OPENED an unclaimed Plex while Plex started — removed within the hour; +> never gate on a status a starting app also returns. > **2026-10-14 (night) — v0.312.0, https only (R-1033, P1; `09` §3 decision 244).** DECIDED BY CC UNATTENDED — operator > may reverse: the redirect lives in traefik on the box (`felhom-https-only` in the `felhom-forwarded` chain), not in diff --git a/REPORT.md b/REPORT.md index 020cce3..8d8c1f0 100644 --- a/REPORT.md +++ b/REPORT.md @@ -1,11 +1,33 @@ -# REPORT — v0.312.0: every public name answers only over https (R-1033, P1, 2026-10-14 night) +# REPORT — v0.313.0: media apps on every drive, drive events, a real restart, Plex without the race (2026-10-15) -Baseline `9b95e8e` (0.311.0). Design: felhom.eu `09` §3 decision 244 + the unattended decision recorded there (traefik on -the box, because the box keys cannot change Cloudflare zone settings). Evidence: felhom.eu -`documentation/audits/https-only-2026-10-14/`. +Baseline `8bc7ec5` (0.312.0). Design: felhom.eu `architecture/15-media-library.md` §2, §3, §7–§10; `09` §3 decisions 245, +247, 248. Evidence: felhom.eu `documentation/audits/media-build-2026-10-15/` (A = Plex gate, G = Tester 1, G7 = demo-hp). -- `forwarded.yml`: `felhom-forwarded` = chain [`felhom-https-only` (redirectScheme https, 301), `felhom-forwarded-headers` - (clean-up + HSTS 86400)]; catch-all router for unknown names over http. traefik.yml unchanged, no traefik restart. -- Tests red-proofed (three mutations, each seen failing). Green gate: build, vet, test all OK. -- Delivered by hand to Tester 1, demo-hp 9201 and demo-felhom 9201 for the proof (Tier 0). **Not vouched, floor not - moved** — the operator's morning step. +## What changed +- `internal/stacks/media_library.go` — per-drive binds for `media_library:` templates, only present drives; dead-drive + check `system.MountIsShutdown`; R-1031 (no drive question), R-1027/R-1032 (removal never deletes shared/`:ro`; safety + list knows userdata). +- `RestartStack` — a real restart (R-1026). +- `internal/mediawire` — the drive wiring (R-1024, R-1037), the old-install repair (R-1047), safe-removal pause/resume, + the stream count. +- `internal/web/media_events.go` + `media_notice.html` — the notice, restart now/later, safe removal that keeps the drive + (R-1044), the returned drive's file browser recreate (R-1038), the Plex claim (R-1028) and „Kész" refused while + unclaimed (R-1045). `after_start` deploy fields. + +## Proven +- Tester 1 (rc.1–rc.3): existing apps moved to the marker binds with every stored path, library item, watch mark and file + identical; Media D added → notice → restart → wired in every app, second run writes nothing; Media B pulled → nothing + lost, the file browser let go and came back at once, one restart cured the apps; Media D safely removed with torrents → + only its torrents paused, every app let go before the unmount, the drive came back by itself, torrents resumed with no + re-check; 13 hardlink pairs intact. +- demo-hp 9201: the marker ignored by 0.312.0; rc.4 wired qBittorrent + Sonarr from the live catalog; a fresh Plex with + no code stays gated and „Kész" is refused while unclaimed. + +## Tests (each seen failing once) +`TestRestartStack_R1026_*`, `TestMediaLibrary_*`, `TestMountIsShutdown_K4`, `TestRemoveStack_R1027_*`, +`TestProtectedHDDPaths_R1032_*`, `TestR1031_*`, `TestAfterStartField_*`, `TestRun_SecondRunWritesNothing`, +`TestRepairOldRoot_K7`, `TestMediaEvents_*`, `TestEjectStep_G4`, `TestPlanDriveGates_SkipsSafelyRemovedDrive`, +`TestSetupDoneProbe_AcceptJSON_Plex`, `TestPlexClaimBox_RendersPerBranch`, `TestPlexDonePress_RefusedWhileUnclaimed`. + +## Fixed without a row (found on the boxes this session) +qBittorrent 5's 204 login; the gate racing a safe removal; presence read from the agent's `state`. diff --git a/controller/README.md b/controller/README.md index b471af1..860f344 100644 --- a/controller/README.md +++ b/controller/README.md @@ -3307,6 +3307,29 @@ The household sees lost files (name, date taken) on the app page until dismissed `app_repaired_after_crash` with counts only. Immich is the first user (`09` §3 decision 236: Immich's own job queue — no key into the household's account). Code: `internal/stacks/after_unclean_boot.go`, `internal/aftercrash/`. +### 8c. Media apps on every drive and the drive events (v0.313.0, R-1023) + +- **Every drive.** A template with `media_library:` (`folder:`, `read_only:`) gets one bind per PRESENT enrolled drive — + `/userdata/media[/]` at the same path — in `docker-compose.override.yml` (header-marked, ours), + rewritten before every `compose up`. An absent drive (not a mountpoint), a dead one (`shutdown` in + `/proc/self/mountinfo`) and a safely removed one are never bound. Network shares never. The wizard does not ask a + media app for a drive; its config goes on the default drive. `internal/stacks/media_library.go`. +- **A real restart.** `RestartStack` = `up -d --force-recreate` with the stack's env; start times before/after; an + error when nothing started again. +- **Wiring** (`internal/mediawire`): after a media app comes up (debounced 60 s), after the media restart, and on + „Bekötés most": qBittorrent categories + automatic management, Transmission's incomplete folder off, Sonarr/Radarr tag, + root folder, download clients, minimum free space, Prowlarr → Sonarr/Radarr, Plex libraries + „scan on change" (the + server's own token, read at use), Jellyfin libraries (the API key named „felhom", read at use from its database). + Idempotent; keys never stored or logged. Old Sonarr/Radarr installs (`/media/`) are repaired once, no file moved. +- **Drive events** (`internal/web/media_events.go`, `/api/storage/media/{status,restart,wire}`): added / removed / + returned are recorded on the drive; the storage page and the dashboard show the notice with „Újraindítás most" + (stream check first) and „Később" (03:30), and per drive „restarted since". A returned drive recreates the file + browser at once; a dead or removed drive is not bound into it. **Safe removal** with media apps: pause that drive's + torrents → recreate the apps and the file browser without it → unmount → keep it registered; its return needs no + household step, and the torrents resume after the restart. +- **Plex:** the claim code is an `after_start` field — asked on the Plex page once Plex runs (`POST /apps/plex/plex-claim`); + the gate opens only when Plex says claimed, and „Kész" is refused before that. + ### 9. Central Hub Reporting #### Operator actions (`internal/report/opactions.go`, `09` §3 decision 185)