Backups and recovery

Use built-in commands for SQLite or PostgreSQL snapshots taken in one read transaction. The output directory must not exist. manifest.json records format, schema, application version, database engine, deployment-file SHA256, data checksum and key ID. database.jsonl contains logical rows. Files use 0600; directories use 0700. Keep YAML, environment values and Vault data separately, with the encryption key outside the backup directory.

mcphub backup --config config.yaml --output ./backup-20261003
mcphub verify-backup --config config.yaml --backup ./backup-20261003
mcphub restore --config config.yaml --backup ./backup-20261003 --into ./recovery/config.db

verify-backup checks checksum and key, restores into a temporary SQLite database, reads configuration and identities, and records the drill. PostgreSQL requires --into MCPHUB_DRILL_DSN pointing to a dedicated empty database, with its DSN stored in that environment variable. Restore requires the same engine, current schema and matching key. The SQLite destination must not exist; PostgreSQL must be empty.

Restore revokes old login/refresh sessions, Broker/service grants, unfinished device authorizations and approvals, and rotates signing keys in the same transaction. Users must log in and consent again. The source database is unaffected. Start the recovered copy in isolation and verify login, catalogs, credentials and actual read calls before switching production. Operations shows the latest backup and database restore check. Database reads alone do not establish successful business recovery. This is disaster recovery for new deployments, without old-configuration or database migration instructions.