v0.228.0 — the off-site check reads the data; the debug page stops lying (R-399 + R-400)
gates / gates (push) Successful in 12s

R-399: monitoring.integrity.read_data_subset defaults to 100%. A pack damaged
without changing its size made plain `restic check` report "no errors were found"
on demo-hp 2026-08-30; every read-data form caught it. Cost on that 134 MB store:
35.0s structure vs 39.2s at 100%. "off" (any case) is the off token; empty means
not-configured, therefore the default; a malformed value falls back to the DEFAULT,
never to structure. A completed check over 5 minutes logs a WARN naming the
duration, the depth and R-401 — operator log only, no hub event, no depth change.
The depth is now recorded with the verdict (LastIntegrityDepth; empty = NOT
RECORDED, never "structure").

R-400: 24 debug-page references, 17 dispatched, 7 dead — three of which fetched on
page LOAD, so those panels were permanently blank. backup/crossdrive implemented;
backup/infra, hub/infra-push, dr/infra-status, storage/watchdog-status and both
storage/simulate-* deleted with their panels and JavaScript.
scripts/debug_route_gate.py fails in both directions and is registered after the
seven were resolved. 18 referenced, 18 dispatched, none orphaned.

Corrections: the dead-field warning in report/types.go said the controller runs no
integrity check and the notifiers are called from nowhere — both false since
v0.227.0. controller.yaml.example gains its missing integrity: block.
integrityCheckTimeout's "ships OFF" comment rewritten.
This commit is contained in:
2026-08-31 10:24:29 +02:00
parent 300d7e87d7
commit 3c49dc8ea4
23 changed files with 1144 additions and 175 deletions
+40 -1
View File
@@ -7,7 +7,46 @@
>
> Ask Claude Code: "Please update CONTEXT.md with what we did today"
Last updated: 2026-08-30 (v0.227.1 — R-359/R-397: the off-site store gets checked)
Last updated: 2026-08-31 (v0.228.0 — R-399/R-400: the check reads the data, the debug page stops lying)
> **2026-08-31 — v0.228.0. TWO RULINGS, recorded so neither is re-litigated.**
>
> **1. The off-site integrity check ships at FULL depth — `--read-data-subset=100%` — and `off` is the
> way back.** Viktor's ruling, 2026-08-31, taken on a measurement rather than a claim: on `demo-hp`,
> 2026-08-30, a pack damaged **without changing its size** made plain `restic check` report
> `no errors were found` and exit clean; every read-data form caught it. Cost on that store
> (140 829 678 B / 2 651 blobs / 67 snapshots): structure 35.0 s, 10% 35.9 s, 50% 37.3 s, 100% 39.2 s.
>
> Three consequences that are decided, not open:
> - **Empty means "not configured", therefore the default.** It does NOT mean off. `off` (any case) is
> the off token, and it exists because a setting with no off switch is not a setting.
> - **A malformed value falls back to the DEFAULT, never to structure.** Falling back to structure
> would silently remove the protection on a typo — R-357's shape, a guard that opens quietly.
> - **The default lives in `internal/backup/offbox_integrity.go`, NOT in `config.applyDefaults`.** Both
> integrity defaults are resolved in one accessor each, beside the argument that justifies them;
> symmetry with the other `Monitoring` defaults is worth less than that.
>
> **The thing a future session will get wrong: there is exactly ONE data point, on a 134 MB store.**
> The cost curves are governed by different quantities — structure tracks the index, read-data tracks
> the data — so nothing here extrapolates. That is why v0.228.0 ships a *notice* (a WARN over 5 minutes
> naming R-401) and NOT a rotation schedule, a size threshold or a bandwidth budget. Every one of those
> would be a number invented from one measurement, which is the shape of the four production designs
> this project has already specced against nothing. **R-401's trigger is that WARN firing on any box,
> not a calendar date.**
>
> **2. Implement or delete FIRST, register the gate SECOND.** R-400 found seven debug-page controls
> with no handler. The gate that makes that impossible (`controller/scripts/debug_route_gate.py`) was
> written and registered only after all seven were resolved — a registered-but-failing gate refuses
> every push, exactly as `instructions_gate` established. The gate is deliberately ten lines: two lists
> and a difference, in both directions, because a cleverer gate needs maintaining and an unmaintained
> gate is how the class hides in the first place. **Keep `handleDebugAPI`'s exact-match switch with its
> `NotFound` default** — a prefix match would have made the original defect invisible instead of merely
> silent.
>
> **The shape worth remembering is worse than "seven dead buttons":** three of the seven fetched on
> page LOAD, so those panels were permanently blank on the page an operator opens when something is
> already wrong.
> **2026-08-30 — v0.227.0/v0.227.1. THREE RULINGS, recorded so none is re-litigated.**
>