Files
fn_registry/dev/issues/0146-add-pc-oneshot-mesh-scaling.md
T
egutierrez 621e8895c9 feat(infra): auto-commit con 86 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 19:38:15 +02:00

12 KiB

id, title, status, priority, created, related_flows, related_issues, dependencies, tags
id title status priority created related_flows related_issues dependencies tags
0146 add-pc one-shot: añade PC al mesh + agente LLM en <2min desde movil pending high 2026-05-24
0009
0134
0144
0145
mesh
wireguard
ssh
scaffolder
agents
llm
scaling
dx

Objetivo

Reducir de 8 pasos manuales (~15min) a 1 comando (<2min) el flujo de añadir un PC nuevo al mesh con su propio agente LLM conversacional. Goal final: chatear desde Element movil con cualquier PC del usuario tras un ./fn run add_pc <name>.

Estado actual (post-0145)

Pipeline manual funcional pero verboso:

  1. Instalar wireguard en PC nuevo.
  2. wg_keygen.
  3. wg_peer_add en hub (organic-machine.com).
  4. wg_client_config + wg_client_install.
  5. Build/scp device_agent binario.
  6. Manifest YAML local.
  7. systemd unit.
  8. provision-agent-user.sh + edit launcher main.go + rebuild + restart agents_and_robots.

Solo agent-wsl-lucas existe. Bloqueado por friccion de pasos para escalar a aurgi-pc, windows-lucas, raspberry, etc.

Vision

operador$ ./fn run add_pc aurgi-pc --via wg
[1/9] generating WG keypair...
[2/9] enrolling peer at hub (10.42.0.21)...
[3/9] cross-compiling device_agent for linux/amd64...
[4/9] uploading binary + manifest + systemd unit via SSH...
[5/9] starting WG + device_agent on remote...
[6/9] provisioning Matrix user @agent-aurgi-pc...
[7/9] generating agent config + system prompt...
[8/9] wiring launcher + rebuild...
[9/9] restarting agents_and_robots.service...
✓ agent-aurgi-pc live. Send a DM from your Matrix client.

Y para hosts sin posibilidad de instalar binary:

operador$ ./fn run add_pc customer-vps-01 --via ssh --ssh-alias customer-prod
✓ agent-customer-vps-01 live (ssh-backed). Send a DM.

Arquitectura

Dos backends para un mismo UX:

Backend A — WG + device_agent (mesh nativo)

  • PC tiene WG client + binary device_agent corriendo.
  • Comandos viajan VPS → WG → device_agent → exec local → audit chain LOCAL.
  • 14 capabilities completas (fs., git., docker., pkg., proc.*, shell.exec, shell.eval).
  • Para tus PCs (laptop, desktop, raspberry, mac, movil rooted).

Backend B — SSH-only (sin binary remoto)

  • PC tiene solo SSH server. VPS tiene SSH key autorizada.
  • Comandos viajan VPS → ssh.Executor → exec remoto → audit en VPS.
  • Tools reducidos: ssh_exec(argv), ssh_fs_read, ssh_fs_list. Sin docker/git/pkg salvo wrapper.
  • Para customer servers, VPS terceros, throwaway boxes.

LLM agent ve diferentes tool sets segun backend. Mismo system prompt template.

Tareas

Fase 1 — Pipeline add_pc_wg_bash_pipelines

1.1. Cross-compile device_agent matrices:

  • GOOS=linux GOARCH=amd64 (default)
  • GOOS=linux GOARCH=arm64 (raspberry pi4+, mac M-series via Linux)
  • GOOS=windows GOARCH=amd64
  • GOOS=darwin GOARCH=arm64
  • Reusa nohup cgo-free build (swap mattn/go-sqlite3 → modernc.org/sqlite si no esta hecho ya).
  • Output: cpp/build/cross/device_agent.<os>-<arch>.

1.2. Funcion cross_compile_device_agent_bash_infra(target_os, target_arch) que devuelve path al binario.

1.3. Funcion add_pc_wg_bash_pipelines(name, ssh_alias, target_os?, target_arch?). Compone:

  • wg_keygen_go_infra (hub side: priv hub + psk; client side: priv cliente)
  • wg_peer_add_go_infra (en hub via SSH al VPS)
  • wg_client_config_go_infra (genera client.conf)
  • ensure_remote_wireguard_installed (SSH al target, apt/dnf install wireguard si falta)
  • wg_client_install_bash_infra (en target via SSH push)
  • cross_compile_device_agent_bash_infra (local)
  • rsync_device_agent_bundle (binary + manifest template + systemd unit → target ~/.local/bin/ + ~/.config/device_agent/)
  • start_device_agent_service (systemctl --user enable --now device_agent)
  • provision_agent_user (ssh al VPS, ejecuta dev-scripts/agent/provision-agent-user.sh con --mode user)
  • wire_launcher_import (edita cmd/launcher/main.go en VPS, anade blank import, git commit + rebuild + restart service)
  • assert_dm_received (espera 30s a que el bot mande "hola" via notify-developer.sh)

