From e1613aea8d52f9474e6562b3c643a05699a26148 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Sat, 24 Oct 2026 21:03:34 +0200 Subject: [PATCH] Restore-holes run close-out: README, CONTEXT, REPORT; the interrupted-restore log line names a waiting put-back. Commit only. --- CHANGELOG.md | 2 ++ CONTEXT.md | 8 +++++ REPORT.md | 34 ++++++++++---------- controller/README.md | 11 +++++++ controller/internal/backup/restore_record.go | 3 ++ 5 files changed, 41 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58637d4..aa3e148 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -88,6 +88,8 @@ brief 2026-10-24, Part 4 (commit only; the release rides the next normal train). over the data the box is about to put back. The restore record (`PutBackWaiting`, `note.restore.interrupted_put_back_waiting`) and the `restore_interrupted` event say the box puts the data back when the drive is there. Pinned by `TestR1251_TheRecordSaysThePutBackWaits` (seen failing). +- The interrupted-restore log line says a put-back waits for its drive (it still said „the household is told to run it + again", which the record no longer says). - A removal clears a waiting put-back (it belongs to the install); a later restore that completes drops it (the household chose that data; the copy stays on disk). - Tests (each seen failing with its rule taken out): `TestR1251_DriveCutRestoreWaitsForTheDriveThenPutsBackBeforeAnyStart` diff --git a/CONTEXT.md b/CONTEXT.md index dba1dcd..280e464 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -1,5 +1,13 @@ # CONTEXT.md — Project Memory +> **2026-10-24 night (unattended restore-holes run) — on `main`, NOT released (next v0.343.0, MinAgent 0.158.1 unchanged).** +> R-1251: a pending put-back blocks every start (`backup/appstop_putback_wait.go`: restore hold `putback_pending`, the +> hold store every start path honours; `ResumePutBack` in the boot recreate and `restartStacks`; `ResumeWaitingPutBacks` +> at start and on a drive return; a failed put-back = the D20 hold; the copy's folders synced before `SetUndo`). +> R-1252: `tier2CaptureSetFull` returns `classified`; reconcile only then; `BackupBlockRejected` via the stack adapter. +> R-1253: `AppStopGuard.BusyWith` / `BeginExclusive`; the exporter refuses a stop-first export. Proven on Tester 1 +> (R-1251) and 9202 (R-1252, R-1253): felhom.eu `audits/restore-holes-2026-10-24/`. Release: Monday's list (STATUS). + > **2026-10-24 (attended release run) — v0.342.0 gains the TESTED line (operator rulings D41 = 50 %, D42, the iperf3 line > test; felhom.eu CONTEXT 07:22/07:26).** `agentapi.LineTest` reads the agent's `GET /host/line-test` (agent ≥ 0.164.0 — > its weekly 10-second iperf3 upload to ep0 inside the tunnel; demo-hp measured 90.7 Mbit/s where the push floor said 10). diff --git a/REPORT.md b/REPORT.md index 8d71a79..d44b4bf 100644 --- a/REPORT.md +++ b/REPORT.md @@ -1,21 +1,21 @@ -# REPORT — review round 2 (2026-10-24, unattended): two small fixes, commit only +# REPORT — the restore and backup holes (2026-10-24 night, unattended; commit only, NOT released) -**What:** found by the review round's readers and verified at `file:line` by the main session (felhom.eu -`documentation/audits/review-round-2-2026-10-24/`). No release; both ride the next normal train (next v0.343.0). +Brief: fix R-1251, R-1252, R-1253 (and R-1254, R-1257 in their repos); live-prove the recovery-code changes; nothing +released. Full record: felhom.eu `documentation/audits/restore-holes-2026-10-24/README.md`. -1. **A media restart no longer starts an app the household stopped (R-721).** `restartMediaApps` and - `mediaSafeRemoval` recreated every media app (`RestartStack` = `up -d --force-recreate`), skipping only held ones. - Now both take `stacks.MediaAppsToRecreate`, which leaves out an app whose recorded intent is „stopped" (logged). Its - override is already written, so its next start sees the drives. Tests: `TestMediaAppsToRecreate_SkipsAppsTheHouseholdStopped` - (red with the rule off) and `TestR2_MediaRecreateLoopsSkipStoppedApps` (source pin of the two loops; red with - `s.mediaApps()` back in the safe removal). -2. **The file manager's header name file appears whole (R-1100).** `LoadOrCreateFileBrowserSSOHeader` created the file - empty and wrote it after; a parallel caller read "" and got an error. Measured on clean `main` `321df1f`: 44 of 300 - runs of the existing parallel-writers check failed (4 of 50 under `-race`). Now: temp file, sync, hard link into place - — 0 of 300, 0 of 50 under `-race`. +| Commit | What | CI | +|---|---|---| +| `bb2809d` | R-1251 (P1): a pending put-back blocks every start; H2 a failed put-back holds; H7 Stop still gets the put-back | 2301 / #482 success | +| `062f9b4` | R-1251: the copy's folders synced before the marker names it (found by the Tester 1 proof: `undo.json.tmp` after a cut); the restore record says the put-back waits | 2302 / #483 success | +| `518a135` | R-1252 (P2): reconcile only under a valid classification; a rejected block is said and signalled; kept copies stay kept; Remove drops kept records | 2303 / #484 success | +| `c9b4b82` | R-1253 (P2): a stop-first export refuses while another operation holds the marker | 2304 / #485 success | +| (close-out) | README, CONTEXT, this report; the interrupted-restore log line names a waiting put-back | final report | -`go vet ./...` and `go test ./...` green. Design docs read: `15-media-library.md` §10–11 (the restart), `01` §5 / `02` -(the file manager sign-in). +**Proofs:** R-1251 on Tester 1 — a local restore of MeTube (1.5 GB volume) cut by powering the VM off, the data disk +taken off and put back: held while away, put back BEFORE the start, the newest data there, a later restart poured +nothing. R-1252 on 9202 — the review's audiobookshelf steps: kept after a bogus path. R-1253 on 9202 — the export refused +during a restore, ran after it. Every rule red-proved (each test names its red-proof). -**Docs (same session):** `REUSE.md` — D22 released in v0.338.0; the `recordInstalledImages` callers; a row for the -stray-copy seams. felhom.eu `documentation/audits/review-round-2-2026-10-24/EDITS.md` lists every edit. +**Images:** dev images `0.343.0-dev.r1251a/b`, `r1252a`, `r1253a` built locally and loaded into the test guests only; +never pushed. **Machines:** Tester 1 and 9202 put back (both: the controller on 0.342.0; leftover anonymous volumes of +the R-1267 class named in the audit). **Release:** Monday — controller v0.343.0 (with R-1250), MinAgent 0.158.1. diff --git a/controller/README.md b/controller/README.md index 04cf87b..2d304a6 100644 --- a/controller/README.md +++ b/controller/README.md @@ -1030,6 +1030,17 @@ Each app can define rich metadata in `.felhom.yml`: files stay); the operator gets `backup_run_failures` leg `restore-put-back`. Only a put-back that fails — or a replay AND rollback that both fail — still HOLDS the app (`restore_mixed` / the restore hold, operator-cleared), and then the copy is kept for support. On success the copy is removed. `offbox_restore_undo.go`. + - **A restore cut by a power loss, on a drive that comes back late (unreleased, R-1251).** The copy of the live + data lives on the app's drive. When it cannot be reached at start because the drive is not bound yet, the app is + HELD (`putback_pending`; „…A visszaállítás előtti adatai egy meghajtón vannak, amely most nem érhető el…") and no + path starts it; when the drive binds, the copy is poured back FIRST, then the app starts. A put-back that fails + holds the app for support („félúton megszakadt"). Stop pressed during the restore still gets the put-back. The + copy's folders are synced before the restore records it. `appstop_putback_wait.go`. + - **An export that stops its app waits for a running restore (unreleased, R-1253):** it is refused (409, + „Egy másik művelet … éppen leállítva tart egy alkalmazást…") while another operation holds the app-stop marker. + - **A broken backup block never deletes a second-drive copy (unreleased, R-1252):** the night copy deletes dest + folders only under a valid classification; a rejected block keeps every copy, says so on the app's status and + tells the operator once a day (`backup_run_failures`, leg `tier2-settings-unreadable`). - **Where an off-site restore puts the data (v0.219.0, R-356).** `ReconstituteFromOffsite` and `PlaceOffsiteRestore` resolve the destination with `Manager.GetAppDrivePath` — **the same resolver `CaptureRecoveryUnit` wrote the snapshot with**: the app's `HDD_PATH` if it declares diff --git a/controller/internal/backup/restore_record.go b/controller/internal/backup/restore_record.go index eeef695..d40a17f 100644 --- a/controller/internal/backup/restore_record.go +++ b/controller/internal/backup/restore_record.go @@ -114,6 +114,9 @@ func (m *Manager) LoadRestoreRecordAfterRecovery(putBack, waiting []string) *Res if res.PutBack { tail = "the start-up put its data back as it was before the restore (R-1195), and the household is told so" } + if res.PutBackWaiting { + tail = "its put-back waits for the app's drive (R-1251), and the household is told so — not to run it again" + } m.logger.Printf("[WARN] [backup] restore of %s (%s, started %s) was INTERRUPTED by a controller stop — recorded as failed; %s", rec.Stack, rec.Op, rec.StartedAt.Format(time.RFC3339), tail) }