F-S2 + F-S3: compose-derived appdata dir resolution (v0.131.0)
The controller assumed an app's HDD appdata dir is always appdata/<stackName>.
paperless-ngx writes appdata/paperless (stack paperless-ngx), so every consumer
keying by stack name silently missed it via a stat-and-skip. One canonical
resolver appbackup.AppDataDirNames derives the real dir name(s) from the app's
compose ${HDD_PATH} binds; all consumers use it.
- F-S2 (tier-2): RunTier2 mirrors the resolved appdata/<name> (paperless docs
got NO tier-2 copy before). Tier2Info size + RestoreTier2Files live dir use it.
WARN when a declared appdata dir is absent. New tier2Mirror seam.
- F-S3 (migrate, NEW): all six per-app appdata legs (collision/size/copy/verify/
cleanup/skip-set) now loop resolved names. scope="app" migration of paperless
previously copied nothing and left an empty media dir (scope="all" was saved by
the merge walk). WARN on missing declared dir in the copy leg.
- Multi-dir (N>1) refusal: tier-2 backup/info/restore refuse loudly (Hungarian);
migrate supports N. No catalog app hits it today; lifted by Task 3.
- Display: storage page sums resolved dirs.
- Truth repair: the v0.130.0 "tier-2 copies the namespace wholesale" claim is
false; corrected in CHANGELOG + main.go export-adapter comment.
+9 tests; red-proofs RP-1..RP-5 all confirmed. Controller-only, no agent/hub
coupling. Task 1 of the backup-classification-redesign arc.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A45Qop8YY8tS94bz63LFne
This commit is contained in:
@@ -1,5 +1,48 @@
|
||||
## Changelog
|
||||
|
||||
### v0.131.0 — F-S2 + F-S3: compose-derived appdata dir resolution (paperless-ngx → appdata/paperless) (2026-07-14)
|
||||
|
||||
The controller assumed an app's HDD appdata dir is always `appdata/<stackName>`. paperless-ngx binds
|
||||
`${HDD_PATH}/appdata/paperless/...` — stack `paperless-ngx`, dir `paperless` — so every consumer that
|
||||
keyed by stack name silently missed it via a stat-and-skip. One canonical resolver
|
||||
(`appbackup.AppDataDirNames`) now derives the real dir name(s) from the app's compose `${HDD_PATH}`
|
||||
binds, and all consumers use it. Task 1 of the backup-classification-redesign arc
|
||||
(`felhom.eu/documentation/audits/SPIKE-backup-classification-2026-07-14.md`), deliberately independent
|
||||
of the classification schema.
|
||||
|
||||
- **F-S2 (spike-proven live) — tier-2 backup/info/restore.** `RunTier2` now mirrors the resolved
|
||||
`appdata/<name>` dir, so paperless documents get their off-drive copy (previously: the appdata leg's
|
||||
`os.Stat` gate skipped `appdata/paperless-ngx`, which never existed — **silent, no copy**).
|
||||
`Tier2Info`'s size + the SSD-headroom guard use the resolved dir. `RestoreTier2Files` targets the
|
||||
resolved live dir (was restoring into a wrong/empty `appdata/paperless-ngx`). A `[WARN]` now fires
|
||||
when the compose DECLARES an appdata dir but it is absent on disk (the silence that hid F-S2). Every
|
||||
rsync leg goes through a new `tier2Mirror` seam (prod behavior unchanged).
|
||||
- **F-S3 (NEW, found this session) — scope="app" migration.** `migrate.go` keyed all six per-app
|
||||
appdata legs (collision check, source-size, copy, verify, cleanup, skip-set) by stack name. For
|
||||
**scope="app"** there is no merge walk, so migrating paperless-ngx copied nothing, "verified"
|
||||
vacuously, flipped `HDD_PATH`, and the app came up with an **empty media dir**. (scope="all" was
|
||||
saved by the merge walk — data safe, accounting off.) All six legs now loop the resolved name(s);
|
||||
the copy leg WARNs on a missing declared dir.
|
||||
- **Multi-dir refusal (defensive; no catalog app hits it today).** An app resolving to N>1 distinct
|
||||
appdata dirs is refused loudly by tier-2 backup/info (honest `no_target` status +
|
||||
`"az alkalmazáshoz több adatkönyvtár tartozik — a 2. mentés jelenleg alkalmazásonként egy könyvtárat
|
||||
támogat"`) and tier-2 file-restore (refused BEFORE the app is stopped). Migrate supports N naturally.
|
||||
This limitation is lifted by the tier-policy engine (Task 3).
|
||||
- **Display.** The storage-detail page sums the resolved appdata dir(s), so paperless-ngx shows a
|
||||
non-empty size.
|
||||
- **Truth repair.** The v0.130.0 entry below states "The scheduled/tier-2 backup path was NOT affected
|
||||
(it copies the felhom-data namespace wholesale)" — **that sentence is false** and is left in place
|
||||
only as the historical record it corrects here: tier-2 copies the recovery unit + the resolved
|
||||
`appdata/<name>` dir(s) ONLY (never the userdata tree — F-S1, unaddressed here — and never the
|
||||
namespace wholesale). The `main.go` export-adapter comment that repeated the claim is fixed in code.
|
||||
|
||||
Scope guards: destination layout unchanged (`<destBase>/appdata` stays flat); no userdata copying at
|
||||
any tier (F-S1 is the classification redesign's, not this task's); `ExportDataMounts` / `.fab` /
|
||||
offbox untouched. Tests: +9 (resolver table incl. dedupe/foreign-drive/whole-root; RunTier2
|
||||
paperless/legacy/multi-dir; Tier2Info + restore refusals + resolved live dir; scope="app" paperless
|
||||
migration). Red-proofs RP-1..RP-5 all confirmed (resolver, RunTier2 leg, restore dst, migrate copy
|
||||
leg, N>1 guard). Controller-only; no agent/hub coupling; MinAgent unchanged.
|
||||
|
||||
### v0.130.0 — CRITICAL C6B-F1: hollow .fab export (three compounding defects) + C6B-F2 share-removal guard (2026-07-14)
|
||||
|
||||
CAMPAIGN-6B surfaced that `.fab` export produced a **config-only, data-free bundle** for 12/13
|
||||
|
||||
Reference in New Issue
Block a user