1.4. Manifest template Y matrix per-OS: paths_allowed difieren (/home/<user>/** en Linux, C:\Users\<user>\** en Windows). Templates en dev-scripts/agent/templates/manifest.<os>.yaml.tmpl.

1.5. Idempotente: re-run con mismo name → no-op + verificar state. Si peer existe pero device_agent caido, restart.

1.6. Rollback: si paso N falla, deshacer 1..N-1. Estado parcial NO debe quedar (peer huerfano, Matrix user sin agent, etc).

Fase 2 — Pipeline add_pc_ssh_bash_pipelines (backend B)

2.1. Funcion ssh_exec_capability_go_infra — wrapper que recibe {argv, host} y hace ssh <host> -- <argv...>. Whitelist binaries opcional. Audit en VPS (apps/agents_and_robots/ssh_audit.db o similar).

2.2. Funcion ssh_fs_read_capability_go_infra, ssh_fs_list_capability_go_infra (read-only, no write para evitar accidentes en customer boxes).

2.3. Tool registry adapter: cuando agent config tiene device_mesh.backend: ssh, el adapter no apunta a HTTP device_agent — apunta a las funciones ssh_* directamente. Mantener interface ToolRegistry pero swap implementation.

2.4. add_pc_ssh_bash_pipelines(name, ssh_alias) compone:

  • assert_ssh_reachable (BatchMode yes connect test)
  • provision_agent_user --mode user --backend ssh
  • generate agent config con device_mesh.backend: ssh, ssh_alias: <alias>
  • wire launcher + restart

NO toca el remote — solo VPS.

Fase 3 — Cross-compile device_agent CGO-free

3.1. Swap mattn/go-sqlite3 (CGO) → modernc.org/sqlite (pure Go) en device_agent. Tests verde tras swap.

3.2. cross_compile_device_agent_bash_infra produce 4 binarios en <30s.

3.3. Bundle script make-bundle.sh <os> <arch> empaqueta zip con binario + manifest.template + systemd-unit/launchd-plist/Task-Scheduler.xml segun OS.

Fase 4 — agents_dashboard "Add device" panel C++

4.1. Modal nuevo en panel "Devices" con:

  • Input: nombre del PC.
  • Dropdown backend: WG mesh / SSH-only.
  • Si WG: SSH alias para upload + OS/arch detect via uname remote.
  • Si SSH: solo alias.
  • Boton "Add". Spawn pipeline en background. Stream logs en TextLog.

4.2. Grid de status: device_id, IP mesh, last handshake, capabilities count, last command ts, audit chain integrity.

4.3. Boton "Revoke" por device → llama wg_peer_revoke + deactivate Matrix user + remove launcher import + restart. Confirmacion doble.

Fase 5 — Health monitor cron + alertas

5.1. Cron 5min monitor_mesh_health_bash_pipelines:

  • wg_status → cada peer con last_handshake > 600s → mark stale.
  • HTTP GET /health a cada device_agent IP del mesh → si falla → mark unreachable.
  • verify_hash_chain por device → si rota → mark corrupted.

5.2. Alertas Matrix a #operator-alerts (room a crear) con mensaje formato:

[ALERT] device_id=aurgi-pc status=stale (handshake 8min ago)
[ALERT] device_id=home-wsl status=hash_chain_corrupted (id=47 broken)

5.3. Dashboard tab "Health" muestra el feed SSE.

Fase 6 — Movil UX validation

6.1. Test en Element movil iOS/Android:

  • Lista de rooms con 1 per device.
  • Notifications activas → push cuando agent responde.
  • Smoke tests de capabilities mas comunes via voice-to-text.

6.2. Documentar docs/mobile-control.md con flujo recomendado:

  • Como agrupar rooms por device en Element favorites.
  • Comandos comunes ("status", "deploy X", "que esta caido").
  • Tiempos esperados (claude-code latency 3-5s + tool exec 0.1-2s).

Aceptacion (DoD triada)

Mecanica

  • ./fn run add_pc <name> --via wg exit 0 + agent live en <2min en wallclock.
  • ./fn run add_pc <name> --via ssh exit 0 + agent live en <30s.
  • Tests unit + integration verde en bash/functions/pipelines/add_pc_*.

Cobertura

  • Smoke matrix: 4 target OS (linux/amd64, linux/arm64, windows/amd64, darwin/arm64) cada uno con add_pc_wg flujo end-to-end.
  • Rollback: simular falla en paso 5 (binary upload corrupted) → assert estado limpio (no peer huerfano, no Matrix user, no entry en launcher).
  • SSH backend: target solo con SSH + sin sudo → agent funciona con tools ssh_exec read-only.
  • Anti-criterio A3 (heredado de 0009): tras add_pc, smoke real via Matrix → audit DB en device tiene entries reales (no bot hallucination).

Vida util

  • 5 PCs reales añadidos durante 7 dias.
  • 0 revokes manuales por error de provision.
  • Operador usa Element movil >=1 sesion/dia interactuando con >=2 devices distintos.
  • Health monitor detecta peer caido en <10min (test con wg-quick down aleatorio).

Anti-criterios

  • Si add_pc deja estado parcial (peer en wg0 + no agent en launcher) → invalida.
  • Si SSH backend ejecuta comandos sin audit en VPS → invalida (no fake "ssh OK" sin log).
  • Si dashboard muestra device "online" pero ultimo handshake >24h → invalida (false positive grave).

Sub-issues planificados

ID Titulo Esfuerzo
0146a cross_compile_device_agent + CGO-free swap a modernc.org/sqlite 2h
0146b add_pc_wg_bash_pipelines (Fase 1) 4h
0146c add_pc_ssh_bash_pipelines + ssh_exec_capability (Fase 2) 3h
0146d Bundle script multi-OS + manifest templates (Fase 3) 2h
0146e agents_dashboard panel "Add device" + status grid (Fase 4) 4h
0146f monitor_mesh_health pipeline + alertas Matrix (Fase 5) 1.5h
0146g Movil UX doc + smoke real con 4 devices fisicos (Fase 6) 1h+observacion 7d

Total: ~17h dev + 7d observacion.

Decisiones de diseño

  1. Pipeline en bash compose funciones del registry, no codigo Go monolitico. Permite que cada paso sea trazable + reusable individualmente.

  2. modernc.org/sqlite vs mattn/go-sqlite3: pure Go elimina CGO + cross-compile trivial. Performance es comparable (modernc benchmarks dentro del 10% para nuestro workload de audit append).

  3. Backend SSH NO replica el manifest enforcement remoto — el manifest vive en VPS y filtra antes de SSH. Trade-off aceptable: SSH backend = "trust the VPS sudo enforcement". Para PCs propios usa WG backend.

  4. Cada device = un agent Matrix separado (NO un agent multi-device). Razon: aislamiento blast radius + room por device = UX claro en Element + capability manifest distinto por device. Coste: mas Matrix users + mas claude-code subprocesses.

  5. NO usar Ansible/Terraform para este flujo. Pipeline bash + funciones del registry es suficiente y evita la dep externa. Si crece a >50 PCs, reconsiderar.

Riesgos

  • Cross-compile + CGO-free: el swap a modernc puede romper audit en runtime si schemas no migran. Mitigar con test golden DB + WAL mode check.
  • Windows systemd equivalente: Task Scheduler es feo. Considera nssm.exe para autostart fiable. Documentar bien en bundle.
  • SSH key trust amplification: backend B requiere SSH agent del VPS confiable a TODOS los target hosts. Si VPS comprometido → todos los SSH targets caen. Reforzar con SSH key per-host + revocacion centralizada.
  • Mac iCloud signing: device_agent.app necesitaria notarization para auto-launch en macOS reciente. Skip para POC, abordar si añadimos Mac al mesh real.
  • Movil notifications: Element push depends on FCM (Android) / APNs (iOS). Sin push, el operador puede perderse approvals time-sensitive. Doc sobre alternativas (NTFY, Gotify).

Notas

  • 2026-05-24 — 0146a done: swap mattn/go-sqlite3 → modernc.org/sqlite v1.50.1 (pure Go). 4 binarios cross-compile OK (linux-amd64 11MB, linux-arm64 10MB, windows-amd64 11MB, darwin-arm64 10MB), todos stripped + statically linked. Build script idempotente en apps/device_agent/build_all.sh. Self-test pass en linux-amd64 nativo. Quedan smoke tests reales en windows/darwin/arm cuando 0146b despliegue a peers fisicos.
  • ./fn run add_pc deberia llamar via mcp__registry__fn_run para que telemetria de issue 0085 quede registrada.
  • Aprovechar 0144b provision-agent-user.sh que ya esta hecho — solo compone, no reescribe.
  • Sub-issue 0146g (UX movil) cierra el flow 0009 completo al fin: "humano controla N maquinas desde movil".
  • Si esto funciona, abrir issue 0147 para "voice control" — Element soporta voice messages; usar transcripcion (Whisper local en VPS) → inyectar como texto al agent.