v0.275.0: a backup's data and its version travel together (R-696, 07 §6.6, D4 option A); R-695, R-691, R-694
gates / gates (push) Successful in 23s

The unit's data files are stamped with the versions that wrote them; the capture keeps the
definition the data belongs to; a restore never starts data under another version's
definition (unit restores refuse a mismatch; the off-site restore writes the snapshot's
definition); every tier's time is its data's; the conversion-copy release needs a dump on
the new engine. File-browser sync single-flight + no empty kept folder (R-695); the kept
view joins the folder's owning group, language switch resyncs (R-691); a restore-generated
login is not shown as the password (R-694). Red-proofs in
felhom.eu/documentation/audits/version-travel-2026-09-26/.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-09-26 10:35:22 +02:00
parent fb2bcdd5d6
commit b6810f14ff
47 changed files with 3771 additions and 135 deletions
+38
View File
@@ -1,3 +1,41 @@
## v0.275.0 — a backup's data and its version travel together (R-696, `07` §6.6, D4 option A); R-695, R-691, R-694 (2026-09-26)
**MinAgent: 0.131.0** (unchanged). Needs hub v0.123.0 (unchanged). New strings: yes (hu + en, 5 keys). Evidence:
`felhom.eu/documentation/audits/version-travel-2026-09-26/`.
- **A1 spike first (9202, 0.274.0, `A1/README.md`).** The five-minute status refresh re-captured the recovery unit's
DEFINITION (`compose/`, `image_pins`) two minutes after an update, over the previous version's DATA. Restored in
that window: an app step (docmost 0.95.0 → 0.96.0) came back only because docmost migrated the old data at its
first start; an engine step (PostgreSQL 16 → 18) poured the 16 datadir back, `postgres:18` refused it and the app
was **left down**. The off-site restore never wrote a definition at all.
- **The data records its versions (A2).** Every data file a leg writes is stamped at that moment (`stampDataFile`:
size, mtime, the definition's pins, `installed_images` as `ref@digest`, in the unit's `data-stamps.json`); the
capture folds them into the manifest's new `data` block and **keeps the definition the data belongs to** — a
refresh after a pin change no longer rewrites `compose/` until the next data run. `image_pins` stays the app's
current pins. Wired in the nightly DB and volume legs and the update's own "back up first" (new `dumpOne` seam).
- **A restore never mixes versions (A3).** The unit restores (own unit, second drive, kept-data Load) refuse, before
anything is touched, a unit whose `compose/` names other pins than its data or whose files were written by
different versions (`ErrUnitVersionMismatch`); the off-site restore writes the snapshot unit's definition (and pin)
right after the stop when its version differs from what runs. A unit without `data` (older) restores as before,
WARNed. The restore page's first sentence names the backup and the version („…visszaállt a(z) %s-i mentésből, a(z)
%s verzióra. Elérhető frissítés: …"), or, when no tested step leads on from that version, that the box will not
update it by itself (the automatic leg already refuses such an app — `LegSkipOlderThanLadder`).
- **The times tell the truth (A4).** Tier 1 = `data.at` (else the newest data file — never the manifest, never a
`pre-restore-*` undo copy); Tier 2 capped by the mirror's data time; Tier 3 capped by the data time recorded at
push (`settings.offsite_data_at`). `ReleaseConversionCopies` additionally requires a database dump written after
the conversion whose recorded engine is the NEW major (`ConversionCopy.Service` recorded from now on).
- **R-695:** the file-browser sync is single-flight (callers queued behind a running sync are covered by one sync
that reads the state after them); an EMPTY dated kept folder is never listed or bound.
- **R-691:** the read-only „Megőrzött adatok" view joins the owning GROUP of a group-readable kept folder another
user owns (`group_add`, never root's group, binds stay `:ro`, the household's files and modes untouched — decided
by CC unattended, `07` §6.5); a language switch re-syncs the file browser so the source's name follows it.
- **R-694:** a restore that GENERATED a `type: password` login (no guest app.yaml) records it (`restored_logins`); the
page no longer shows that value as "the first password set at install" and says to use the password valid at the
backup — measured per app: six of seven catalog apps keep the login in their data (code-server is the exception,
`loginAppliedEveryStart`).
- Red-proofs (each seen failing, tree restored): `A5-redproofs/` RP1–RP5, `D2/`, `D3/`, `D4/`. Parity: one new
Hungarian fixture (`deploy_deployed_restored_login`); no existing fixture changed.
## v0.274.0 — kept data: a choice at reinstall, a list, a read-only view, a load (2026-09-25, `09` §3 decision 36); R-690, R-692
**MinAgent: 0.131.0** (unchanged). Needs hub v0.123.0 (unchanged). New strings: yes (hu + en). **A second release