v0.127.0: customer-facing escrow ceremony wizard (/backup/escrow) + Scenario-F stale-blob re-check — one-shot R reveal (no-store, typed-back), re-stage-first start order, agent version gate (MinAgent 0.88.0), escrowed-state hash re-check with card warning (never flips, never blocks); manual-confirm button removed (endpoint stays deprecated)

This commit is contained in:
2026-07-13 19:01:31 +02:00
parent 51c871ad9b
commit 08a966b92f
13 changed files with 1419 additions and 16 deletions
+19 -4
View File
@@ -795,10 +795,20 @@ not just those with HDD data. Non-HDD apps can configure destination, method, an
> real repo). **Atomicity gate:** enabling offsite pushes the password to the agent (`StageEscrowSecret` →
> `POST /escrow/stage-secret`) and marks `EscrowState="pending"`; **no offsite backup runs until the escrow
> is confirmed** (`OffboxRunnable()`), so an un-recoverable offsite copy can never exist.
> **Operator ceremony (pilot, supervised):** enable offsite (→ pending) → run
> `felhom-agent --selftest=escrow-create --identity-bundle <assembled> --upload` (the bundle now carries
> the staged restic password, auto-injected, then wiped) → hand the customer the fresh **R** (once;
> supersedes any prior code) → `POST /backup/offbox/confirm-escrow` (or the "Letét megerősítése" button).
> **Ceremony — PRIMARY path (v0.127.0, agent ≥ v0.88.0): the customer wizard** at `/backup/escrow`
> (`web/escrow_handlers.go` + `templates/backups_escrow.html`): preflight (agent
> `GET /escrow/preflight` + version gate) → warnings (re-ceremony adds the supersede copy) →
> password re-auth (login rate limiter) → **re-stage-first** (offbox configured →
> `PushOffboxPasswordForEscrow`; a staging failure ABORTS the start — no hash-less blob, ever) →
> agent job (`POST /escrow/ceremony`, poll `GET /escrow/ceremony/status` @2 s) → **one-shot R
> reveal** (`POST /escrow/ceremony/claim`, `Cache-Control: no-store`; R exists only in the page's
> JS scope; 10-min unclaimed TTL → void, re-run supersedes) → typed-back (two random words,
> client-side) → finish. R is never templated/logged/persisted on either side.
> **Operator fallback (CLI, unchanged text mode):** enable offsite (→ pending) → run
> `felhom-agent --selftest=escrow-create --upload` (the staged restic password auto-injected,
> then wiped) → hand the customer the fresh **R** (once; supersedes any prior code) → the
> auto-confirm flips escrowed hands-free. (The manual "Letét megerősítése" button is GONE from
> the card; the deprecated endpoint remains for legacy hash-less blobs.)
> **DR:** recover R → the escrow yields the password → `POST /backup/offbox/inject-password {password}`
> pre-places it 0600 → configure offbox → restore. The SFTP access key is **regenerated** at DR (a fresh
> sub-account key), NOT escrowed; the DR recipe carries only the non-secret `offsite_restic`
@@ -813,6 +823,11 @@ not just those with HDD data. Non-HDD apps can configure destination, method, an
> agent-staged secret. The canonical hasher (`backup.HashResticPassword`, trimmed-string sha256) is pinned
> by a cross-repo test vector against the agent's. The manual `POST /backup/offbox/confirm-escrow` is a
> **deprecated fallback** for legacy hash-less blobs (e.g. the demo's).
> **Stale-blob re-check (v0.127.0, Scenario F):** an ESCROWED box re-compares the ACK hash every
> cycle — mismatch OR a present blob with an EMPTY hash (a superseding ceremony that missed the
> staged secret) sets an in-memory stale flag (`EscrowAutoConfirmer.StaleBlob` → the Távoli
> mentés card's warning + re-ceremony CTA) + one warn per distinct hub hash. State never flips,
> runs never block; a covering blob (or a fresh auto-confirm) clears it.
> - **Injection guard** (`ValidateOffboxTarget`): host/user/repo must not start with `-` (ssh
> option-injection) or carry metacharacters/traversal; `OffboxConfigured` fails closed on an invalid
> target. Image: `restic` + `openssh-client` (re-added; restic's sftp backend shells out to `ssh`).