Saltar a contenido

PDF-004E Staging Postgres Restore Drill

Fecha local: 2026-06-19

Estado: RESTORE DRILL REAL EJECUTADO / CLEANUP COMPLETO / GO PDF-004F PREFLIGHT / NO-GO DDL EJECUCION / NO SECRETS / STAGING INTACTO / SANDBOX INTACTO

portal_visible = yes

Scope: tenant

tenant_id: alpuntodeventa

Owner: Gabi / Carlos Canu

Fuente de verdad: docs/tenants/alpuntodeventa/business-observer/production/PDF-004E-STAGING-POSTGRES-RESTORE-DRILL.md

1. Autorizacion explicita

El usuario autorizo PDF-004E: ejecutar restore drill real del backup baseline de PostgreSQL staging Business Observer en el VPS, usando un entorno temporal aislado, sin tocar el PostgreSQL staging principal, sin tocar openclaw-postgres-sandbox, sin crear DB/roles/schema/tablas de negocio en el staging principal, sin ejecutar sync/scheduler, sin tocar produccion, sin exponer secretos y documentando evidencia, validacion y cleanup/rollback.

2. Safe point

Control Valor
workspace C:\APV\openclawai
rama main
HEAD/origin observado al iniciar 8f0313d77d8bb64715d3fc98219edff44a44173c
ultimo commit observado al iniciar ops: execute business observer staging postgres backup baseline
decision SAFE POINT PASS / RESTORE DRILL TEMPORAL AISLADO

3. Validacion local de arranque

Control Resultado
git status -sb PASS ## main...origin/main
git rev-parse HEAD PASS 8f0313d77d8bb64715d3fc98219edff44a44173c
git diff --check PASS limpio al iniciar
MkDocs strict PASS con .\\.venv-portal\\Scripts\\mkdocs.exe build --strict

Nota operativa local: la ruta literal ..\\.venv-portal\\Scripts\\mkdocs.exe no existe desde C:\APV\openclawai; la venv disponible para este repo es .\\.venv-portal.

4. Backup source

Campo Valor
directorio /opt/backups/openclaw/business-observer-staging/postgres/baseline/20260619T170037Z/
archivo openclaw-bo-staging-postgres-baseline-20260619T170037Z.dump
formato pg_dump -Fc
database origen postgres bootstrap
tamano esperado 1032 bytes
tamano observado 1032 bytes
sha256 esperado 402dce45fe93936b12f17a54ee437d637b3c573d02a3ff5c506d83e48a3860c4
sha256 observado 402dce45fe93936b12f17a54ee437d637b3c573d02a3ff5c506d83e48a3860c4
pg_restore --list PASS total_lines=15 metadata_lines=15 toc_entries=0

5. Preflight VPS

Comandos remotos ejecutados por ssh -o BatchMode=yes openclaw-vps, sin imprimir secretos ni contenido del dump.

Control Observado
hostname srv977009
uptime up 2 weeks, 4 days, 13 hours
disco / 96G total, 29G usado, 68G disponible, 30%
memoria 7.8Gi total, 5.9Gi available
swap 4.0Gi total, 4.0Gi free
imagen restore postgres:16.14-alpine disponible
staging principal openclaw-business-observer-postgres-staging running healthy
staging host port binding {}
sandbox guardrail openclaw-postgres-sandbox running healthy
backup file PASS existe
backup size PASS 1032 bytes
backup sha256 PASS 402dce45fe93936b12f17a54ee437d637b3c573d02a3ff5c506d83e48a3860c4
colisiones temporales PASS ninguna para container, volume, network, secret dir ni work dir

6. Recursos temporales creados

Recurso Valor
container openclaw-bo-postgres-restore-drill-20260619T170037Z
volume openclaw_bo_postgres_restore_drill_20260619T170037Z_data
network openclaw-bo-restore-drill-20260619T170037Z-internal
network policy internal=true
secret temporal /opt/secrets/openclaw/business-observer-staging/restore-drill-20260619T170037Z/postgres_password
secret permissions root:root 600, sin imprimir valor
path temporal /opt/stacks/business-observer-staging-restore-drill/20260619T170037Z/
host port binding temporal {}
imagen postgres:16.14-alpine

Validacion despues de crear recursos:

text temp_status=running temp_health=healthy temp_ports={} temp_network_internal=true temp_volume=openclaw_bo_postgres_restore_drill_20260619T170037Z_data temp_secret_stat=root:root 600 staging_principal=running healthy sandbox=running healthy

7. Metodo de restore

Se ejecuto pg_restore real dentro del contenedor temporal contra la DB bootstrap postgres del entorno temporal.

Primer intento operativo:

  • comando: docker exec -u postgres ... pg_restore --exit-on-error -d postgres ...
  • resultado: exit_code=1
  • causa: Permission denied al leer el backup montado readonly, porque el dump baseline esta protegido como root:root 600
  • impacto: sin cambios en staging principal, sin secretos expuestos y sin DDL/DML fuera del contenedor temporal

