Remote-Pulse: contrato del rol y reconciliación pendiente — 20 octubre 2026¶
Solo fuente. Base infraestructura c40bdb9; app propia
<REDACTED>,
main consultado por GitHub. No SSH, app HTTP, PostgreSQL, NAS, entorno/secretos
o Vera. No se importó la app ni instalaron dependencias.
Matriz: declarado, requerido y observado¶
La columna viva procede únicamente de la observación dirigida de las 19:55 CEST, no de una nueva consulta ni de inferir valores privados.
| Área | Rol actual | App upstream / observación y consecuencia |
|---|---|---|
| Revisión y layout | clone main a /opt/rp/server; versión declarada0.1.0 |
App1.0.15 en server/pyproject.toml, código server/src/rp_server; unidad viva apunta /opt/rp/source/server. main flotante no fija entrega |
| Python/uv | variable Python3.12 ignorada; paquetes/venv fijan3.12; pipx por pip3 global, uv bajo /root/.local/bin y symlink |
App requiere >=3.12. Declarar versión disponible en OS objetivo; Bookworm no aporta3.12 por defecto. PEP668 puede impedir pip global y /root puede impedir acceso de rp al uv enlazado; no son fallos runtime comprobados |
| Instalación | uv pip install -r /opt/rp/server/requirements.txt |
No existe requirements raíz en ese SHA; server usa pyproject/uv.lock/hatchling. Instalar dependencias sueltas tampoco instala paquete src |
| Configuración | TOML y RP_CONFIG_PATH, DATABASE_URL, RP_DATA_DIR, RP_LOG_DIR | Settings usa entorno/.env, extra=ignore. Requiere POSTGRES_URL y JWT_SECRET; database.py consume postgres_url. No hay cargador TOML ni alias DATABASE_URL en fuente actual |
| Credenciales/URLs | JWT solo escrito en TOML; URI postgresql://; sin sesión/OIDC explícitos | POSTGRES_URL debe seleccionar asyncpg; JWT_SECRET y SESSION_SECRET privados. SESSION_SECRET tiene valor de desarrollo; omitirlo no es seguro. SERVER_URL por defecto localhost perjudica enrolamiento remoto. OIDC/URLs/proxies deben preservarse explícitamente, sin leerlos aquí |
| PostgreSQL | módulos community.postgresql sin driver Python declarado; HBA local, URI localhost TCP | Acreditar psycopg del intérprete Ansible y política socket/TCP. Línea HBA local no configura TCP. No se afirma identidad de BD/rol vivos por defaults |
| Orden migraciones | postgres.yml ejecuta Alembic antes de app.yml | Antes de crear usuario, clonar, venv y config: instalación limpia falla. Migración además en raíz incorrecta, sin mismo EnvironmentFile |
| Unit | raíz /opt/rp/server, uvicorn rp_server.main, 2 workers, bind127.0.0.1 |
src necesita instalación; WorkingDirectory correcto server. Caddy remoto usa rp.lan:8080: bind solo loopback necesita mediador que el rol no acredita. Selección viva no acredita bind/workers/env reales |
| Proxy/identidad | --proxy-headers sin política explícita de peers; opciones TOML obsoletas | Settings trusted_proxies tiene defaults antiguos .247/.248/.250. Reconciliar Caddy .40/.41, encabezados y OIDC nativo; Pocket ID no tiene forward-auth |
| Frontend | no construcción/copia SPA | Fuente tiene solo .gitkeep en static/dash-next; script oficial construye Node22+/npm y empaqueta assets. Health200 no demuestra dashboard utilizable |
| Copias | rol declara timer/script03:00 | Lectura19:46 no encontró esa implementación. No acredita ausencia de otras copias/PBS. Reparación de PR82 es fuente, no instalación |
Fuentes propias aprovechables¶
server/README.md,server/SETUP.mdyserver/dev.sh: contrato de desarrollo uv sync → variables → Alembic → uvicorn. Sus --reload/0.0.0.0 no constituyen una receta de producción segura.server/pyproject.toml,server/uv.lock,server/alembic.iniy migraciones: paquete, resolución y esquema actuales.settings = Settings()se evalúa al importar; no usar imports de preflight contra el servicio real sin contexto.scripts/build_dashboard.sh: Node22+, npm ci con lock y copia aserver/src/rp_server/static/dash-next; wheel incluye esos assets. No ejecutar su rsync --delete sobre entrega viva durante exploración.packaging/linux/remote-pulse.serviceejecuta agente heartbeat, no servidor. El workflow release construye agentes; no acredita un instalador server actual.- Rol Caddy señala
snippets/rp.caddy, ausente en árbol c40; las rutas RP están enCaddyfile.full-routing. Resolver fuente desplegada antes de actualizar imports/snippets. No copiar documentación de forward-auth antigua.
Protección temporal, no modernización parcial¶
Primera tarea de remote_pulse_server/tasks/main.yml: fail explícito con la
unión de tags actuales del rol, antes de todos los includes. No usa always:
una fixture real mostró que always supera el never heredado y rompe una
ejecución ordinaria. Sin checkout adicional, gran checker,
consulta externa o variable de excepción. Pruebas locales copian entrypoint
real y reemplazan includes por sentinelas en directorio temporal: normal,
selecciones actuales y --check fallan antes de mutar. Otra fixture con los
tags reales del play [remote_pulse, never] conserva rc0/omisión en ejecución
ordinaria; la selección manual remote_pulse falla antes de los sentinelas.
El test calcula la unión de tags de includes y tareas para detectar futuras
ampliaciones no cubiertas por el guard.
No cambia playbook never, servicio vivo, systemd, boot, datos o copias. La
protección cubre el entrypoint normal; omitir deliberadamente tags del guard, --start-at-task
y direct include deliberados quedan fuera. No es una política de permisos.
La reversión del commit quitaría el freno pero no arregla el contrato; no
usarla para desplegar el rol obsoleto. Retirar la tarea solo con reconciliación
revisada y pruebas de instalación/actualización en destino aislado.
Orden exacto de la reconciliación futura¶
- Acreditar propietario, unidad, revisión, recursos, Python/OS y persistencia existentes con lectura acotada. Preservar env privado por referencia; no sustituir BD/rol/URLs/OIDC ni claves por defaults o nuevos valores. Resolver otras copias y restauración verificable antes de cambios de esquema.
- Paquetes/driver PostgreSQL de Ansible y Python>=3.12 compatibles con OS;
uv fijado accesible al usuario rp en ruta del sistema, sin depender de
recorrer /root o pip global. Crear usuario/directorios respetando permisos
vivos; no cambiar owner de
/var/lib/rppor asumir el rol correcto. - Entrega de revisión inmutable a layout canónico
/opt/rp/source/server, reconciliando cambios propios. Preparar frontend desde lock en staging, no sobre assets vivos. Instalar paquete y dependencias desde server con uv sync --locked --no-dev y entorno proyecto explícito; decidir una venv única y alinear unit/migración, sin dos instalaciones ambiguas. - Render privado del EnvironmentFile: POSTGRES_URL con asyncpg, JWT_SECRET, SESSION_SECRET, SERVER_URL, PUBLIC_DASHBOARD_URL y configuración OIDC/peers pertinentes. Secretos existentes conservados, no valores de ejemplo. TOML obsoleto no puede seguir aparentando ser fuente. Aislar shadow .env del checkout para que no altere la resolución sin inventario. Codificar credenciales reservadas en la URI y citar el formato EnvironmentFile correctamente, sin imprimir valores; interpolación de password literal no es una prueba de DSN válido.
- Configurar PostgreSQL/HBA conforme a transporte elegido. Separar creación del esquema de migración: ejecutar Alembic desde server con el mismo entorno y usuario que app, después de paquete/config y backup recuperable. Ensayo migración desde copia aislada antes de producción; rollback de código no revierte automáticamente esquema o datos.
- Unit coherente con ruta/venv/usuario y escritura mínima. Revisar dos workers: dispatcher y retención arrancan por proceso; conservar o cambiar concurrencia con evidencia del event bus/SSE, no por defecto. Elegir bind accesible solo a Caddy/red necesaria más firewall, o mediador explícito; no publicar 0.0.0.0 sin política. Forwarded headers y peers explícitos, login OIDC nativo.
- En fixture: imports/version/assets, config con referencias falsas, migración de copia PostgreSQL y arranque aislado, rutas autorizadas/no autorizadas, enrolamiento sintético, heartbeat, SSE y secretos/URLs preservados. No usar /health200 como sustituto. Validar ambos Caddy y recuperación de datos.
- Solo tras revisión: ventana de aplicación acotada, diff/rollback por componente e inventario de copias existente. Backup corregido se instala únicamente si sustituye/completa un propietario identificado, no para duplicar calendario. Restituir unidad/config/entrega previa coordinadamente; recuperación de BD solo mediante plan comprobado, sin tratar downgrade de código como DR.
No se implementa ninguna de estas fases operativas en esta intervención.