OPS-03: despliegue, backup, restore y rollback

Este runbook deja reproducibles las operaciones de la versión 1 sin depender de conocimiento oral. Los comandos son para el checkout del repositorio y usan únicamente datos sintéticos durante la verificación. Nunca se versiona un dump, una URL con credenciales ni la passphrase.

Preflight y despliegue

  1. Crear .env a partir de .env.example y cargar las referencias desde el entorno o desde el gestor de secretos. SCHEMASAFE_DATABASE_URL debe ser una URL PostgreSQL válida y SCHEMASAFE_BACKUP_PASSPHRASE una passphrase de alta entropía. No escribir sus valores en el comando, ticket o log.
  2. Ejecutar el control estático y la configuración de Compose:

bash python scripts/check_deployment_policy.py docker compose config

  1. Desplegar la aplicación y esperar los healthchecks:

bash bash scripts/deploy.sh

deploy.sh usa el perfil app, que inicia PostgreSQL, backend y frontend; --wait y /health hacen que un servicio no saludable detenga la operación.

Backup cifrado

El backup es lógico (pg_dump --format=custom) y se cifra con AES-256-CBC, salt y PBKDF2 mediante OpenSSL. La passphrase se entrega a OpenSSL por nombre de variable (env:), nunca como argumento. El destino debe ser un almacenamiento externo al volumen de PostgreSQL, con retención y acceso administrados por la organización.

mkdir -p backups
export SCHEMASAFE_DATABASE_URL='postgresql://...'
export SCHEMASAFE_BACKUP_PASSPHRASE='valor-proporcionado-por-el-gestor'
python scripts/postgres_backup.py backup \
  --output backups/schemasafe-$(date +%Y%m%d-%H%M%S).pgdump.enc

El archivo resultante queda ignorado por Git. El script crea primero un archivo temporal con permisos restrictivos y solo lo publica de forma atómica cuando el cifrado finaliza.

Restore verificado

El restore es una operación destructiva sobre el destino indicado: usa pg_restore --clean --if-exists --single-transaction. Elegir primero una base de recuperación desechable, detener el tráfico o aplicar la ventana de cambio y verificar el servicio antes de restaurar producción.

python scripts/postgres_backup.py restore \
  --backup backups/schemasafe-YYYYMMDD-HHMMSS.pgdump.enc

La prueba reproducible de CI ejecuta scripts/run_operational_recovery.py --check: crea un marcador sintético, cifra el dump, elimina la tabla, restaura, comprueba el marcador y demuestra que una passphrase incorrecta falla sin continuar hacia pg_restore. Esta prueba no contiene datos reales y no se considera evidencia de restore si alguna etapa falla.

Rollback y volúmenes

Para volver a una versión conocida, el operador debe tener el checkout limpio y un commit/tag previamente validado:

bash scripts/rollback.sh <commit-o-tag-verificado>

El script verifica el checkout, cambia al ref solicitado, levanta de nuevo el perfil app y valida /health. Un rollback de aplicación no elimina ni recrea los volúmenes de datos. Los volúmenes nombrados schemasafe_data y postgres_data son persistentes; los volúmenes de MongoDB, CouchDB y Cassandra pertenecen a sus perfiles de prueba. docker compose stop conserva datos. docker compose down -v está prohibido en el runbook normal porque destruye la base local; solo puede usarse con una decisión explícita de limpieza.

Los backups viven fuera de esos volúmenes y se gestionan mediante la política de retención externa. El repositorio no promete RPO/RTO ni retención legal sin una configuración concreta del proveedor.

Seguridad, límites y evidencia

El workflow ejecuta secret-scan, dependency-scan (Python con pip-audit y frontend con npm audit) y ops-recovery. El gate de release depende de esos jobs además de las pruebas, build, Compose, escenarios y PostgreSQL.

Si faltan pg_dump, pg_restore, openssl, la URL o la passphrase, la operación falla con un mensaje acotado y no registra valores sensibles. Un restore con passphrase incorrecta o dump corrupto no se reporta como exitoso. La automatización solo valida recuperación lógica de PostgreSQL; no cubre respaldos físicos, replicación, cifrado gestionado por KMS, restauración de volúmenes Docker ni una base NoSQL. Esas limitaciones deben permanecer visibles en la evidencia de despliegue.