Skip to content

Remote-Pulse: verificación del dump antes de publicar y retener

Estado acreditado al 20 de octubre, 20:26 CEST

Capa Evidencia y límite
Servicio CT280, uvicorn y PostgreSQL16 activos en lectura de las 19:55; no prueba funcional completa
Dumps nativos PG Plantillas timer disabled, sin instancias cargadas en el filtro de las 20:13; otros planificadores desconocidos
Selección PBS Configuración de las 20:17: CT280 incluido, habilitada y a las 05:00 hacia pbs; no acredita ejecución
Ejecución PVE Log local consultado a las 20:26 registra finalización de CT280 en el lote de las 05:00; archivo y recuperación no comprobados
Rol Ansible Entrada obsoleta protegida por PR85; no se aplica al servicio vivo
Restauración Pendiente de acreditar; no se inició una nueva prueba

Defecto reproducido y corrección en fuente

La revisión local del20oct encontró que la plantilla copiaba al destino y borraba archivos antiguos antes de ejecutar pg_restore --list. Una fixture con verificación fallida reprodujo publicación no validada y pérdida de un archivo de45 días. Evidencia privada next-coverage-review-20261020-40s_v7fg/rp-backup-order-proof.json, SHA256 <REDACTED>. No prueba que ese script estuviera instalado ni que se perdieran datos reales.

PR82, merge <REDACTED> a las19:39:04 CEST, cambia el orden: dump privado → verificación de índice → publicación sin sobrescritura → copia opcional → retención local. Root abre los descriptores; PostgreSQL mantiene su usuario postgres y usa stdout/stdin. No requiere acceso de postgres a través del directorio privado de la aplicación. El leaf de backups queda root:root0700; se conservan padre0750, ubicación, calendario03:00 y días de retención.

Temporales0600, lock local no bloqueante y publicación mediante hardlink exclusivo con fsync de archivo/directorio evitan sobrescribir una generación existente. Los errores conservan archivos antiguos y no disparan reintento o rollback automático. Un error posterior al link puede dejar un destino incierto que requiere inspección, sin tratarlo como commit confirmado.

Nueve fixtures renderizan la plantilla real y ejecutan shell sobre archivos privados con herramientas PostgreSQL/sudo simuladas: fallos dump/list/copy, destinos existentes y symlink, orden de éxito y exclusión de dos procesos. La CI de PR39467714129 y la posterior39467929520 pasan lint y la matriz Linux3.12/3.14 con flock nativo; se reutiliza la matriz existente de fixtures, sin nuevo job operativo.

Alcance operativo

Sólo fuente: no se aplicó el rol, ejecutó pg_dump, consultó PostgreSQL, llamó al NAS, envió healthchecks o lanzó restauraciones. El play conserva never; Ansible-pull ordinario no despliega este rol manual. Runtime y coherencia con fuentes se acreditan por separado antes de cualquier aplicación.

pg_restore --list valida lectura del índice, no una restauración completa. La presencia de un directorio no prueba montaje o salud NAS; se conserva la política previa de copia local cuando no existe destino. No se añade recorrido NAS o poda remota. Los límites de I/O bloqueada y diagnóstico físico siguen pendientes. Fuente y recuperación.

Comprobación dirigida de CT280: 19:46 CEST

El20oct 19:46:27 CEST, propietario revalidado por API PVE: CT280 LXC running en proxmox. Boot del padre 82d105f6… idéntico antes/después. El lector sólo accedió a metadatos/rutas fijas locales, tras filtrar mountinfo y rechazar montajes remotos o desconocidos. No listó backups ni abrió rutas NAS.

El script no existe, tampoco /var/lib/rp/backups. Las unidades rp-pg-backup.service y rp-pg-backup.timer devuelven LoadState=not-found; no tienen ejecuciones acreditadas. El padre /var/lib/rp observado es root:root0755, no la declaración rp:rp0750 del rol. Esta divergencia exige resolver la implementación viva y su persistencia antes de aplicar el rol; no se instala por asumir que la plantilla describe el servicio actual.

Los valores predeterminados Resultsuccess/ExecMainStatus0 de una unidad not-found no son un backup correcto. Ausencia de este script/timer tampoco demuestra que CT280 carezca de otras copias o PBS. Ningún servicio/DB/timer fue ejecutado, recreado o reconfigurado; no se consultaron datos, entorno, logs o PG. La corrección de PR82 sigue siendo una prevención fuente, sin runtime aplicado.

