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:
@@ -1,58 +1,60 @@
|
||||
# REPORT — v0.117.0: consuming-namespace NAS verification + deploy-view truth (RCA fixes 2+4)
|
||||
# REPORT — v0.118.0: backup integrity (F7 atomic dumps · F6 no-single-copy · F5 stale sweep)
|
||||
|
||||
**Date:** 2026-07-11 · **Version:** controller v0.117.0 (from v0.116.1) · **MinAgent:** 0.81.0
|
||||
UNCHANGED (all checks controller-namespace-local; no new agent API) · **Deployed:** guest 9201
|
||||
(`0.117.0` healthy) · **NOT published/vouched** — Peti stays 0.113.0. Pairs with agent v0.84.0
|
||||
(RCA fix 1). Commits: `c0f3e12` + `4a9c54a` (linux-suite test pin).
|
||||
**Source:** `felhom.eu/documentation/audits/AUDIT-nas-cwa-rca-2026-07-11.md`.
|
||||
**Date:** 2026-07-12 · **Version:** controller v0.118.0 (from v0.117.0) · **MinAgent:** 0.81.0 (UNCHANGED)
|
||||
· **Deployed:** guest 9201 (`0.118.0` healthy) · **Source:** `felhom.eu/documentation/audits/CAMPAIGN-3-2026-07-11.md`.
|
||||
|
||||
## What shipped
|
||||
|
||||
- **`internal/system/fsclass*.go`** — statfs f_type classifier for THIS process's namespace:
|
||||
`network` (nfs/cifs/smb2) | `autofs` (healthy idle trigger, NEVER force-mounted) | `stub` |
|
||||
`unknown` (error/3 s timeout → fail open). Seams: `statfsFn`, `netProbeFSClass`,
|
||||
`Server.classifyFSPath`, `Router.classifyFSPath`.
|
||||
- **Fix 2a — probe assertion:** `--netprobe` child creates the probe file first (legitimately
|
||||
triggers the automount), then REQUIRES a mounted network fs → exit 5 → category
|
||||
`not_network_fs`, new §3.2 Hungarian message, full rollback, nothing registered.
|
||||
- **Fix 2b — deploy refusal:** `POST /api/stacks/{name}/deploy` → `refuseNetworkStubDeploy`: a
|
||||
registered network `HDD_PATH` classifying as stub refuses 409; idle autofs / live / unknown /
|
||||
local / unregistered / empty all proceed.
|
||||
- **Fix 2c — stub badge:** `networkStorageWarnings` → (warnings, stubs); stub leg runs even when
|
||||
the agent is unreachable; dashboard + stacks cards render "Hálózati tárhely hibás — az alkalmazás
|
||||
nem a NAS-t látja"; stub WINS over unreachable; the unreachable line stays byte-identical
|
||||
(template-asserted). Pure core `networkStorageWarningsIn` + `stubNetworkPaths`.
|
||||
- **Fix 4 — deploy-view truth (the RCA S-C symptom):** deployed-app storage select marks `selected`
|
||||
by the STORED `HDD_PATH`; absent stored path → extra disabled `<path> (nem elérhető)` option;
|
||||
`IsDefault` selects only for NEW deploys.
|
||||
- **F7 (HIGH) — atomic volume dumps.** `backup.DumpAppVolumes` writes the tar to `<vol>.tar.tmp`,
|
||||
fsyncs it, then atomically `os.Rename`s over the restore point ONLY on success (+ best-effort dir
|
||||
fsync via `atomicPromoteTar`) — mirroring the DB-dump path (`dbdump.go` DumpOne). Any tar
|
||||
error / timeout / dead-NFS EIO removes only the `.tmp`; the last good `.tar` is byte-untouched. The
|
||||
`.tar.tmp` is invisible to restore-point/stale scans (ends `.tmp`, not `.tar`); orphan tmps are
|
||||
swept. New `tarVolume` seam for the red-proof.
|
||||
- **F6 (LOW) — no single-copy.** `RunAllTier2` no longer skips non-HDD apps → volume-only apps get a
|
||||
cross-drive tier-2 copy. sys_drive restore-point label is now clear ("Belső SSD (rendszer)"), never
|
||||
blank. `SingleCopyWarning` (honest HU banner) shows on a single-drive box with no off-drive target.
|
||||
- **F5 (LOW) — stale primary sweep.** `pruneStalePrimaryDirs` (end of each backup cycle) removes an
|
||||
orphaned `backups/primary/<app>` dir on an OLD drive after an HDD_PATH move. Guards: deployed +
|
||||
different-current-drive only; never the current-drive dir or an undeployed app's dir; strictly under
|
||||
a `backups/primary/` prefix.
|
||||
- **Part 4 — locality fork: operator chose (A) keep locality, document-only.** No code change; the
|
||||
NAS-outage behaviour + tier-2 mitigation are documented plainly.
|
||||
|
||||
## Tests + red-proofs
|
||||
## Tests + red-proofs (all green)
|
||||
|
||||
| Test | Result | Red-proof |
|
||||
|---|---|---|
|
||||
| magic table + seam + real-local-dir-is-stub (linux) | PASS | — |
|
||||
| `TestNetProbeChild_StubRefused` / `_AutofsAfterCreateRefused` / `_RealLocalDirRefused` (linux) | PASS | assertion disabled → **the stub VERIFIED** (exit 0) → FAIL |
|
||||
| `TestNetAdd_StubProbe_RollsBackNotRegistered` (rollback + not registered + Hungarian) | PASS | same mutation → job phase `done` → FAIL |
|
||||
| `TestRefuseNetworkStubDeploy_Table` (7 rows) | PASS | mounted-only gate → idle-autofs + unknown rows FAIL (over-refusal) |
|
||||
| `TestNetworkStorageWarningsIn_StubWins` / `_UnreachableAloneUnchanged` | PASS | — |
|
||||
| `TestNetworkBadgeTemplates_DistinctStrings` (unreachable line byte-identical) | PASS | — |
|
||||
| `TestDeployPage_DeployedSelectShowsStoredHDDPath` (real Manager + real template render) | PASS | IsDefault-only revert → default drive selected → FAIL (both assertions) |
|
||||
| `TestDeployPage_MissingStoredPathRendersTruthOption` | PASS | — |
|
||||
- F7: happy atomic promote (no `.tmp` left); **truncation red-proof** — pre-seeded good `.tar`, tar
|
||||
fails mid-write → original byte-unchanged, no 0-byte (revert to in-place write → fails); leftover
|
||||
`.tar.tmp` swept.
|
||||
- F6: volume-only app in the tier-2 run set (revert the skip → fails); single-drive honest signal;
|
||||
sys_drive drive-label non-blank.
|
||||
- F5: redeployed residue removed; **guard red-proofs** — undeployed app's restore point kept,
|
||||
current-drive dir kept.
|
||||
- Existing `TestListRestorePoints_DriveLabel/SSD` updated (blank → clear label, the F6 behaviour).
|
||||
|
||||
Full suite green on Windows AND on 180 (linux); the linux run caught the pre-existing C5 child-body
|
||||
suite needing the classifier pinned to `network` (fixed in `4a9c54a` — the real statfs correctly
|
||||
refuses a tempdir). Gates: `template_id_gate.py` + `emoji_gate.py` OK.
|
||||
## Live validation (demo 9201, real pipeline, sim-NAS rails — exportfs only)
|
||||
|
||||
## Deploy + live validation
|
||||
- **F7 money-shot:** established good tars (radarr sha `847a97ad…` +4 others), then `exportfs -u` the
|
||||
NFS target 4 s into a backup during volume dumps → run `success:false`; **all 5 nas-media volume
|
||||
tars BYTE-IDENTICAL** (clean host-side diff), **no 0-byte file, no leftover `.tar.tmp`**; the next
|
||||
clean run produced fresh good tars (`success:true`). This is the exact campaign F7 repro, now safe.
|
||||
- **F6:** after a tier-2 cycle, volume-only `actualbudget` + `seerr` appear under
|
||||
`felhom-usb/backups/secondary/` (previously none); `actualbudget` snapshot `drive_label` =
|
||||
"Belső SSD (rendszer)"; single-copy banner correctly absent on the multi-drive demo.
|
||||
- **F5:** a seeded stale `nas-media/backups/primary/actualbudget` (actualbudget lives on sys_drive) was
|
||||
swept by the next backup; the real sys_drive dir + radarr's nas-media dir were kept.
|
||||
- **Restore round-trip:** calibre-web tamper → restore → BYTE-IDENTICAL (53 files), container healthy —
|
||||
F7's write change did not affect restore.
|
||||
|
||||
- Image `0.117.0` built+pushed on 180, deployed to 9201 via the bootstrap mechanism; healthy.
|
||||
- **Q1c reboot validation (operator GO, with agent 0.84.0):** post-reboot, no manual action —
|
||||
CWA auto-started healthy on the NAS, health `status=ok` on the first cycle, dashboard renders NO
|
||||
stub badge (grep count 0 against the live page).
|
||||
- **NOT live-validated (test-level only, by design):** the stub refusal branches — producing a live
|
||||
stub post-fix would require breaking a healthy guest (the agent now heals it at start). Covered by
|
||||
the red-proven unit/render tests above.
|
||||
## NOT live-validated / standing items
|
||||
|
||||
## Follow-ups
|
||||
- Single-drive `SingleCopyWarning` live (the demo has enrolled drives) — unit-tested only.
|
||||
- Task C (F8/F4) and Task D (ring/alerting) remain queued.
|
||||
- Peti's box (controller 0.113 / agentless-on-proxmox2) reaches 0.118 + agent 0.85 at his next train —
|
||||
noted for the roadmap; the agentless-on-proxmox2 cluster gap stands.
|
||||
- No publish/floor movement; agent untouched (MinAgent 0.81.0).
|
||||
|
||||
RCA fixes 3/5/6 queued as separate tasks. Peti publish train: 0.84.0 + 0.117.0.
|
||||
## Box state at wrap
|
||||
|
||||
controller 0.118.0 healthy on 9201; all backups consistent (fresh tier-1 + tier-2 incl. volume-only
|
||||
apps); NAS re-exported; no stale test residue.
|
||||
|
||||
Reference in New Issue
Block a user