Skip to content

[P0] Prove PostgreSQL backup/restore preserves security evidence authority and measured RPO/RTO #239

Description

@seonghobae

Refs #80 #192 #236 #241 #242 #244.

Current status — recovery acceptance executed, protected integration still pending

The original production gap was a real destructive PostgreSQL recovery proof for Wardnet's durable reputation-security authority. That acceptance is implemented by Draft PR #241, but protected/default truth has advanced to main@f8260f1e03836039ff9463dd99fa982e4e270c4b and StateAuthority::Postgres remains disabled. The #241 receipts below are historical old-parent implementation evidence until the Runtime Configuration foundation (#140/#310) is synthesized against current protected main and the PostgreSQL dependency stack is non-force-restacked. Do not confuse branch recovery evidence with production authority or an accepted buyer RPO/RTO.

Current #241 is exact 992d9c366c47515a121b786197c872db81957dcc, Draft, based on exact #236 e1131c2ce1078322b48caa87b2088b1866b08626. Its complete recovery delta is inherited by #242 and #244 in the parked PostgreSQL stack; none of those predecessor receipts transfer after parent/head movement.

Executed physical recovery contract

scripts/postgres_recovery_drill.sh runs against pinned postgres:18.4-bookworm and uses PostgreSQL-native physical recovery rather than a logical-dump substitute:

  • pg_basebackup with backup-manifest verification;
  • archived WAL and a declared PITR target beyond the base backup;
  • destruction of the source data volume before recovery;
  • restore into a fresh PostgreSQL 18.4 instance;
  • ordinary externally managed runtime LOGIN verification, never only state-owner/superuser inspection;
  • FORCE RLS/tenant isolation, immutable generation/publication/audit/current-head/schema evidence and historical ABA/divergent replay rejection after restore;
  • zero lost controlled Wardnet publication transactions in the fixture and a measured non-zero restore duration;
  • one new post-restore runtime publication through the bounded repository;
  • real fail-closed corrupt-manifest, missing-WAL, unreachable-target and partial-role/RLS recovery cases.

A separate scripts/postgres_recovery_role_mapping_guard.sh creates an externally managed LOGIN carrying unsafe CREATEDB, executes the canonical runtime-principal mapper, requires rejection and proves no residual wardnet_runtime membership edge. Backup/WAL credentials remain external infrastructure/IAM authority and never enter repository evidence.

RED → minimum repair → exact GREEN

Hosted CI 34372854983 on exact 78c0d6327f77a9b7d3c3c9e9ffd1fdf0af3edc5d executed the physical drill far enough to parse the recovery receipt, then failed because the Rust acceptance requested partial_schema_or_rls_state_failed_closed while the executed guard emitted partial_role_or_rls_state_failed_closed; it also requested unsafe-role evidence without an executed hostile fixture. This was a test/evidence-contract defect, not a PostgreSQL recovery semantic failure.

The minimum repair aligned the assertion to the executed partial-role/RLS guard and added the separate real unsafe-role mapping hostile fixture. Exact d87acfed4046a4dee5a50c77eff8ddfc77466675 then failed only cargo fmt --check on one deterministic line wrap. Exact 992d9c366c47515a121b786197c872db81957dcc applies only that rustfmt result.

CI 34375192687, rust job 102546106310, was terminal SUCCESS on exact #241 992d9c...: checkout, pinned toolchain, formatting, full locked workspace tests including the destructive PostgreSQL recovery drill and unsafe-role guard, and strict Clippy all passed. Fresh inline review-thread inventory recorded by the owning PR was zero. This is historical predecessor evidence and must be reacquired on the eventual current-base integration head.

What remains outside this acceptance

This controlled fixture proves the recovery mechanism and Wardnet security-state invariants on its tested predecessor lineage. It does not establish production backup cadence, storage-provider durability, encryption-key ownership, cloud/database IAM, accepted buyer RPO/RTO/SLO, or immutable release identity. Those remain aggregate #80/#192/#84/#85 work. #242 and #244 subsequently add real divergent-writer and half-open protocol-progress acceptance on top of this recovery evidence; their GREEN also remains Draft/unreleased and old-parent until foundation-first restack.

A logical dump still cannot substitute for this lane's physical/WAL recovery contract. Backup/WAL provider credentials must remain outside Wardnet application configuration and evidence. No production StateAuthority::Postgres enablement follows from this test alone.

Completion gate

Keep this issue open until #241 or a verified successor preserving the complete recovery scripts/tests/evidence reaches protected main as part of the dependency-first PostgreSQL integration. First synthesize Runtime Configuration #140 with current protected-main auth/runtime semantics through #310 (or a verified complete successor), then restack dependent PostgreSQL PRs non-destructively and reacquire exact-head evidence. The unchanged integration candidate must retain current recovery acceptance together with then-live 100% owned-production coverage/rustdoc, review/thread, security/CodeQL, package/SBOM/provenance/governance and fresh protected-base evidence. Production backup/storage/encryption/IAM and accepted RPO/RTO remain separate release prerequisites even after this issue's code/test delta is protected.

No force update, destructive rebase, self/model approval, routine bypass, gate weakening, mutable foreign dependency, cross-service SQL, source copy, logical-dump-only RPO claim, backup-without-restore claim, fabricated RPO/RTO, or predecessor-evidence transfer.

TRACEABILITY

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions