# felhom.eu — task reports > **Overwrite** this file with a summary of the most recent task only (uniform with the other repos; not cumulative). The cumulative hub history lives in [hub/CHANGELOG.md](hub/CHANGELOG.md); the scripts history lives in [scripts/CHANGELOG.md](scripts/CHANGELOG.md). ## SPIKE — referential-coupling backup classification — 2026-07-14 **controller 0.130.0 (demo 9201) / agent 0.88.0 · findings-only, no production code · full audit: `documentation/audits/SPIKE-backup-classification-2026-07-14.md`** Empirical ground-truth pass for the userdata-backup-classification redesign (mandatory=COUPLED / optional=DECOUPLED-precious / excluded=DECOUPLED-bulk). ### What was established - **SQ1 — offsite carries no userdata today, no exception (source + live).** All 12 restic snapshots are `backups/primary/` units only; a full `restic ls` of the newest immich snapshot shows compose + `immich-postgres.sql` + manifest — **immich is offbox-toggled and its photo library is in none of its snapshots** (the latent broken-restore gap, now live-proven). - **NEW F-S1:** tier-2 does **not** copy bulk userdata — `RunTier2` rsyncs only the unit + `appdata/`; the `tier2.go:17` "recovery unit + bulk userdata" header and the `main.go:1360` "namespace wholesale" comment are stale. Browsable HDD userdata has **zero automated off-drive protection today** (live: `secondary/{radarr,jellyfin}` hold only `recovery-unit/`). - **NEW F-S2:** tier-2's appdata leg keys on the stack name → **paperless-ngx** (`appdata/paperless`) is silently skipped (live contrast: `secondary/nextcloud` has `appdata/`, `secondary/paperless-ngx` doesn't) — its document originals get no tier-2 copy. - **SQ3 — the coupling model is VALIDATED (scratch Immich, catalog images v2.5.5).** DB-present / library-absent restore: the server **refuses to boot** (its own `.immich` folder-check, with the mount state remembered *in the DB*); with the skeleton recreated it boots into a **lying gallery** — timeline reports all 3 assets, every thumbnail/original fetch is HTTP 500. No repair/ re-import path. Restoring the files → all 200 again. **Worse-than-empty: confirmed.** - **SQ2** — full per-bind classification for all 55 catalog apps (13 hdd + 42 volume-only); shared-media-tree consistency resolved by the "class belongs to the bind; the writing app is the authority; `:ro` readers back up nothing" rule. - **SQ4** — size split measured live (state 0.5 M–933 M vs bulk tree ~100 MB demo / TB-scale prod); the two-number estimate reuses the existing `estimate.go` per-mount du + container-view volume sizer — zero new measurement plumbing. - **SQ5 — round-trip verdict: EXCLUSION scoping** (tar the userdata root minus excluded subtrees). Per-bind nested tars cannot ride the v1 manifest (`HDDSubdirs` basenames; CTRL-001 forbids path separators); exclusion scoping needs no manifest/import change and stays backward-compatible. Proposed `backup:` block schema + **two-level default** (no block → legacy per-tier behavior; block present → unlisted writable binds mandatory) — the task's single-level mandatory-default premise would have shipped unmigrated media trees offsite (quota blow-up) and was corrected. - **SQ6** — `.fab` over-capture quantified on the live tree (radarr bundle carries ~1.6× its own data even on the small demo tree, unbounded in prod); the live marker-file export leg is blocked on the customer-owned dashboard login (same blocker as the open Viktor full-circle test). ### Cleanup Scratch Immich fully removed (containers/volumes/network/files/images; verified 0 spike containers, controller healthy). Restic inspection read-only (`--no-lock`), 12 snapshots before and after. No drive namespace, tier-2 target, or deployed app touched.