# Campaign 10 — closeout: two last measurements, then teardown (2026-08-02) **Companion doc** (my call, per the task) to `CAMPAIGN-10-two-storage-soak-2026-07-31.md` and `SPIKE-recovery-unit-space-2026-08-02.md`, rather than appending — those two are already long and this session answers two specific questions and then dismantles the rig. **Part 1 headline:** Q1 **lowers** R-158's rank — the failure *is* customer-visible, on one page, and it persists and clears correctly. Q2 **clears** `ValidateDump` of shipping bad dumps, and simultaneously **kills C2's proposed gate** on its current predicate. --- ## Q1 — when a backup refuses for lack of space, what does the customer see? Method: ballast `/mnt/sys_drive` to 699 MB free (homebox's unit needs 2.3 GB), run the real backup through `POST /api/backup/run`, and read every customer-facing surface through the real UI endpoints. ### The five points | # | Surface | Result | |---|---|---| | 1 | **`/backups` overview** | **SHOWS IT** — `✗ Adatmentés sikertelen` | | 2 | **`/backups/apps`** (per-app) | **shows nothing** — Homebox tier-1 reads `Utolsó: 3 perce` | | 3 | `/stacks/homebox` (app detail) | **shows nothing** | | 4 | `/` dashboard · `/launcher` | **show nothing** — no banner | | 5 | `GET /api/backup/status` | `db_dump.success: **false**` | | — | hub event / email | **none** (R-158) | Exact copy, as rendered on `/backups`: ✗ Adatmentés sikertelen ### The point-5 question — retry, stay failed, or quietly go green? **It retries, stays failed, and does not lie.** Measured across three runs: | run | condition | `status.success` | `/backups` shows failure | unit mtime | |---|---|---|---|---| | 1 | constrained | false | **true** | 07:30:50 | | 2 | still constrained | false | **true (persists)** | 07:30:50 (unchanged) | | 3 | space freed | **true** | **false (cleared)** | **07:37:38 (fresh)** | **`/backups/apps` is honest, not deceptive.** Its `Utolsó: 3 perce` tracks the *unit's real mtime* (07:30:50), not the failed run's timestamp — so it correctly reports the age of the last good unit. It simply never says the latest attempt failed. **This is NOT the R-156 family**: no surface claims a fresh backup over a stale unit. ### R-158's rank — LOWERED, with the reason > **R-158 is a notification gap, not a silent-failure defect. It ranks BELOW R-157.** Because the customer *can* find out by looking, and the indicator behaves correctly — it persists while failing and clears on recovery. What is missing is that **nothing pushes it**: no hub event, no email, no dashboard banner. And the discovery path is poor in a specific way worth fixing: **the per-app backup page — the natural place to ask "is homebox backed up?" — shows no failure at all**, while the answer lives one page away on the overview. R-157 outranks it because R-157's mechanism B leaves a `deployed: true` app **not running**, with the deadapp check reporting `0 currently down` — silent on *every* channel, including the one the customer would look at. --- ## Q2 — was `ValidateDump`'s warning correct? The warning, seen twice: [WARN] [backup] ValidateDump: …/rallly-postgres.sql is structurally valid (32 tables) but its accounts table has NO rows — the dump may predate the customer's data ### It was factually correct, and the dump was NOT deficient The live database genuinely had no accounts. Every non-empty table, from `pg_stat_user_tables`: _prisma_migrations | 129 cc_proof | 82 <-- the campaign's own canary instance_settings | 1 accounts | 0 **An empty table proves nothing either way**, so — as the task required — an account was **seeded** and the backup re-run: INSERT users (id='c10user', …) -> 1 row INSERT accounts (id='c10acct', …) -> 1 row Result: [INFO] [backup] DB dump: rallly-postgres → rallly-postgres.sql (100.6 KB, 396ms, 32 tables) (no ValidateDump line at all — the warning STOPPED) grep -c c10acct = 1 grep -c c10user = 2 dump size 102 766 B -> 103 029 B **Verdict: the validator is sound and no bad dumps are shipping.** It correctly detected an empty `accounts` table, and the moment real data existed the dump captured it and the warning cleared. *(Seeded data disclosed: one `users` row and one `accounts` row, both `c10*`-prefixed, on a scratch customer that this session then deletes.)* ### What it does to C2's ordering — the proposed gate is DEAD on this predicate C2 proposed dropping the DB volume tar (halving DB-app units, and closing the D5/R-127(b) initdb-skip password trap) **once `ValidateDump` is promoted from a warning to a gate**. That ordering does not survive Q2: > **A fresh appliance legitimately has zero accounts.** Gating on "the `accounts` table has rows" would > **block the backups of every new customer** until someone registers a user — refusing good backups > for the entire period a box is most fragile. The validator's *fact* is right and its *inference* ("may predate the customer's data") is wrong: there was no data to predate. So the dependency chain is longer than C2 assumed: 1. a **sound gate predicate** first — a comparison against the **live** DB (per-table row counts in the dump vs `pg_stat_user_tables`) rather than an absolute expectation about one table; 2. **then** the warn→gate promotion; 3. **only then** the tar-drop. **Until (1) exists, the DB volume tar stays load-bearing** — not because dumps are bad, but because nothing can yet *prove* a given dump is good. --- ## Findings **No new `R-n`.** Register grepped (`documentation/backlog/*.md`) for `ValidateDump`, `accounts table`, `Adatmentés sikertelen`, and the per-app backup page: no existing rows, and neither Q1 nor Q2 produced a defect that is not already covered. - **Q1 does not mint an R** — it *re-ranks* R-158 (filed in the spike) and adds the specific improvement worth making: surface the per-app failure on `/backups/apps`, where a customer looks for a specific app. - **Q2 does not mint an R** — it *removes* a proposed change (the gate) and lengthens C2's dependency chain. Recording that a design is wrong is the spike rule working. Nothing fixed, per the fences.