Skip to content

fix: move production database backups to private storage - #118

Merged
abrichr merged 1 commit into
mainfrom
codex/database-backup-restore-proof
Aug 8, 2026
Merged

fix: move production database backups to private storage#118
abrichr merged 1 commit into
mainfrom
codex/database-backup-restore-proof

Conversation

@abrichr

@abrichr abrichr commented Aug 8, 2026

Copy link
Copy Markdown
Member

Outcome

Moves the scheduled production database backup out of public GitHub artifacts and into a private, public-access-blocked S3 bucket after client-side age encryption.

Safety contract

  • binds the production database URL to the exact declared Supabase project;
  • stores only ciphertext and a redacted manifest in S3;
  • uses an exact GitHub OIDC environment trust and least-privilege writer role;
  • refuses empty or schema-only dumps;
  • rejects local shell, file, and COPY PROGRAM commands in restored SQL;
  • verifies ciphertext, plaintext, archive members, dump hashes, and the inner/outer contract binding before psql runs;
  • refuses the production project as a restore target;
  • measures database-only RPO and RTO without claiming private Storage recovery; and
  • keeps the age private key on the trusted operator device.

Infrastructure and cost

The included CloudFormation template targets AWS account 992382684924. It creates a private versioned S3 bucket, 90-day backup retention, 365-day drill-evidence retention, an exact GitHub OIDC writer role, and an exact local restore role. It uses SSE-S3 and does not create a paid KMS key or enable Supabase PITR. S3 Standard is about USD 0.023 per GB-month plus requests.

Verification

  • 141 tests pass.
  • Documentation validation passes.
  • Strict MkDocs build passes.
  • ShellCheck passes.
  • actionlint passes.
  • CloudFormation validation passes in AWS account 992382684924.

Not yet claimed

No production backup or scratch restore ran. No AWS resource was created. An AWS administrator must deploy the stack because claude-ops lacks cloudformation:CreateChangeSet. GitHub still needs the protected production-backup environment and database secrets. The private age key needs a confirmed second vault or offline copy. A new scratch Supabase project is also required. The database-only drill cannot replace the canonical Cloud database-plus-Storage drill.

@abrichr
abrichr merged commit 8b060c2 into main Aug 8, 2026
5 checks passed
@abrichr
abrichr deleted the codex/database-backup-restore-proof branch August 8, 2026 16:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant