--- id: RISK-F-0006 type: finding title: "apps-pg has no backup configured at all: R0 means no recovery" status: fixed owner: risk-nexus reported_by: railiance-platform reported_via: flex-auth routed_by: risk-nexus date_reported: "2026-08-17" date_filed: "2026-08-19" system: railiance-platform environment: production fix_owner: railiance-platform fix_tracking: RPF-WP-0019 (finished) related: [RISK-F-0001] # Graded by risk-nexus 2026-08-19 — docs/rulings/2026-08-19-second-grading.md severity: high severity_at_production: critical impact: I4 likelihood: L2 fidelity_modifier: false production_rescore: true disclosure: public publication: pending-handover publication_id: risk-f-0006-apps-pg-no-backup publication_path: "findings/apps-pg-no-backup/v1/index.html" publication_subtitle: "A shared production database had no backup or recovery path; encrypted off-host backup and a demonstrated restore closed the gap." revision: "fixed-1" last_reviewed: "2026-08-21" review_interval: 6m embargo_lifted: "2026-08-20 — backup live, restore demonstrated with matching row counts" embargo_was_since: "2026-08-19" escalation: answered escalation_trigger: 3 escalation_status: answered date_fixed: "2026-08-20" escalation_answered: "2026-08-19" escalation_answered_by: the-custodian escalation_act: approve decision: "spend for apps-pg backup storage approved; no ceiling stated" last_checked: "2026-08-21T07:32:09Z" next_check: "2026-08-21T07:32:09Z" cadence: instant clean_streak: 0 graded_by: risk-nexus ruling: RISK-RULING-2026-08-19-B checked_by: "risk-nexus" --- # RISK-F-0006 — the platform database cannot be recovered ## What is true, as reported `apps-pg` (`railiance-platform`) has no backup configured at all: no `barmanObjectStore`, no retention policy, and `BestEffort` QoS on the pod. Reported in the same round as `RISK-F-0001`, whose author noted that `R0` here means **no recovery**, not merely no erasure policy. Not verified by this repo. `railiance-platform` owns it. ## Why it is graded highest of the round despite being the least exciting The other findings in this round are about someone reaching something. This one is about nothing coming back. There is no attacker in it and no clever step — an ordinary node failure, a lost volume, a mistaken `DROP`, and the data that was in `apps-pg` is gone. `BestEffort` QoS makes the pod the first candidate for eviction under memory pressure. Eviction alone is an availability event and recoverable. What is not recoverable is anything that damages the volume, and that is the case with no answer today. ## Register ruling — 2026-08-19 `high` today (`I4` × `L2`, non-adversarial reading), `critical` at production, embargoed, and **escalated on trigger 3 (spend)**. `I4`: `apps-pg` is shared platform infrastructure, so the loss is not confined to one system, and it is unrecoverable rather than degraded. `L2` on the non-adversarial reading the scale gained for this finding: irrecoverable loss needs a volume or corruption event, which is an ordinary failure the estate has seen the shape of but not an expected weekly occurrence. `production_rescore: true`: at production this is `L3`, because the surface area of ordinary operational events grows with real traffic and real operators. **Escalation, trigger 3.** Object storage for backups is recurring spend that is not currently committed, and no repo can authorise it for itself. The ask is narrow: approve a backup target and its cost, or state that the estate accepts running `apps-pg` with no recovery and for how long. The second is a legitimate answer in build mode and needs saying out loud rather than happening by default. The disclosure condition deliberately includes a demonstrated restore. A backup nobody has restored from is a claim, not a control — the same class of error as the gate in `RISK-F-0002`. ## Reviews - **2026-08-19** — filed and graded from `RISK-F-0001`'s unfiled list. Open at review: has the spend been ruled on; is a backup configured; has a restore been demonstrated; does `railiance-platform` track it anywhere. ## Operator decision — 2026-08-19: approved The spend is approved. `railiance-platform` may provision backup storage for `apps-pg` without returning for authorisation. No ceiling was stated, so none is recorded. The register asks `railiance-platform` to report the actual target and its monthly cost once chosen; a figure materially above the trigger-3 band (recurring €50/month) comes back for confirmation rather than being assumed covered. That is the register being careful with an open approval, not a condition on it. **What is now blocking is work, not permission.** The finding stays `open` at `high`, and the embargo condition is unchanged: a backup exists **and** a restore has been demonstrated once. A backup nobody has restored from is a claim, not a control. `fix_tracking` is still `unset` and is now `railiance-platform`'s to open. ## Reviews - **2026-08-19** — escalation answered, spend approved. Open at review: is a backup configured; has a restore been demonstrated; what does it cost. - **2026-08-20** — clean check: checked against the inbox and the owner's record; nothing moved. Cadence instant → 1h (1 clean in a row); next check 2026-08-20 11:02Z. ## Check — 2026-08-21: fixed, and the evidence was read rather than taken `railiance-platform` finished `RPF-WP-0019` on 2026-08-20. This register read their evidence file rather than accepting the report: `railiance-platform/docs/evidence/RPF-WP-0019-backup-restore-2026-08-20.md`. - Governed target live at `s3://railiance-platform-pg-backup/platform-pg/apps-pg/`, 30-day retention, continuous WAL. - `apps-pg-daily-20260820204148` completed in 8s, `LastBackupSucceeded=True`. - **A separately named scratch cluster restored both consumer databases in 56s, with exact database sizes and all 13 `coulomb_social` user-table row counts matching.** The scratch namespace was deleted; production stayed `Ready`. **The embargo condition required a demonstrated restore and got one.** That condition existed because a backup nobody has restored from is a claim, not a control — and the demonstration is the difference between this finding closing and merely appearing to. They also fixed something the grading had cited but not asked for: `apps-pg-1` moved from `BestEffort` to `Burstable` QoS, with requests and limits, which was part of why `L2` rather than `L1`. And their evidence records a failed first WAL attempt against the wrong prefix rather than only the successful one, which is the standard this register keeps asking of reporters. `fixed`, `public`, escalation closed. The spend approved on 2026-08-19 has a real target behind it. - **2026-08-21** — not clean: owner replied; see the dated check section Cadence 1h → instant; checked again immediately.