v0.104.0: off-box unit discovery (durable, deployment-independent) + no-silent-success
offbox located each toggled app's recovery unit via AppNamespaceRoot→GetAppDrivePath, which reads the app's LIVE app.yaml HDD_PATH and silently falls back to systemDataPath when the app isn't deployed → looked on the wrong drive, backed up nothing, reported ok/0 (DIAG root cause). Now: - discoverOffboxUnit/offboxCandidateNSRoots scan the durable storage registry (schedulable non-decommissioned paths ∪ systemDataPath) for backups/primary/<app>, independent of deploy state; newest-by-manifest-CreatedAt wins on drive churn. - RunOffboxBackup: runOffboxInternal returns (backedUp, missing, err); 0-of-N toggled → hard error + operator alert; partial → ok + new OffboxTarget.LastWarning (shown on /backups, preserved across config edit). - AppNamespaceRoot + primary WRITE paths unchanged. - 6 non-hollow tests (A-E + edge) + both companion red-proofs run (reverted). - NOT yet live-validated against the Storage Box (spike creds torn down). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
@@ -1,5 +1,35 @@
|
||||
## Changelog
|
||||
|
||||
### v0.104.0 — off-box unit discovery (durable, deployment-independent) + no-silent-success (2026-07-09)
|
||||
|
||||
Fixes the off-box mis-resolution + silent-success landmine surfaced by the Storage-Box spike and pinned by
|
||||
the DIAG report (`felhom.eu/documentation/audits/SPIKE-storagebox-restic-direct-2026-07-09.md`). Root cause:
|
||||
`runOffboxInternal` located each toggled app's recovery unit via `RecoveryUnitPath(AppNamespaceRoot(stack),
|
||||
stack)`; `AppNamespaceRoot`→`GetAppDrivePath` reads the app's **live** `app.yaml` `HDD_PATH` and returns `""`
|
||||
for a not-currently-deployed app, **silently falling back to `systemDataPath`**. So a toggled-but-undeployed
|
||||
app was looked for on the wrong drive → `os.Stat` failed → skipped → the run returned `nil` → status `ok`
|
||||
with 0 snapshots (no alert).
|
||||
|
||||
- **Discovery over inference** (`internal/backup/offbox.go`): new `discoverOffboxUnit` / `offboxCandidateNSRoots`
|
||||
scan the durable storage registry — every registered *schedulable, non-decommissioned* path
|
||||
(`GetSchedulableStoragePaths`) ∪ `systemDataPath`, deduped by resolved nsRoot — for `backups/primary/<app>`,
|
||||
independent of live deploy state. Multiple copies of the same unit (drive churn) → the **newest by manifest
|
||||
`CreatedAt`** (mtime fallback) is backed up, the stale one WARN-logged. `AppNamespaceRoot` and the primary
|
||||
WRITE paths (`CaptureRecoveryUnit`/dumps) are **unchanged**.
|
||||
- **No silent success** (`RunOffboxBackup`): `runOffboxInternal` now returns `(backedUp, missing, err)`.
|
||||
≥1 toggled but `backedUp==0` → a **hard error** (`LastStatus="error"` + `offboxNotify` fires with a non-nil
|
||||
err → operator alert). A *partial* run stays `ok` but sets a new customer-visible **`OffboxTarget.LastWarning`**
|
||||
(`internal/settings/settings.go`, `last_warning,omitempty`) naming the skipped apps; rendered on `/backups`
|
||||
in the `--warn` style (`internal/web/templates/backups.html`), preserved across a config edit
|
||||
(`internal/web/offbox_handlers.go`).
|
||||
- Tests (`internal/backup/offbox_test.go`): six non-hollow cases (A discovery-on-registered-drive, B 0/N
|
||||
hard-error+alert, C partial→warning, D newest-of-two-copies, E happy path, edge 0-toggled), asserting the
|
||||
exact discovered `src` + `LastStatus`/`LastError`/`LastWarning` + notify-err. **Companion red-proofs run:**
|
||||
(A) reverting to `AppNamespaceRoot` resolution → 0 backups → FAIL; (B) `if false` on the 0/N promotion →
|
||||
silent `ok` → FAIL; both reverted.
|
||||
- **NOT yet live-validated against the Storage Box** — awaiting supervised re-provision + endpoint round-trip
|
||||
(box repos/creds were torn down with the spike). Unit suite fully covers the discovery + status logic.
|
||||
|
||||
### v0.103.0 — F-C2-1: config loader no longer corrupts a bcrypt password_hash (silent auth bug) (2026-07-07)
|
||||
|
||||
Fixes campaign-2 finding **F-C2-1** (`felhom.eu/documentation/tests/CAMPAIGN-2-2026-07-07.md`).
|
||||
|
||||
Reference in New Issue
Block a user