From 0b1b8d34455d6a84ec7f3ebf32cfd3efe93eaf70 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Tue, 6 Oct 2026 15:49:58 +0200 Subject: [PATCH] v0.301.0: R-518, R-638, R-717 (MinAgent 0.131.0) Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS --- CHANGELOG.md | 9 +++++++++ controller/README.md | 12 +++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e02be9a..782de66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## v0.301.0 — one short stop per backup tier; restores replay before the app starts; the family window reopens a command-closed sign-up (R-518, R-638, R-717; `09` §3 154, 156) (2026-10-06) + +**MinAgent: 0.131.0** (unchanged — R-518 reads the agent's existing `Primary` tier flag, R-82 agents ≥ 0.97.0). + +- **R-518 (decision 156, option A — reverses R-82's one window for both tiers):** a quiesce window runs only the FIRST due tier and starts the apps again at its `snapshotted`; the upload finishes with the apps running; another due tier waits for a later cycle in its own short stop. „Mentés most" makes the LOCAL (primary) copy only; with the local storage absent it makes no copy and stops nothing (ERROR line). A tier that refuses to start inside a window still lets the next one try in that window (no copy made yet). The button text and its confirm say so in hu + en (about 1–1.5 minutes — an estimate from measured parts, not a measured press). Tests: TestFirstTierSnapshot_ResumesAppWhileUploadContinues (the red test), TestBothTiersDue_FirstCycleRunsOnlyFirstTier, TestManualPress_RunsOnlyLocalTier, TestLeftoverTier_RunsInNextCycleInItsOwnWindow, TestManualRunTiers_NoPrimaryAvailable_BacksUpNothing — red-proofed. +- **R-638 (decision 154, option A):** the no-manifest fallback `RestoreApp` starts only the database services, replays, then starts the app (it started the whole stack at the CURRENT definition first); a dump with no identifiable database service is refused before anything is touched; a failed volume step skips the replay. A unit restore whose volume leg failed does not replay. The loader is unchanged; no delete step added. The two main paths were measured safe first on 9202 (docmost, romm). Known limit, not fixed: the off-site rollback's reverse direction (R-893). Tests: TestR638_* (7), red-proofed. +- **R-717:** `after_setup` gains `open_command` / `open_success`: the household's 15-minute window marks the lock `opening` on disk, lifts the env, runs the open command; only full success records `lifted`; a failed open closes it again at once and the app page says so (`app_info.signup_native_open_failed`, hu + en). The close command runs at the window's end, at every start and after a successful update (`markNativeLockForReapply`); a failed close is retried every 2 minutes. Tests: after_setup_r717_test.go (7), red-proofed. Proven live on 9202 with wishlist. +- The shared rule file's copies line names five copies (decision 152). + ## Unreleased (2026-10-06 afternoon) — instruction files kept true (`09` §3 decision 150); no code change - `.claude/rules/unprompted-work.md`: §5 „Instruction files" (the operator's standing rule) and the copies line names the four copies (it said „all three repos"). diff --git a/controller/README.md b/controller/README.md index 7d1c74e..8b11d9c 100644 --- a/controller/README.md +++ b/controller/README.md @@ -1294,7 +1294,10 @@ The nightly backup has two phases that run sequentially. All paths are **per-dri > **Multi-tier whole-guest backup (v0.174.0, R-82 Slice B).** The agent can serve SEVERAL whole-guest > backup tiers with independent cadences — "local daily + PBS weekly" (agent >= v0.97.0, > `GET /backup/tiers`). The controller owns quiescing, so it reconciles them: it collects EVERY due -> tier up front and runs them inside **ONE quiesce window** — one stop, N sequential backups (vzdump +> tier up front. **Since v0.301.0 (R-518, `09` §3 decision 156) a window runs ONLY the first due tier and resumes the +> apps at its `snapshotted`; the next due tier waits for a later cycle with its own short stop, and „Mentés most" makes +> the LOCAL copy only (nothing, and no stop, when the local storage is absent). The rest of this paragraph is the +> pre-v0.301.0 rule, kept for history:** it ran them inside **ONE quiesce window** — one stop, N sequential backups (vzdump > holds a guest lock), one resume. Two cycles on the weekly night would mean two app outages for one > night's work. The app stays quiesced until the **LAST** tier snapshots, so every tier is > app-consistent; the consequence is that both-due-night downtime is *(first tier's full backup)* + @@ -1878,6 +1881,10 @@ appear in the restore dropdown with per-app snapshot filtering. **Tier 1 restore** (`RestoreApp`): - Stop app → resolve app's home drive → `restic restore --target / --include ...` → populate Docker volumes from restored tars → restart app → health check +- **v0.301.0 (R-638):** with a database dump, the no-manifest fallback starts ONLY the database services, replays, then + starts the app (before, the whole stack started at the current definition first); a dump with no identifiable + database service is refused before anything is touched; a failed volume step skips the replay. A unit restore whose + volume leg failed does not replay either. - Restore paths: config dir, DB dump dir, volume dump dir, HDD mounts - Docker volumes restored via `restoreDockerVolumes()`: `docker volume rm -f` → `docker volume create` → `docker run alpine tar xf` @@ -2011,6 +2018,9 @@ that folder is never a dead end, and an install never runs into it silently (R-6 into app.yaml + one `compose up -d`, or a command) set when the gate opens, after the block. The window lifts and the loop re-applies it. `POST /apps//close-signup` for an app installed before the rule: lock record (`opened_by: close-signup`), block, switch; never a gate. Code: `internal/stacks/after_setup.go`. + **v0.301.0 (R-717):** `open_command` / `open_success` reopen a command-closed switch for the household's 15-minute + window (marked `opening` on disk first; a failed open closes it again and the page says so); `command` runs again at + the window's end, at every start and after a successful update; a failed close is retried every 2 min. - **The family gate (v0.287.0, decisions 63/64)** — `.felhom.yml` `family_gate: true` puts a PERMANENT door in front of the app: only the household's family members (each with their own name and password, „Család" card on the security page) and the household itself get through; `family_gate_except:` lists literal path prefixes left to the app's own