From a2d2569719751974e1c3656c640057e9ab1c0f9b Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Wed, 21 Oct 2026 11:03:32 +0200 Subject: [PATCH] register: the ep0 WireGuard row is R-1204 (R-1201 was taken by a parallel session; the earlier commit message says R-1201) --- .../rehearsal-2026-10-20/B6-failures/s8-wrong-clock/README.md | 4 ++-- documentation/audits/rehearsal-2026-10-20/journal.md | 2 +- documentation/backlog/OPEN-ITEMS.md | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/documentation/audits/rehearsal-2026-10-20/B6-failures/s8-wrong-clock/README.md b/documentation/audits/rehearsal-2026-10-20/B6-failures/s8-wrong-clock/README.md index 3f495240..8d068e37 100644 --- a/documentation/audits/rehearsal-2026-10-20/B6-failures/s8-wrong-clock/README.md +++ b/documentation/audits/rehearsal-2026-10-20/B6-failures/s8-wrong-clock/README.md @@ -26,12 +26,12 @@ with the RTC set; clock control = the box's HTTP Date header (`01-run.txt`). elérhető" 10+ minutes after the return. ep0's side, read-only: Tester4's last handshake was 07:40:47 — while its clock said 2028 — and none since, while the other peers shook hands 21–96 s ago. WireGuard refuses a handshake whose timestamp is older than the last one it accepted, so the tunnel stays dead until the real date passes 2028 or the - peer is reset on ep0. **→ R-1201.** Not reset (ep0 is read-only in this run). + peer is reset on ep0. **→ R-1204.** Not reset (ep0 is read-only in this run). 2. **The local whole-box tier's newest archive is dated 2028-10-21.** By the code (`localapi/server.go:1187`), the due rule answers „within cadence" until then — the D3/T11 shape (R-1189 a). The live answer was not read: the controller asks only inside its night window, and the box dies in B7 before tonight. - Paperless stayed stopped after the return with a clear sentence („leállítottuk, mert újra és újra összeomlott … Az Indítás gombbal újra megpróbálhatod"); one Start → running in 1 minute. **→ R-1202** (with the „Hub nem elérhető" text). -**Verdict: FINDINGS.** A box that runs once with its clock ahead loses its DR tunnel (R-1201, P2) and, by the code, its +**Verdict: FINDINGS.** A box that runs once with its clock ahead loses its DR tunnel (R-1204, P2) and, by the code, its whole-box schedule (R-1189 a); a box with its clock behind stops an app silently and blames the hub (R-1202, P3). diff --git a/documentation/audits/rehearsal-2026-10-20/journal.md b/documentation/audits/rehearsal-2026-10-20/journal.md index e0bbbc39..c0711dc0 100644 --- a/documentation/audits/rehearsal-2026-10-20/journal.md +++ b/documentation/audits/rehearsal-2026-10-20/journal.md @@ -84,7 +84,7 @@ | 05:27–05:45 | due checks | R-1019 closed (demo-felhom read-only, two channels), R-895 first verdict recorded, R-435 moved to 10-27 (logs gone) | | 05:40 | mail | the nightly DooPlex secret sweep named three rehearsal secrets in session records: OLD_BIND_TOKEN, BIND_TOKEN, SETUP_CODE — my mail reads (full text of the bind and setup mails) carried them in; all three are one-time and already spent. From now on mail is read names-only | | 05:58–07:13 | B6 ★7 | DST live: the first 02:30 skipped, the second ran once (01:30:00Z box), PASS; side effects of the 4-day jump: a local whole-box archive and off-site snapshots dated 2026-10-25; W30 | -| 07:15–07:58 | B6 ★8 | −2 y (OS raised it to 2026-04-13): „Hub nem elérhető" only, Paperless stopped silently → R-1202; +2 y: whole-box archive dated 2028; back to real time: ep0 WireGuard tunnel dead (handshake replay) → R-1201 (P2); R-1189 (a) half-live | +| 07:15–07:58 | B6 ★8 | −2 y (OS raised it to 2026-04-13): „Hub nem elérhető" only, Paperless stopped silently → R-1202; +2 y: whole-box archive dated 2028; back to real time: ep0 WireGuard tunnel dead (handshake replay) → R-1204 (P2); R-1189 (a) half-live | | 07:57–08:45 | B6 ★10 + #15 | 3 days off (box clock 2026-10-28): ONE catch-up, clear household note; a restart mid-catch-up recovered (marker, drive gate, one new catch-up); 8 apps off-site; PASS | | 08:44:37 | B7 | the box dies: hard stop, `qm destroy 9320 --purge` (own VM, own disks) | | 08:44:55–08:53 | B7 | reinstall from the same public ISO, the guide as written; pairing screen after ~5 min. The pairing code was OCR'd into sec (two reads agreed) and blacked out in the screenshot | diff --git a/documentation/backlog/OPEN-ITEMS.md b/documentation/backlog/OPEN-ITEMS.md index 42d9a594..a1e30db3 100644 --- a/documentation/backlog/OPEN-ITEMS.md +++ b/documentation/backlog/OPEN-ITEMS.md @@ -196,11 +196,11 @@ stopping line that lies. | **R-1186** | Backup & restore | P3 | **The nightly off-site copy is skipped silently when another backup holds the flag, and the catch-up never re-runs it.** `offbox.go:981-996` returns nil with an INFO line on the nightly path; `withLeg` marks the leg ended anyway (`cmd/controller/main.go:1246`). The 05:30 proof and 06:00 integrity check take the same flag, so a backup time near them collides every night. Only the hub's 48 h `offsite_stale` notices. CONFIRMED in code. Data-loss hunt 2026-10-20 (T5). | OPEN | — | Fix: mark the leg NOT ended on a busy skip so the catch-up retries; say it on the backups page | CC | | **R-1187** | Backup & restore | P3 | **`.fab` export/import candidates from the data-loss hunt, not yet proven:** (a) an export silently drops a drive folder that holds a symlink (`appexport/fabplan.go:292`, `export.go:714`); (b) the import never sets file owners and drops symlinks (`restore.go:1157-1176`); (c) import into a STOPPED app merges into the existing volumes, and the default export (stop ticked) carries no SQL dump (`restore.go:361-374`, `export.go:262,366`, `appbackup/dbdump.go:142`); (d) no concurrency guard, no undo, no record (`restore.go:181-186`, `web/handler_export.go:312-353`); (e) PROVEN and split out as R-1191 (the import drops the family gate); (f) it trusts the bundle's HDD_PATH (`restore.go:589-631`); (g) the DB import runs psql without ON_ERROR_STOP and misses postgis (`restore.go:1052-1053, 928-937`). Read by reviewer 1; main session spot-checked (a); (e) proven live → R-1191. Evidence `audits/dataloss-hunt-2026-10-20/C1-restore-rollback-candidates.md`. | VERIFY | — | Prove (c) first on 9202 with a throwaway app; split into rows only what reproduces | CC | | **R-1188** | Backup & restore | P3 | **Restore-path candidates from the data-loss hunt, not yet proven (one confirmed in code):** (a) PROVEN LIVE → R-1195 (a power cut mid-restore restarts the app on the backup's data; the undo copy is not used); (b) a failed `volume rm` is ignored before the untar (`restore.go:218`); (c) PROVEN against production code (`audits/dataloss-hunt-2026-10-20/C3-R12-leftover-temp/`): an interrupted second-drive whole restore leaves `.felhom-restoring`, and EVERY retry fails „fájlmásolás sikertelen: … file exists" with the file never back (`tier2_whole.go:86-87`, O_EXCL); (d) the full off-site download has a 30-min cap per press and the household is not told to retry (`web/offbox_handlers.go:455`); (e) place and full restore re-read the LATEST snapshot instead of the downloaded one (`offbox_restore.go:675-679`). Evidence `audits/dataloss-hunt-2026-10-20/C1-restore-rollback-candidates.md`. | VERIFY | — | Fix (c) now (remove a stale temp of the same name before the copy); prove (a) with the B6 power-cut-mid-restore scenario | CC | -| **R-1189** | Backup & restore | P3 | **Time and concurrency candidates from the data-loss hunt, not yet proven:** (a) a host clock ahead during one whole-guest backup silences that tier until real time passes it, and the hub reads the same clock (agent `localapi/server.go:1178-1192`, `backup/runner.go:607-629`, hub `monitor/deadline.go:243`; R-973 cap counts future runs `backup_cap.go:61`); (b) the whole-guest start creeps ~5 min/night until a night is skipped silently (`server.go:1184`, `quiesce.go:150, 807-818`) — PARTLY SUPPORTED by demo-hp's agent journal 2026-09-30…10-20: completions drift 04:36→04:50 between resets, and THREE nights had no local whole-box backup (Oct 2, 6, 9), each right after an off-cycle daytime/evening run (Oct 1 22:15, Oct 5 11:24, Oct 8 22:25) — the 24-hour „not due yet" rule skips the next night; nothing tells anyone; (c) the whole-guest quiesce stops apps mid-restore or mid-update (`quiesce.go:213-275, 565`); (d) CONFIRMED in code: the off-site proof and integrity check are plain daily jobs outside the catch-up (`nightchain.go` header: the catch-up runs only the three backup legs), so they never run on a box that is off at 05:30–06:00, while the comment at `cmd/controller/main.go:1575-1577` says the opposite; (e) CONFIRMED in code: the hub's 05:00 check wants a dump „since Budapest midnight" (`hub/internal/monitor/deadline.go:416-419, 556-565`), so an evening backup time (which the banner suggests) raises a false `expected_dbdump_missed` error every morning — and on 2026-10-25 the check also runs at 04:00 (R-1183); (f) the OS leg and kernel reboot follow a daytime valve backup (agent `server.go:982-986`, `kernel.go:101-114`) — design question; (g) spring forward 2027-03-28 fires dump and second copy together; (h) self-update busy check before the pull only (`updater.go:532-545, 764`); (i) a double-clicked restore shows failed while it runs (`web/handlers.go:1853-1874`). Evidence `audits/dataloss-hunt-2026-10-20/C1-time-concurrency-candidates.md`. | VERIFY **(a) half-live 2026-10-21 (B6 #8):** the box wrote a local whole-box archive dated 2028-10-21 while its clock was 2 years ahead (`s8-wrong-clock/README.md`); by `localapi/server.go:1187` the local tier is „within cadence" until then. The due answer itself was not read live (the box died in B7 before its night window). The same run found R-1201 (the ep0 tunnel). | — | (a) is B6 #8's live test; (b) read the agent journal on demo-hp; the rest by unit tests | CC | +| **R-1189** | Backup & restore | P3 | **Time and concurrency candidates from the data-loss hunt, not yet proven:** (a) a host clock ahead during one whole-guest backup silences that tier until real time passes it, and the hub reads the same clock (agent `localapi/server.go:1178-1192`, `backup/runner.go:607-629`, hub `monitor/deadline.go:243`; R-973 cap counts future runs `backup_cap.go:61`); (b) the whole-guest start creeps ~5 min/night until a night is skipped silently (`server.go:1184`, `quiesce.go:150, 807-818`) — PARTLY SUPPORTED by demo-hp's agent journal 2026-09-30…10-20: completions drift 04:36→04:50 between resets, and THREE nights had no local whole-box backup (Oct 2, 6, 9), each right after an off-cycle daytime/evening run (Oct 1 22:15, Oct 5 11:24, Oct 8 22:25) — the 24-hour „not due yet" rule skips the next night; nothing tells anyone; (c) the whole-guest quiesce stops apps mid-restore or mid-update (`quiesce.go:213-275, 565`); (d) CONFIRMED in code: the off-site proof and integrity check are plain daily jobs outside the catch-up (`nightchain.go` header: the catch-up runs only the three backup legs), so they never run on a box that is off at 05:30–06:00, while the comment at `cmd/controller/main.go:1575-1577` says the opposite; (e) CONFIRMED in code: the hub's 05:00 check wants a dump „since Budapest midnight" (`hub/internal/monitor/deadline.go:416-419, 556-565`), so an evening backup time (which the banner suggests) raises a false `expected_dbdump_missed` error every morning — and on 2026-10-25 the check also runs at 04:00 (R-1183); (f) the OS leg and kernel reboot follow a daytime valve backup (agent `server.go:982-986`, `kernel.go:101-114`) — design question; (g) spring forward 2027-03-28 fires dump and second copy together; (h) self-update busy check before the pull only (`updater.go:532-545, 764`); (i) a double-clicked restore shows failed while it runs (`web/handlers.go:1853-1874`). Evidence `audits/dataloss-hunt-2026-10-20/C1-time-concurrency-candidates.md`. | VERIFY **(a) half-live 2026-10-21 (B6 #8):** the box wrote a local whole-box archive dated 2028-10-21 while its clock was 2 years ahead (`s8-wrong-clock/README.md`); by `localapi/server.go:1187` the local tier is „within cadence" until then. The due answer itself was not read live (the box died in B7 before its night window). The same run found R-1204 (the ep0 tunnel). | — | (a) is B6 #8's live test; (b) read the agent journal on demo-hp; the rest by unit tests | CC | | **R-1190** | Backup & restore | P3 | **Key and retention candidates from the data-loss hunt, not yet proven:** (a) a recovery ceremony while off-site is not configured seals a package with no repo password and supersedes the good one (`escrow_handlers.go:217`, agent `main.go:2975-2981`, hub `store.go:3392`); (b) the global „create your recovery code" bar links to the ceremony the backups page hides during a recovery offer (`escrow_banner.go:23-33` vs `backups_remote.html:144-160`); (c) after a reuse-path reinstall the new PBS key K is never escrowed and nothing compares fingerprints (`felhom-pbs-apply:99`, `escrow_confirm.go:182-205`); (d) whole-guest off-site copies run before any escrow exists (design question vs 07 §6.1's Tier-3 gate); (e) the escrow PUT is two statements; (f) the operator's off-site re-issue resets the provider password before saving it (hub `offsite.go:217-245`); (g) „Megőrzött adatok" can list a running app's live folder when its app.yaml is unreadable (`kept.go:220-235, 330-402`); (h) a unit restore can point an app back at an old drive and F5 then prunes the current drive's unit (`backup.go:1517-1574`). Evidence `audits/dataloss-hunt-2026-10-20/C1-keys-candidates.md`, `C1-delete-retention-candidates.md`. | VERIFY | — | Unit tests first for (a), (e), (g) | CC | | **R-1198** | Backup & restore | P3 | **A backup disk the family adds later is never offered as the place for the whole-box backup; the page keeps offering the disk that holds the apps' own data.** Rehearsal 2026-10-20 B6 #13 (`audits/rehearsal-2026-10-20/B6-failures/s13-second-drive/`): a 50 GB disk plugged in and initialised as „Mentolemez" → the backups page still offers only „Családi adatlemez — Kijelölöm"; `internal/web/backup_target_offer.go:101` `firstOfferableDrive` offers the FIRST eligible drive, never a choice, and the drive's card has no „use for backups". | OPEN | — | Offer every eligible drive (largest empty first) and let the household pick | CC | | **R-1200** | Backup & restore | P3 | **A box installed in the afternoon gets no whole-box backup on its first night: the install's own backup starts the 24 h clock, so the family's whole first day reaches a whole-box copy only on the SECOND night (~38 h after install).** Rehearsal 2026-10-20 B5 (`audits/rehearsal-2026-10-20/B5-night/README.md`): Tester4's install backup at 12:09Z; at the 02:30–06:30Z window the agent answered „within cadence window" (`felhom-agent internal/localapi/server.go:1187`, `age >= tier.Cadence`, default 24 h). R-899 (closed) fixed the same shape for a daytime PRESS only. The other tiers did run that night (database copy, second drive, off-site — all PASS), so app data was covered; the whole-box (DR) tier was not. | **OPEN** — a design question: should the first scheduled night always run (like a press), or is one tier enough on night one? | — | decide; if „always run": treat the install backup like a press in the due rule, with a test on the first night | CC | -| **R-1201** | Backup & restore | P2 | **A box that runs once with its clock ahead loses its WireGuard tunnel to ep0 — the PBS whole-box copies and the operator's door — until the real date passes the wrong one, and nothing says why.** Rehearsal 2026-10-20 B6 #8 (`audits/rehearsal-2026-10-20/B6-failures/s8-wrong-clock/`): Tester4 booted with its clock at 2028-10-21 for 13 min, then the real time. ep0's `wg show` (read-only): Tester4's last handshake 07:40:47Z (clock at 2028), none in the 14 min after the return, the other peers 21–96 s. WireGuard refuses a handshake initiation whose TAI64N timestamp is not newer than the last one accepted from that peer, so the peer stays dead until 2028 or until ep0 resets it. Effects seen: every agent PBS call times out (15 s), the controller's due-check errors, the backups page says „A host-ügynök jelenleg nem elérhető". Likely triggers in the field: a dead CMOS battery, a hand-set BIOS clock, a VM restored with a wrong RTC. | **OPEN** — reproduced once live; not reset on ep0 (read-only in this run; the peer still shows the stale handshake). The box is destroyed in B7, which ends it for Tester4. | — | design: detect it (the hub sees the peer's handshake age) and heal it (re-key the peer, or ep0 resets the stored timestamp on a hub-signed request); a test with a fake clock | CC | +| **R-1204** | Backup & restore | P2 | **A box that runs once with its clock ahead loses its WireGuard tunnel to ep0 — the PBS whole-box copies and the operator's door — until the real date passes the wrong one, and nothing says why.** Rehearsal 2026-10-20 B6 #8 (`audits/rehearsal-2026-10-20/B6-failures/s8-wrong-clock/`): Tester4 booted with its clock at 2028-10-21 for 13 min, then the real time. ep0's `wg show` (read-only): Tester4's last handshake 07:40:47Z (clock at 2028), none in the 14 min after the return, the other peers 21–96 s. WireGuard refuses a handshake initiation whose TAI64N timestamp is not newer than the last one accepted from that peer, so the peer stays dead until 2028 or until ep0 resets it. Effects seen: every agent PBS call times out (15 s), the controller's due-check errors, the backups page says „A host-ügynök jelenleg nem elérhető". Likely triggers in the field: a dead CMOS battery, a hand-set BIOS clock, a VM restored with a wrong RTC. | **OPEN** — reproduced once live; not reset on ep0 (read-only in this run; the peer still shows the stale handshake). The box is destroyed in B7, which ends it for Tester4. | — | design: detect it (the hub sees the peer's handshake age) and heal it (re-key the peer, or ep0 resets the stored timestamp on a hub-signed request); a test with a fake clock | CC | ## Storage & devices — 10 rows (P3 4, P4 6)