controller v0.118.0: backup integrity F7/F6/F5 — docs + CHANGELOG + REPORT + CONTEXT

F7 atomic volume dumps, F6 no single-copy (volume-only tier-2 + honest single-drive
signal), F5 stale-primary sweep. Part 4 locality fork = A (doc-only). Live-validated
on 9201: F7 money-shot byte-identical through mid-write cut, F6/F5 confirmed, restore
round-trip byte-identical.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017CDMFpFx84pfviCTVuGGhf
This commit is contained in:
2026-07-12 09:18:05 +02:00
parent e3903be0f1
commit 0f311adaa1
4 changed files with 126 additions and 48 deletions
+27
View File
@@ -363,6 +363,13 @@ self-sufficient backup** — any single tier can fully restore an app.
No tier depends on another tier's data.
- **Tier 2 is configurable for ALL apps** — not just apps with HDD data. Non-HDD apps
back up config + DB dumps to the secondary drive (small but protects against drive failure).
**(v0.118.0, F6):** the nightly tier-2 RUN (`RunAllTier2`) now actually includes volume-only apps
too — it used to skip every non-HDD app, leaving them a single controller-level copy on `sys_drive`.
A sys_drive app's restore-point drive label is now clear ("Belső SSD (rendszer)"), never blank.
- **3-2-1 on single vs multi drive (v0.118.0, F6):** on a box with a second physical drive, tier-2 is
the off-drive copy. On a **single-drive** box (no off-drive target at all) there is genuinely only
ONE local copy — `FullBackupStatus.SingleCopyWarning` surfaces an honest Hungarian notice on the
backup page ("Csak egy másolat készül…") instead of implying a 3-2-1 guarantee the box cannot keep.
- The `AppBackupPrefs.Enabled` field in settings.json is legacy and not read by any code.
**Per-app Tier 2 contents by app type:**
@@ -380,6 +387,26 @@ self-sufficient backup** — any single tier can fully restore an app.
The nightly backup has two phases that run sequentially. All paths are **per-drive** — each physical drive gets its own restic repo and per-app DB dump directories.
> **Atomic dump writes (v0.118.0, CAMPAIGN-3 F7).** BOTH dump paths are crash-safe: the DB dump
> (`dbdump.go` DumpOne) and the Docker-volume dump (`DumpAppVolumes`) write to a `.tmp` sibling, fsync,
> then `os.Rename` over the restore point ONLY on success. A mid-write failure (a NFS cut mid-tar, an
> EIO, a timeout) removes only the `.tmp` and leaves the last good `.sql`/`.tar` **byte-untouched** —
> a tier-1 restore is replace-semantics, so an in-place write that got truncated to 0 bytes used to
> destroy the only restore point. `.tar.tmp` files are invisible to the restore-point/stale scans and
> orphans are swept on the next run.
> **Stale-primary sweep (v0.118.0, F5).** After each cycle, `pruneStalePrimaryDirs` removes an
> orphaned `backups/primary/<app>` dir left on an OLD drive when an app's `HDD_PATH` moved to another
> drive. Guarded: only for a DEPLOYED app whose CURRENT drive differs from the dir's drive; never the
> current-drive dir (the live restore point) or an undeployed app's dir; strictly under `backups/primary/`.
> **NAS backup locality (v0.118.0, CAMPAIGN-3 Part 4 — decision A).** A NAS-resident app's tier-1
> artifacts live **on the NAS itself** (`nas-media/backups/primary/<app>`), beside the data. During a
> NAS outage both the app data AND its freshest tier-1 dump are on the dead device — the **tier-2**
> cross-drive copy to a local drive is the off-NAS leg that saves them (and only after it has run).
> This locality is deliberate (kept in the fork over retargeting tier-1 to a local drive); the tier-2
> copy is the mitigation. Stated here so the outage window is never a surprise.
**Drive layout (v0.26.0):**
```
<drive>/