Backup and restore posture for persistent data is evidenced in the repo
Why it matters
This is an evidence-pointer check: it verifies committed evidence of the backup and restore control, which is exactly what an auditor will ask for. It evidences SOC 2 A1.2 (backup and recovery infrastructure) and supports A1.3 and CC7.5 (recovery testing and incident recovery). Auditors do not accept "Supabase probably handles it": they want to see where backups are configured and, crucially, how a restore would actually be executed and by whom. AI-generated and vibe-coded apps typically fail both halves. The scaffolded stack leans on platform defaults nobody has confirmed (Supabase free tier has no PITR; daily backups are not restore rehearsals), and no human ever writes the restore runbook because "how do I restore prod" is not a prompt anyone types until the day the table is already dropped. The GitLab 2017 database incident is the canonical case: five backup mechanisms existed on paper, none restorable when needed, roughly six hours of production data lost. A committed IaC flag or ops doc plus a restore procedure is cheap insurance and the minimum artifact a SOC 2 readiness assessment expects.
Severity rationale
Medium because missing backup and restore evidence does not itself expose data, but it turns any destructive incident (bad migration, dropped table, ransomware) into unbounded data loss and stalls the SOC 2 availability criteria until the evidence exists.
Remediation
Commit both legs of the evidence. Backup leg: either an IaC setting (backup_retention_period = 7 on an aws_db_instance, point_in_time_recovery on DynamoDB, backup_configuration { enabled = true } on a GCP google_sql_database_instance), a scheduled dump job (a pg_dump step in .github/workflows/backup.yml or a Vercel/Supabase cron), or an ops doc such as docs/ops/backup-restore.md stating the platform-managed arrangement ("Supabase Pro, PITR enabled, 7-day window"). Restore leg: in the same doc or a scripts/restore-db.sh, write the concrete restore procedure — the exact commands or the dashboard path plus who is authorized to run it. Platform-managed backups documented in a committed ops doc are acceptable auditor evidence; undocumented platform defaults are not.
Detection
- ID:
backup-and-restore-posture-documented - Severity:
medium - What to look for: First determine whether a persistent data store exists: migrations (
supabase/migrations/,prisma/migrations/,drizzle/,migrations/,alembic/versions/, Gomigratefiles), an ORM schema (prisma/schema.prisma,drizzle.config.ts,schema.rb, SQLAlchemy models), or a DB driver/client in the manifest (pg,mysql2,@supabase/supabase-js,mongodb,mongoose,better-sqlite3; Pythonpsycopg2/sqlalchemy; Godatabase/sqldrivers). If none, skip. If a store exists, hunt for BOTH legs. Backup leg: IaC backup config in*.tf/ CDK / Pulumi (backup_retention_period> 0,point_in_time_recovery,backup_configuration,deletion_protectionalongside snapshot settings); a scheduled dump job in the repo (pg_dump/mysqldump/mongodumpin.github/workflows/*.yml,vercel.jsoncrons,supabase/functions/*, aMakefileorscripts/backup*invoked by a scheduler); OR a committed ops doc (docs/ops/*.md,docs/runbooks/*.md,README,RUNBOOK.md,docs/backup*) stating the platform-managed arrangement, e.g. "Supabase PITR enabled, 7-day window" or "Neon point-in-time restore". Restore leg: a restore script (scripts/restore*,pg_restoreusage), or a restore runbook/section in the same doc containing the actual commands or the dashboard path plus who runs it. - Pass criteria: A persistent data store exists AND both legs are present: (1) backup evidence via IaC config, an actually-scheduled dump job, or an ops doc naming the platform arrangement; (2) restore evidence via a restore script or a runbook section with concrete commands or dashboard path plus owner. A committed ops doc covering both legs passes on its own; that is exactly the evidence a real auditor accepts.
- Fail criteria: A persistent data store exists and either leg is missing. Sneaky variants that still FAIL: a backup script in
scripts/that no workflow, cron, or doc ever invokes (unwired); a backup workflow that is commented out orif: false; IaC withbackup_retention_period = 0orskip_final_snapshot = trueand no other backup evidence; a doc that says "backups: TODO" or names the platform without stating the arrangement; backup evidence present but no restore procedure anywhere (backup-only is half a control). Do NOT fail for missing recency ("last tested date"): recency is not verifiable from a repo and is out of scope. - Skip (N/A) when: No persistent data store: no migrations, no ORM schema, no DB driver in the manifest. Quote:
"No migrations, ORM schema, or database driver — project has no persistent data store". - Before evaluating, quote: The data-store evidence (migration dir or driver name), then for each leg the file path plus a 1-3 line excerpt: the IaC backup setting, the schedule line of the dump job, or the ops-doc sentences stating the backup arrangement and the restore procedure. If a leg is missing, quote the closest near-miss found (e.g. the unwired script path) or state that no candidate files matched the enumerated globs.
- Report even on pass:
"Backup leg: <iac-config | scheduled-job | ops-doc> at <path>; restore leg: <script | runbook> at <path>". - Detail on fail:
"supabase/migrations/ has 14 migrations but no IaC backup config, no scheduled dump job, and no ops doc stating a platform backup arrangement — commit evidence (e.g. docs/ops/backup-restore.md) of the Supabase plan's backup/PITR setup plus a restore procedure"or"terraform/rds.tf sets backup_retention_period = 7 but no restore script or runbook exists anywhere — backup leg passes, restore leg missing". - Remediation: Commit
docs/ops/backup-restore.md(or wire IaC flags likebackup_retention_period = 7) covering both legs: what backs the data up (platform arrangement, IaC setting, or scheduledpg_dumpjob) and exactly how to restore (commands or dashboard path plus who runs it). Platform-managed backups documented in a committed ops doc are valid evidence. Deeper operational coverage:database-design-operations.
External references
- soc2:2017 · A1.2 — Availability — backup and recovery infrastructure (also evidences A1.3, CC7.5)
- iso-27001:2022 · A.8.13 — Information backup
- nist:rev5 · CP-9 — System Backup
Taxons
History
- 2026-07-03·v1.0.0·Initial soc2-readiness v1 authoring — merged owner of backup and restore evidence, requiring both a backup leg and a restore leg committed to the repo.·by soc2-readiness-v1-build