v0.154.0 — R-48: one restore entry per app, and the intent is a described choice
The offsite restore list rendered up to five inline forms per app row. Two of them —
„Helyreállítás az élő adatok közé (csak a hiányzó fájlok)" and „Teljes visszaállítás
(fájlok + adatbázis)" — were sibling buttons whose difference is whether the customer's
data comes back at all. That mis-selection CAUSED the round-2 incident: an operator who
had read the source pressed the missing-only button and /backup/offbox/reconstitute was
never hit (DIAG-immich-restore-round2-2026-07-19, finding 1).
The rule this establishes: two adjacent controls whose difference is "your data comes
back" vs "your data cannot come back" must never be distinguishable only by layout.
Each row now carries ONE „Visszaállítás…" entry linking to a per-app wizard at
GET /backups/restore/app?name=<app>: three intent CARDS with consequence sentences, a
visible phase strip, danger styling plus the R-43 double-confirm carried over verbatim on
the destructive one, and the pair-honesty panel bound to real OffsiteScratchPair facts.
deriveWizardStep is pure over (op running, size-gate flash, scratch ready); the step is
never accepted from the request, and a running op outranks a stale ?full_prep= so no
commit button survives into a restore. While ANY op runs every mutation form is suppressed
server-side instead of being offered and refused.
No new mutation endpoint: every card posts to the pre-existing /backup/offbox/* handler
with the same field names and gates, and the page works with JavaScript disabled.
internal/{backup,appbackup,selfupdate} untouched. R-45's job registry stays its own item.
Fixes a latent bug found on the way: offboxRedirectTo hardcoded "?" when appending its
flash, which against the wizard's ?name=<app> target would have buried the flash inside
the name value.
No new agent coupling — MinAgent stays 0.90.0.
This commit is contained in:
+32
-1
@@ -7,7 +7,38 @@
|
||||
>
|
||||
> Ask Claude Code: "Please update CONTEXT.md with what we did today"
|
||||
|
||||
Last updated: 2026-07-20 (v0.153.0 — R-47: the DB replay no longer races the app, both paths)
|
||||
Last updated: 2026-07-21 (v0.154.0 — R-48: one restore entry per app, intent as a described choice)
|
||||
|
||||
> **2026-07-21 — v0.154.0 (R-48).** Collapses the offsite restore controls to a single
|
||||
> „Visszaállítás…" entry per app row plus a per-app wizard at `GET /backups/restore/app?name=<app>`.
|
||||
> The defect it closes is the CAUSE of the round-2 incident: the list rendered up to five inline
|
||||
> forms per row, two of which — the missing-only merge and the true reconstitution — were sibling
|
||||
> buttons whose difference is whether the data comes back. The rule it establishes: *two adjacent
|
||||
> controls whose difference is "your data comes back" vs "your data cannot come back" must never be
|
||||
> distinguishable only by layout.*
|
||||
>
|
||||
> **DECISION: the wizard is server-rendered on the EXISTING endpoints.** No new mutation endpoint,
|
||||
> no JSON state API, no client router. Every card is a real form POST to
|
||||
> `/backup/offbox/{restore,place,reconstitute}` with the same field names and gates, and the server
|
||||
> renders the next step — so it works with JavaScript disabled. `TestRestoreWizard_NoNewMutationEndpoints`
|
||||
> makes that structural: adding a form that posts somewhere new fails the suite by design.
|
||||
>
|
||||
> **DECISION: R-45 stays its own item.** The wizard polls the two existing status surfaces as-is; the
|
||||
> generalized job registry (and with it a real per-phase progress feed) is not built here.
|
||||
>
|
||||
> **DECISION: the step is derived, never requested.** `deriveWizardStep` is pure over (op running,
|
||||
> size-gate flash, scratch ready). Precedence is load-bearing — a running op outranks a stale
|
||||
> `?full_prep=` in the URL, or a commit button reappears mid-restore. While ANY op runs every
|
||||
> mutation form is suppressed server-side rather than offered and then refused with a 409.
|
||||
>
|
||||
> Latent bug found and fixed on the way: `offboxRedirectTo` hardcoded `"?"` when appending its flash,
|
||||
> which would have buried the flash inside `?name=<app>`. **No agent coupling — MinAgent stays
|
||||
> 0.90.0.** 9 new tests + the Group-B red-proof; full suite green.
|
||||
>
|
||||
> **NOT live-validated at commit time by design:** v0.154.0 is published but deliberately NOT
|
||||
> hand-deployed — the operator's hub floor save (0.153.0 → 0.154.0) pulls it via the self-update
|
||||
> path, and that swap IS the R-23(a) single-fire validation (STOP-1).
|
||||
|
||||
|
||||
> **2026-07-20 — v0.153.0 (R-47).** Closes the H4 race on **BOTH** restore paths. The replay needs a
|
||||
> running DB container, so both paths started the WHOLE stack first — giving the application a window
|
||||
|
||||
Reference in New Issue
Block a user