Verified, restorable PostgreSQL backups#976
Open
atomantic wants to merge 18 commits into
Open
Conversation
…ent-relative manifest key
… flag degraded in dashboard widget
…ore, DEFAULT_STATE.pgBackup, restore-path tests
…n dump for live-DB restore, unlink partial dumps, degraded in City vault
…_BACKEND=postgres) is unreachable; defer manifest-hash restore-verify
…arning in review queue, not high-severity failure
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PortOS treats PostgreSQL as an optional accelerator (Memory + creative catalog live there; everything else is file-based, and
pgMode='file'runs with no DB at all). Every backup snapshot already dumped Postgres alongside the rsync ofdata/, but the dump result was silently swallowed — a missing/failedpg_dumpreportedstatus: 'ok'with a green file count, the dump was unverified and unhashed, there was no restore path, and the UI never surfaced DB-backup state. This makes the DB data PortOS already stores genuinely recoverable.This is backup-mechanism only — no on-disk
data/format change, no data migration, and Postgres stays optional (skippedis a first-class, benign outcome).What changed
dumpPostgresreturns an explicit, verified status —ok(withsizeBytes+tableCount) /skipped(no PG — file mode, benign) /failed(pg_dump_missing|dump_error|empty_dump). A 0-byte/truncated dump that exits 0 is now caught.runBackuppropagates the outcome — a failed dump degrades the backup to a newdegradedstatus (files still saved);skipped/okstayok. The full result is persisted aspgBackupin backup state, and the dump is hashed into the snapshot manifest.BACKUP_DB_DUMP_FAILED) that toasts even on unattended scheduled runs (via a newgetIo()accessor), and the dashboardBackupWidgetflagsdegradedas a warning.restorePostgres+POST /api/backup/restore-db— dry-run by default, same path-traversal guard asrestoreSnapshot, refuses a real restore when the DB is unreachable (no half-restore).ui/Modal, dry-run preview then confirm).Design docs
docs/superpowers/specs/2026-06-05-verified-pg-backup-design.mddocs/superpowers/plans/2026-06-05-verified-pg-backup.mdTest Plan
backup.test.js(dump status branches, degraded mapping, restore) +routes/backup.test.js(restore-db route + validation)severity:'warning'-dropped-toast seampg_dumpmissing → expectdegradedstatus + warning toast; Restore DB dry-run preview → confirmKnown follow-up
runBackupintegration test (the pg-status wiring is currently covered by the purebackupStatusForPghelper + code-reading) — recorded in the plan doc.