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
+33
View File
@@ -1,5 +1,38 @@
## Changelog
### v0.118.0 — backup integrity: atomic volume dumps (F7) + no single-copy (F6) + stale-primary sweep (F5) (2026-07-12) — MinAgent: 0.81.0
Fixes CAMPAIGN-3 (`felhom.eu/documentation/audits/CAMPAIGN-3-2026-07-11.md`) backup findings. MinAgent
UNCHANGED (0.81.0) — all changes are controller-local; no new agent API consumed.
- **F7 (HIGH) — atomic volume dumps.** `backup.DumpAppVolumes` now writes the tar to `<vol>.tar.tmp`,
fsyncs it, and only atomically `os.Rename`s it over the restore point on success — the same
crash-safe pattern the DB-dump path already uses (`appbackup/dbdump.go` DumpOne), extended with a
best-effort directory fsync. Before this, tar wrote the `.tar` IN PLACE, so a mid-write NFS cut left
a 0-byte tar REPLACING the last good dump (tier-1 restore is replace-semantics → an empty volume).
Now any tar error / timeout / dead-NFS EIO removes ONLY the `.tmp`; the last good `.tar` is
byte-untouched. The `.tar.tmp` name (ends `.tmp`, not `.tar`) is invisible to the
restore-point/stale scans; orphan `.tar.tmp` from a killed run is swept. New `tarVolume` test seam.
- **F6 (LOW) — no single-copy backups.** Volume-only apps (no HDD_PATH, backups on sys_drive) now flow
through the tier-2 cross-drive copy (`RunAllTier2` no longer skips non-HDD apps) — a second copy on
the secondary drive (the 3-2-1 intent). Their restore-point drive label is no longer blank (clear
"Belső SSD (rendszer)"). A single-drive box (no off-drive target) surfaces an HONEST
`SingleCopyWarning` banner on the backup page instead of implying a 3-2-1 guarantee it cannot keep.
- **F5 (LOW) — stale primary-dir sweep.** After each backup cycle, `pruneStalePrimaryDirs` removes an
orphaned `backups/primary/<app>` dir an app left on an OLD drive when its HDD_PATH moved (invisible
disk residue). LOAD-BEARING GUARDS: removes only when the app is deployed AND its current namespace
root differs from the dir's drive; NEVER touches the app's current-drive dir (the live restore
point) or an undeployed app's dir; only ever operates strictly under a `backups/primary/` prefix.
- **Part 4 (operator fork) — backup-target locality: option A (keep locality), document-only.** NAS
apps' tier-1 artifacts stay beside the data on the NAS; tier-2's cross-drive copy is the off-NAS
leg. Documented plainly (backup feature doc) so the NAS-outage window is never a surprise; no code
change (option B, retarget-to-local, was not selected).
- **Live-validated (demo 9201):** F7 money-shot — a mid-write `exportfs -u` during a volume dump left
all 5 nas-media volume tars BYTE-IDENTICAL (sha unchanged), no 0-byte, no leftover `.tar.tmp`, run
`success:false`; next run produced fresh good tars. F6 — actualbudget/seerr now on
felhom-usb/secondary. F5 — a seeded stale dir on the wrong drive swept, current dirs kept. Restore
round-trip byte-identical. Tests incl. the F7 truncation red-proof + F5 guard red-proofs, all green.
### v0.117.0 — consuming-namespace NAS verification + deploy-view truth (RCA fixes 2+4) (2026-07-11) — MinAgent: 0.81.0
Controller half of the RCA fix pair (agent v0.84.0 ReassertNetworkMounts). Source: