Backup Attestation

A backup that you cannot prove integrity of is a liability. Every Tetrapus snapshot is hashed into a Merkle root, signed by the Org's audit-scope KMS key, and recorded in backup_manifests. Restore is not just "load the bytes" — it recomputes the root from the restored DB and rejects the restore if the signature doesn't verify.

Lifecycle

graph LR SNAP["pg_dump / wal segment"] --> HASH["sha256 over canonical row order"] HASH --> ROOT["sha256_root"] ROOT --> SIGN["KMS sign_es256(root)"] SIGN --> MAN["backup_manifests row"] MAN --> S3["object store: dump.bin + manifest.json"] S3 -->|months later| REST["pg_restore on target"] REST --> RH["recompute sha256_root"] RH --> VER["KMS verify(signature, root)"] VER -->|ok| OK["restored_verified_at = now()"] VER -->|mismatch| FAIL["restore aborted, alert paged"]

backup_manifests table

Column Type Purpose
idUUIDManifest PK
org_idUUIDTenant
backup_idTEXTObject-store key (e.g. s3://…/2026-04-26.bin)
taken_atTIMESTAMPTZSnapshot wall-clock
sha256_rootBYTEAMerkle root over canonical row hashes
signed_by_kidTEXTJWKS kid for verification
signatureBYTEAES256 r||s, 64 bytes
restored_verified_atTIMESTAMPTZNULL until first successful restore-verify

Canonical row order

"sha256 over the database" is meaningless without canonicalisation — Postgres heap order is allowed to change. The snapshot driver enumerates tables in alphabetical order, then rows in primary-key order, hashing the canonical-JSON form of each row. The leaf hashes feed an RFC 6962-shaped Merkle tree (same construction as audit attestation) and the resulting root is what gets signed.

CLI

tetrapus-admin backup snapshot drives the snapshot from an operator workstation; tetrapus-admin backup verify independently re-validates a manifest against a restored DB.

Bash Take a signed snapshot
tetrapus-admin backup snapshot \
  --org-id  3f2a…             \
  --out     s3://acme-backups/2026-04-26.bin
# wrote 4.7 GiB
# sha256_root  = 9b0c8a3e…
# signed_by    = jwk_audit_2026q2 (KMS arn:…)
# manifest id  = 1aa3-…
Bash Restore-verify against a target Postgres
tetrapus-admin backup verify \
  --manifest    s3://acme-backups/2026-04-26.json \
  --against-db  postgres://restore-staging.local/tetrapus \
  --jwks-url    https://tetrapus.example.com/.well-known/jwks.json
# recomputed sha256_root = 9b0c8a3e…
# signature verified by  jwk_audit_2026q2
# OK: restore matches manifest, restored_verified_at recorded

Why this matters

  • Tamper detection: If anyone modifies the snapshot in object storage, the recomputed root won't match the signed value and restore aborts.
  • Region migration: The signed manifest is the artefact region migration hands off — the new region verifies the signature with the customer's KMS public key before bringing the Org online.
  • Auditor request: "Show me a backup taken on date X". You can produce both the bytes and a third-party-verifiable proof that the bytes are what was taken on date X.
  • Insider risk: Backup operators do not hold the signing key — they can take a snapshot but cannot sign one.

Restore-verify guard

A backup whose restored_verified_at is NULL has never been restore-tested. The platform exposes this metric per Org so operators can alert on "no successful restore-verify in the last 30 days" — turning the once-a-year audit question "do your backups actually restore?" into a continuous metric.

Related

Questions?

Reach out for help with integration, deployment, or custom domain codecs.