Local Agent — Auto-update silencioso (técnica)
Qué es
El Local Agent se actualiza solo, en silencio: el usuario nunca ve ni interviene en el mantenimiento del Agente (norma fundacional). Introducido en s176 (Local Agent 2.9.0, SaaS 1.26.0) como mitigación del riesgo §6 del EPIC Full-Local Agent — al mover toda la I/O de red al Agente, su versión se volvió crítica: un Agente viejo no tiene los endpoints nuevos y rompe features.
Arquitectura (3 piezas)
1. Publicación automática del binario (PR #203)
build_agent.bat, al terminar de compilar, sube el .exe a Hetzner: scp a /tmp en root@crearack.com + docker cp al volumen persistente app_media del contenedor web (resuelto dinámicamente con docker ps | grep -web-N, porque el sufijo cambia entre redeploys de Dokploy). Si el SSH falla, avisa pero no rompe el build. El SaaS sirve ese binario en GET /downloads/CreaRackAgent.exe.
2. Lado SaaS — anuncia y empuja (PR #204, v1.25.0)
core/agent_release.py:get_latest_agent_version()(leeterminal/agent/version.py, la versión con la que se compiló el.exe),get_agent_sha256()(hash del.exeservido, cacheado por mtime/size),is_outdated()(SemVer numérico),agent_update_payload().GET /api/agent/manifest(terminal/api/agent_update.py, auth = JWT del Agente) →{version, sha256, url}para el chequeo al arrancar.- Push por WebSocket: en el heartbeat
ping(terminal/consumers.py), si el Agente reporta una versión por detrás de la última, el SaaS le envíacommand: "agent_update"con{version, sha256, url}. Dedup por versión reportada (no re-empuja cada 30 s). core/views.py::download_agent:GET /downloads/CreaRackAgent.exeacepta el JWT del Agente además de la sesión de navegador (el Agente descarga con su token).
3. Lado Agente — descarga, verifica, se reemplaza (PR #205, Agent 2.9.0)
terminal/agent/core/updater.py:
- Recibe
agent_updatepor el WS (o consulta/api/agent/manifestal arrancar). - Descarga el
.execon su JWT aCreaRackAgent.new.exe. - Verifica el SHA-256 contra el del manifest. Si no coincide → descarta (nunca ejecuta un binario sin verificar).
- Swap por renombrado (Windows no deja sobrescribir un
.exeen marcha, pero SÍ renombrarlo):CreaRackAgent.exe → .old.exe,.new.exe → CreaRackAgent.exe, relanzar (relaunch_from_install_dir) yos._exit(0)(fiable también desde una task asyncio, dondesys.exitno terminaría el proceso). El nuevo proceso borra el.old.exeal arrancar. - Solo en ocio: el swap se aplica únicamente si no hay sesiones SSH activas (
network.ssh.ACTIVE_BRIDGES) — al arrancar (ocioso por definición) o cuando terminen las sesiones, para no cortar trabajo. Staging con markerupdate.jsonrecuperable ante reinicio.
Decisiones de diseño
- Silencioso, sin UI: se descartó la “Capa 1” (un banner visible avisando de versión vieja) por la norma de que la instalación/mantenimiento del Agente son transparentes para el usuario. Se implementó directamente la “Capa 2” (auto-update silencioso).
- Disparo: push por WebSocket (inmediato para Agentes residentes) + chequeo del manifest al arrancar (robustez).
- Seguridad: HTTPS, mismo origen, descarga autenticada (JWT), verificación SHA-256 obligatoria. Pendiente/mejora futura: firma Authenticode del
.exe. - Orden seguro garantizado por
version.pycomo puerta: el.exenuevo se publica al compilar, pero el SaaS solo anuncia la versión nueva al desplegar el código → nunca se ordena actualizar a una versión cuyo.exeno esté servido.
Bootstrap (importante)
El salto 2.8.0 → 2.9.0 es manual una vez (los Agentes 2.8.0 no entienden el comando agent_update). Hay que compilar e instalar la 2.9.0 en cada equipo. De la 2.9.0 en adelante, automático para siempre.
Distribución del .exe
El binario se sirve desde el volumen app_media de Hetzner vía GET /downloads/CreaRackAgent.exe (no se versiona en git, ~23 MB). Se publica con build_agent.bat (automático) o a mano (scp+docker cp, ver context/INFRA.md). El Release de GitHub agent-vX.Y.Z guarda el .exe solo de la versión en curso (referencia/respaldo).