Evidencia privada rp-backup-runtime-plan-20261020-mylkat9d/projection.json, SHA256 <REDACTED>. Lector host SHA256 <REDACTED>; nueve fixtures locales pasan, sin contar la observación como prueba de copia.

Procedencia seleccionada del servicio vivo: 19:55 CEST

Una segunda lectura mínima a las 19:55:05 CEST, con owner/boot revalidados, observa rp-server.service loaded/active/running, PID517 e invocación <REDACTED>; inicio18:45:41. WorkingDirectory /opt/rp/source/server, ejecutable uvicorn y argumento público rp_server.main:app; EnvironmentFile /etc/rp/server.env, sin leer contenido. PostgreSQL16-main también está loaded/active/running, PID194, inicio18:45:41. Estos estados no prueban consultas, ingestión o salud funcional.

El candidato de código identificado por la unidad src/rp_server/config.py tiene5295 bytes y SHA256 <REDACTED>, idéntico al archivo de main actual <REDACTED>. Su AST declara postgres_url/PostgresDsn/env_file; no tiene los nombres DATABASE_URL/RP_CONFIG_PATH de la plantilla antigua. El candidato database.py usa postgres_url. No se importó la app, resolvió sys.path ni leyó entorno: son archivos candidatos acreditados por la unidad, no una prueba completa de resolución de imports o de qué base está usando.

La comparación del repositorio actual, commit19oct21:22:53UTC, acredita server/pyproject.toml versión1.0.15 y ausencia de requirements.txt en su raíz. El rol clona main pero espera requirements.txt y genera DATABASE_URL/RP_CONFIG_PATH. Por ello no debe aplicarse completo sin reconciliar su contrato. El checkout local63e0de5 de septiembre sólo se usó como pista, no como main actual.

La documentación propia propone pg_dump03:30/WAL7d con otro nombre de DB/ruta, pero no identifica unidad/timer/script; no acredita ejecuciones. El próximo paso es descubrir metadatos acotados de timers/planificadores de backup y resolver su fuente, no crear una tarea duplicada por inferencia. No se ejecutaron consultas PostgreSQL, backups, importaciones, probes o cambios del servicio.

Lector revisado v2: once fixtures, rechazo de montajes apilados ambiguos y stdin/stdout no bloqueantes con deadline compartido. Privado rp-unit-source-plan-20261020-rmfcdn50/projection.json, SHA256 <REDACTED>. Lector host SHA256 <REDACTED>.

Privacidad del aviso opcional: 20:07 CEST

La PR84 se fusiona a las 20:07:52 CEST en <REDACTED>. La URL privada opcional de Healthchecks pasa por stdin como configuración de curl, mediante printf builtin y quoting JSON/shell; deja de aparecer en sus argumentos o en una variable exportada. La validación previa, con no_log, acepta vacío o HTTP(S) ASCII visible sin espacios/controles para evitar escapes incompatibles. Conserva redirecciones, límite de diez segundos y fallo no fatal del aviso.

Once fixtures locales pasan: los nueve casos de publicación y dos de privacidad y validación, con curl simulado y sin HTTP. La CI de PR39471725115 acredita lint y Linux Python3.12/3.14. El script generado conserva root:root0700, protección añadida en 3ccb4dc: la URL puede seguir dentro del archivo privado. No se aplica el rol ni se envía un aviso real. Estas correcciones no acreditan copias, recuperación o protección activa de CT280.

La CI posterior39472072101 también termina correcta en lint y ambas versiones Linux.

Temporizadores seleccionados: 20:13 CEST

Lectura mínima del20oct20:13:39 CEST, CT280 running en proxmox y boot padre 82d105f6… conservado. De13 unit files timer, tres nombres coinciden con el filtro rp/remote-pulse/postgres/backup/dump: dpkg-db-backup.timer enabled, pg_basebackup@.timer disabled y pg_dump@.timer disabled. Entre ocho timers cargados, sólo coincide dpkg-db-backup, active/waiting. Las plantillas PostgreSQL no acreditan instancias programadas. El timer de dpkg no acredita una copia de la aplicación o PostgreSQL. Otros nombres/planificadores y PBS quedan fuera de este filtro; no se afirma ausencia global de backups.

Una tentativa anterior falló al consultar show de los nombres seleccionados; la repetición diagnóstica20:12 conserva phase=timer_show_command/rc1. La lectura válida posterior ejecutó únicamente los dos listados, sin show, logs, contenido de backups, PostgreSQL, NAS o jobs. No se atribuye el fallo a una plantilla sin evidencia adicional. Owner/boot revalidados y stdin/stdout acotados por plazo.

