diff --git a/CONTEXT.md b/CONTEXT.md index d3890e1..8d903f8 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -7,7 +7,45 @@ > > Ask Claude Code: "Please update CONTEXT.md with what we did today" -Last updated: 2026-08-22 (v0.218.0 — R-354/R-355: the abandoned database, and the volumes the off-site restore never returned) +Last updated: 2026-08-22 (v0.219.0 — R-356: the off-site restore refused every app that has no data drive) + +> **2026-08-22 — v0.219.0 (R-356). One predicate was answering two questions.** +> +> **[DESIGN] The restore destination is resolved by the SAME rule as the capture destination.** The +> drive if the app declares one, the system data path otherwise — `Manager.GetAppDrivePath`, one +> expression, now used by `CaptureRecoveryUnit`, `ReconstituteFromOffsite` and `PlaceOffsiteRestore` +> alike. Anything else and the restore aims somewhere the backup never came from, which surfaces as a +> placement-mismatch prompt on a box where nothing actually moved. +> +> **The refusal that protects a drive app from being restored onto the wrong disk (R-253, R-351) +> applies to apps that HAVE a drive to get wrong.** It used to be reached by `HDD_PATH == ""`, which +> also stood in for "is this app installed?". Measured in the catalogue at `459766cb1639`: **53 +> templates, 13 `needs_hdd: true`, 40 `false`** — so for 40 apps that test was permanently true and the +> off-site restore refused them forever, while they were running, telling the customer to reinstall +> them "in the same place", which those apps never offer. **An app with no drive is not misconfigured** +> (`01-topology-and-trust.md` §8, `[DESIGN]`); it is the majority case, and between 19 and 22 August it +> was called a defect four times. +> +> **Now:** *installed?* is asked of `ListDeployedStacks()` via `Manager.isStackDeployed`, which **fails +> CLOSED on a nil provider** — "cannot tell" must not become "go ahead" when the next act is a write. +> *Where?* is asked of `GetAppDrivePath`. A third refusal, with its own sentence and its own route, +> covers installed-but-no-resolvable-data-root: widening `nincs telepítve` to cover that would send a +> customer to reinstall a running app and hide the real fault. +> +> **FENCED, and not changed:** `offboxCaptureSet`'s raw `GetStackHDDPath` (`offbox_capture.go:43`). +> Capture resolves an app's declared `userdata`/`import` file legs against that value; a system-data +> fallback there would write a snapshot claiming to hold the customer's files and not holding them. The +> fenced ACT is "introduce a fallback into capture-side path resolution" — reading the value elsewhere +> is fine. +> +> **Proven live on `demo-hp`, 2026-08-22.** `privatebin` (driveless): planted through the app's own +> HTTP API plus a direct file plant, off-sited, **deleted**, restored through +> `POST /backup/offbox/reconstitute` — **15/15 files back byte for byte**, two Hungarian accented names +> included, message „0 fájl és 1 adatkötet visszaállítva". The scratch was unit-only, exactly the shape +> nobody had ever driven to completion before, and every downstream leg held. `calibre-web` (drive +> app) walked the same way and did not move. Evidence: +> `felhom.eu/documentation/audits/DRILL-r356-hot-only-restore-2026-08-22/evidence/`. + > **2026-08-22 — v0.218.0 (R-354/R-355). The database nobody backed up, and the restore that > returned most apps nothing.**