Metodo final aplicado:

  • comando: docker exec ... pg_restore --exit-on-error -U postgres -d postgres ...
  • motivo: mantener el dump root:root 600 sin relajar permisos; el proceso root del contenedor temporal lee el archivo y conecta localmente como postgres
  • passwords inline: NO
  • contenido del dump impreso: NO

Resultado final:

text pg_restore_exit_code=0 pg_restore_stdout_bytes=0 pg_restore_stderr_bytes=0 temp_after_restore_status=running temp_after_restore_health=healthy

8. Validaciones post-restore

Validaciones ejecutadas solo dentro del contenedor temporal:

Control Resultado
current_database() postgres
server_version 16.14
DB count 3
non-system schema count 1
openclaw_business_observer_staging en temporal false
schema business_observer en temporal false
roles business observer en temporal 0

Interpretacion:

  • el restore real ejecuto correctamente sobre el entorno temporal;
  • toc_entries=0 es consistente con un backup baseline bootstrap sin objetos de negocio;
  • la unica presencia no-system esperada es public del bootstrap PostgreSQL;
  • no aparecieron DB, schema ni roles de negocio.

9. Staging principal intacto

Validacion ejecutada en el staging principal dentro de transaccion READ ONLY.

text transaction_read_only=on business_db_exists=false business_schema_exists=false business_role_matches=0

Confirmado:

  • no se creo openclaw_business_observer_staging;
  • no se creo schema business_observer;
  • no se crearon roles staging de negocio;
  • no se ejecuto DDL ni DML en el staging principal;
  • no se ejecuto SOURCE-003;
  • no se ejecuto sync/scheduler.

10. Sandbox intacto

openclaw-postgres-sandbox se mantuvo running healthy antes, durante y despues del drill.

No se uso como staging, no se le aplico restore y no se modifico.

11. Cleanup

Cleanup completo ejecutado despues del restore exitoso:

Recurso Resultado
container temporal container_absent=PASS
volume temporal volume_absent=PASS
network temporal network_absent=PASS
secret dir temporal secret_dir_absent=PASS
work dir temporal work_dir_absent=PASS

Health final:

text openclaw-business-observer-postgres-staging status=running health=healthy ports={} openclaw-postgres-sandbox status=running health=healthy PDF004E_REMOTE_RESULT=PASS

Recursos temporales remanentes: NINGUNO.

12. Confirmaciones de seguridad

  • sin host port binding en el contenedor temporal;
  • sin host port binding en staging principal;
  • sin passwords inline;
  • sin leer ni imprimir secret file real del staging;
  • sin imprimir secret temporal;
  • sin guardar dumps/backups/sql en Git;
  • sin tocar La Directa;
  • sin tocar SGC productivo;
  • sin tocar produccion;
  • sin push;
  • sin deploy portal.

13. GO / NO-GO

text GO = PDF-004F DDL BUSINESS OBSERVER CANDIDATE/PREFLIGHT NO-GO = DDL EJECUCION EN STAGING SIN AUTORIZACION EXPLICITA SEPARADA NO-GO = PRODUCCION NO-GO = SYNC DIARIA / SCHEDULER

14. Riesgos pendientes

  • El backup baseline actual cubre solo el catalog bootstrap postgres; antes de cargas reales, los backups posteriores deberan incluir objetos de negocio.
  • El primer intento demostro que los dumps root:root 600 requieren un metodo de restore compatible con permisos restrictivos.
  • PDF-004F debe preparar DDL candidate/preflight sin ejecutar cambios hasta una autorizacion separada.

15. Proximos safe points

  1. PDF-004F DDL business observer candidate/preflight
  2. autorizacion explicita y separada para ejecucion DDL staging
  3. backup posterior al DDL si se autoriza y ejecuta
  4. produccion y sync diaria siguen bloqueadas

16. Conclusion

text PDF-004E PASS RESTORE DRILL REAL = EXECUTED IN TEMPORARY ISOLATED POSTGRES PG_RESTORE_EXIT_CODE = 0 TOC_ENTRIES = 0 CONSISTENT WITH BOOTSTRAP BASELINE TEMP HOST PORT BINDING = {} CLEANUP = COMPLETE TEMP REMNANTS = NONE STAGING PRINCIPAL = RUNNING HEALTHY / PORTS {} BUSINESS DB = ABSENT BUSINESS SCHEMA = ABSENT BUSINESS ROLES = ABSENT SANDBOX = RUNNING HEALTHY / INTACT NO SECRETS EXPOSED GO = PDF-004F DDL CANDIDATE/PREFLIGHT NO-GO = DDL EXECUTION WITHOUT EXPLICIT AUTHORIZATION NO-GO = PRODUCTION / DAILY SYNC