Evidencia privada rp-backup-timer-lists-only-20261020-s12y23jw/observation.json, SHA256 <REDACTED>. Lector host SHA256 <REDACTED>: cinco fixtures y paridad AST con guardas/captura/parsers previamente revisados. Recibo diagnóstico rp-backup-timer-plan-20261020-gnug8wju/observation-v3.json, SHA256 <REDACTED>.

Entrada obsoleta detenida antes de mutaciones: 20:15 CEST

PR85, merge <REDACTED> a20:15:43 CEST, detiene la entrada manual del rol antes de instalar paquetes, modificar PostgreSQL o renderizar archivos. No altera el servicio vivo. La tarea cubre los tags actuales sin always: una fixture mostró que always superaba never y rompía ejecuciones ordinarias. Cinco pruebas con18 invocaciones Ansible locales verifican omisión ordinaria, selecciones manuales, check y control negativo con escritura ficticia. Autor y peer pasan; CI39472897855 correcta en lint y ambas versiones Linux. Saltos deliberados de tags/tareas quedan fuera de este freno, que no es una política de permisos. La CI posterior39473210492 también termina correcta; publicación39473210745 correcta después del merge.

La matriz y plan de reconciliación describe instalación de paquete/venv, configuración privada, frontend, orden de migraciones, proxy y recuperación. No es una modernización parcial ni acredita copias reales. La cobertura de configuración PBS se revisa por separado.

Selección programada en Proxmox: 20:17 CEST

El20oct20:17:21 CEST, consulta exclusiva de configuración /cluster/backup y propietario actual por /cluster/resources: CT280 running en proxmox, boot observador 82d105f6… conservado. De siete tareas configuradas, una selecciona explícitamente280: <REDACTED_UUID>, enabled=true, horario 05:00, almacenamiento pbs, sin exclusión de280 y sin restricción de nodo. No hubo selectores ambiguos/pools pendientes en esta proyección. Esto acredita selección programada, sin demostrar ejecución reciente, copia correcta, consistencia de PostgreSQL o restauración.

No se consultó storage, backup-info, PBS, datastores, tareas/logs o NAS ni se inició trabajo. API JSON procesado en RAM y sólo campos operativos seleccionados persistidos; ocho fixtures locales pasan por autor, root y peer. Lector privado rp-pve-backup-config-plan-20261020-kowxbias/reader.py, SHA256 <REDACTED>. Recibo observation.json, SHA256 <REDACTED>. El siguiente paso es acreditar historial local de ejecución que incluya280, sin equiparar un job de grupo correcto a una copia individual no identificada.

Finalización individual registrada: lectura 20:26 CEST

Consulta única a las 20:26:10 CEST, owner CT280/proxmox running y boot padre 82d105f6… conservado. De cuatro tareas vzdump archivadas recientes, dos eran de otro guest explícito y no se leyeron sus logs. Se leyeron únicamente dos logs locales exactos, regulares y estables, tras validar montaje/ancestros sin seguir enlaces; no se abrió PBS, NAS o ningún archivo de backup.

El lote con epochs 1792465202–1792465238 corresponde a 05:00:02–05:00:38 CEST del 20 de octubre y termina OK. Su log identifica un bloque de CT280/lxc inequívoco, con inicio literal 05:00:11 y finalización 05:00:31, sin zona en esos literales. Resultado reported_success independiente del TASK OK global. Tamaño no acreditado. Log de 4330 bytes, SHA256 <REDACTED>.

La tarea más reciente del alcance, 05:30:02–05:31:28 CEST, queda target_context_unknown: no se interpreta su éxito global como éxito de CT280 ni se afirma que 05:00 sea su última ejecución absoluta. Tampoco se atribuye el backend de esa ejecución sólo por coincidir con la configuración PBS actual. El registro acredita finalización informada por PVE, no existencia actual, integridad, consistencia PostgreSQL ni restauración del backup.

Recibo privado rp-vzdump-history-plan-20261020-db0i0a69/observation.json, SHA256 <REDACTED>. Lector SHA256 <REDACTED>; once fixtures repetidas por root/peer y formatos contrastados con fuente PVE. Límites: cuatro tareas/48 h, 512 KiB por log/2 MiB total, plazo cooperativo de 10 s. Sólo proyecciones seleccionadas; UPID/usuarios/mensajes privados no retornados.