TRUSTIVAN ships backup and restore tooling as operator scripts (infra/scripts/backup.sh, restore.sh, restore-drill.sh), not as a managed backup service. This page states what those scripts do today, plainly, including the gaps — a number nobody would act on if it turned out to be wrong is worse than no number at all.

What is backed up

PostgreSQL, including roles and privileges. A pg_dump of the schema and its data, plus a separate pg_dumpall --roles-only of the cluster’s login roles. Both matter: the application connects as narrow, non-superuser roles (trustowl_app_login, trustowl_job_login) that row-level security binds, and those roles are cluster objects a plain database dump does not carry. Restoring the data without them produces a database RLS does not enforce, or one every query is refused against — see Data protection for why the role matters this much. Encrypted before it leaves the host that took it, to a recipient — the production host holds no key that can decrypt its own backups. Redis is not backed up. It holds queue state and rate-limit counters, both reconstructable, never a customer’s security findings.

What is not backed up, or not yet proven

  • Off-host storage has been drilled only against a local rclone target, not a real S3-compatible bucket with production credentials. Until that drill runs against real object storage, treat the off-host copy as configured but unproven in your environment.
  • The age decryption identity’s storage location is an operator decision, documented as needing to live off the production host. Nothing in the software enforces that placement — verify it in your own deployment.
  • The Kubernetes / managed-Postgres deployment path has no backup gate wired into it today. The Compose deployment path does; a managed Postgres provider’s own backup and PITR features are the appropriate substitute if you deploy that way, and are not something TRUSTIVAN configures for you.
These are stated as blockers to a stronger RPO/RTO claim, not as completed capabilities.

RPO and RTO, as shipped

Neither number has been validated against production traffic or production infrastructure — both are measured against a local drill. Treat them as engineering targets you re-verify in your own environment, not as an SLA.

The restore drill, and what it proves

restore-drill.sh restores from the off-host copy into a new database (never over a live one), and checks, in order:
  1. The schema version matches what the restoring build expects.
  2. tenant_isolation policies exist on the restored tables.
  3. Per-role grants exist for both the application and job-plane roles — a restore that carries the data and the policies but not the privileges produces a database that refuses every query, which looks identical to “the restore worked” until the first request.
A weekly timer runs it and writes a dated artefact — “we have backups” is a belief; a file recording that a restore from off-host storage completed on a given date, with the checks it passed, is evidence. See Audit trail for the parallel principle applied to the identity trail.

Retention

Local encrypted backups are pruned after BACKUP_RETENTION_DAYS (default 30). Off-host retention is not currently governed by this tooling — set a lifecycle rule on whatever object storage you configure.

See also

  • Data map — what is stored, encrypted or not, and for how long, independent of backups.
  • Environment configuration — BACKUP_DIR, BACKUP_PUBLIC_KEY, BACKUP_REMOTE, BACKUP_RETENTION_DAYS.