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:
@@ -703,6 +703,19 @@ not just those with HDD data. Non-HDD apps can configure destination, method, an
|
||||
> - init-if-absent (idempotent), `forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune`,
|
||||
> single-flight (shares `m.running`) + migration-guard, restic's own exit code checked, restore to a
|
||||
> scratch dir (non-destructive).
|
||||
> - **Unit discovery (v0.104.0) — durable, deployment-independent.** Each toggled app's recovery unit is
|
||||
> **discovered** by scanning the durable storage registry — every registered *schedulable* storage path
|
||||
> (`GetSchedulableStoragePaths`) ∪ the system-data fallback drive — for `backups/primary/<app>`, rather
|
||||
> than *inferring* the drive from the app's live `app.yaml` `HDD_PATH` (which silently fell back to
|
||||
> `systemDataPath` for a toggled-but-undeployed app → offbox looked on the wrong drive, backed up
|
||||
> nothing, and reported `ok`/0). If the same app's unit exists on two drives (drive churn), the **newest
|
||||
> by manifest `CreatedAt`** is used and the stale one is WARN-logged. The WRITE side (`CaptureRecoveryUnit`
|
||||
> / dumps) is unchanged — this only changes offbox's read/discovery path. Boundary: decommissioned or
|
||||
> non-schedulable drives are not searched.
|
||||
> - **No silent success (v0.104.0):** a run where ≥1 app is toggled but **0** were backed up (no unit found
|
||||
> anywhere) is a **hard error** → `LastStatus="error"` + operator alert (was a misleading `ok`/0 snapshots).
|
||||
> A *partial* run (some units missing) stays `ok` but sets a Hungarian **`LastWarning`** naming the skipped
|
||||
> apps, shown on `/backups`.
|
||||
> - **Secrets** (SSH key + auto-gen repo password) are **0600 files in the data dir** — never logged/committed;
|
||||
> they ride DR via the PBS whole-CT snapshot of the rootfs (the recovery-unit/dr-recipe stay secret-free).
|
||||
> - **Injection guard** (`ValidateOffboxTarget`): host/user/repo must not start with `-` (ssh
|
||||
|
||||
Reference in New Issue
Block a user