Files
fn_registry/dev/flows/0009-agentes-dispositivos-mesh.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

18 KiB

name, id, status, created, updated, priority, risk, related_issues, apps, projects, vaults, capability_groups, trigger, schedule, expected_runtime_s, tags
name id status created updated priority risk related_issues apps projects vaults capability_groups trigger schedule expected_runtime_s tags
agentes-dispositivos-mesh 0009 pending 2026-05-23 2026-05-23 high high
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
agents_dashboard
agents_and_robots
wg_hub
device_agent
element_agents
wireguard
device-agent
docker-agent
manual 300
mesh
wireguard
matrix
e2ee
agents
devices
docker
sandboxing

Goal

Hablar desde Element con dispositivos completos (PCs, moviles, raspberry, IoT) y con contenedores Docker como si fueran agentes Matrix. Cada device/container ejecuta sus capabilities declaradas (shell/fs/camera/docker/sensores) bajo:

  1. Mesh WireGuard anclado en organic-machine.com — sin abrir puertos en los devices.
  2. Matrix E2EE como bus de control y chat — un room por device/container.
  3. Capability manifest firmado ed25519 — el device rechaza lo que no este firmado.

Pre-requisitos

  • VPS organic-machine.com con root SSH (alias vps en ~/.ssh/config).
  • agents_and_robots y agents_dashboard desplegados (ya OK).
  • pass con clave operador ed25519 (pass insert operator/ed25519 — crear si falta).
  • apt-get install wireguard wireguard-tools permitido en el VPS.
  • Devices Linux/WSL: sudo sin password para wg, wg-quick, systemctl.
  • Devices Android: Termux + WireGuard app + pkg install golang openssh-client.

Funciones del registry recomendadas

Rol Funcion candidata Estado
WG install (host) wg_install_bash_infra FALTA: crear
WG keygen wg_keygen_go_infra FALTA: crear
WG hub setup wg_hub_setup_bash_infra FALTA: crear
WG peer add (hub) wg_peer_add_go_infra FALTA: crear
WG peer remove (hub) wg_peer_remove_go_infra FALTA: crear
WG peer revoke (kill switch) wg_peer_revoke_go_infra FALTA: crear
WG client config gen wg_client_config_go_infra FALTA: crear
WG client install (device) wg_client_install_bash_infra FALTA: crear
WG status (parse wg show) wg_status_bash_infra FALTA: crear
Docker list (host) docker_container_list_go_infra FALTA: crear
Docker exec capability docker_container_exec_go_infra FALTA: crear
Docker logs tail docker_container_logs_go_infra FALTA: crear
Docker container enroll docker_container_enroll_go_infra FALTA: crear
Capability sign capability_manifest_sign_go_infra FALTA: crear
Capability verify capability_manifest_verify_go_infra FALTA: crear
Enrollment token gen enrollment_token_create_go_infra FALTA: crear
Enrollment token verify enrollment_token_verify_go_infra FALTA: crear
Matrix room per device matrix_room_for_device_py_browser (extender) OK base, EXTENDER
Provision hub pipeline provision_wg_hub_bash_pipelines FALTA: crear
Enroll device pipeline enroll_device_bash_pipelines FALTA: crear
Sink audit log device_audit_append_go_infra FALTA: crear
Notify approval matrix_send_message_py_browser (existente) OK

Apps tocadas

  • agents_dashboard (cockpit ImGui) — panel "Mesh" + "Devices" + "Containers" + approval queue.
  • agents_and_robots (hub Matrix VPS) — listener Matrix por device/container.
  • wg_hub (nuevo service Go en VPS) — enrollment endpoint, peer CRUD, SSE stream.
  • device_agent (nuevo binario per-host) — capability dispatcher con sandbox.
  • container_agent_sidecar (opcional, nuevo) — sidecar para containers que necesitan WG-peer propio.

Projects relacionados

  • element_agents (parent project — agents Matrix).

Vaults / storage

  • apps/wg_hub/operations.db — tabla wg_peers, wg_enrollment_tokens, device_audit.
  • apps/agents_dashboard/local_files/agents_dashboard.db — cache devices + capabilities.
  • pass operator/ed25519 — clave maestra del operador (firma manifests).
  • pass wg/preshared/<device_id> — PSK por peer.

Capability groups consultados

  • wireguard (nuevo, ver docs/capabilities/wireguard.md).
  • device-agent (nuevo, capability dispatcher + sandbox + audit).
  • docker-agent (nuevo, capabilities sobre containers locales).

Flow

Fase A — registry primero (delegar a fn-constructor en paralelo)

  1. function: wg_install_bash_infra (delegada).
  2. function: wg_keygen_go_infra (delegada).
  3. function: wg_hub_setup_bash_infra (delegada).
  4. function: wg_peer_add_go_infra (delegada).
  5. function: wg_peer_remove_go_infra (delegada).
  6. function: wg_peer_revoke_go_infra (delegada).
  7. function: wg_client_config_go_infra (delegada).
  8. function: wg_client_install_bash_infra (delegada).
  9. function: wg_status_bash_infra (delegada).
  10. cmd: ./fn index — registra las 9 nuevas.
  11. cmd: fn doctor unused | grep wg_ — confirma que estan listas y no huerfanas (se usan en pasos C).

Fase C — POC manual end-to-end

  1. function: wg_install_bash_infra (sobre organic-machine.com via SSH).
  2. function: wg_keygen_go_infra → key par hub.
  3. function: wg_hub_setup_bash_infra — wg0, 10.42.0.1/24, ufw 51820/udp, persistencia.
  4. function: wg_keygen_go_infra → key par device home-wsl.
  5. function: wg_peer_add_go_infra (en hub) → asigna 10.42.0.10.
  6. function: wg_client_config_go_infra → genera client.conf.
  7. function: wg_client_install_bash_infra (en home-wsl).
  8. cmd: ping -c3 10.42.0.1 desde home-wsl — verifica handshake.
  9. cmd: curl http://10.42.0.1:8080/healthz — agents_and_robots accesible por IP privada.
  10. Repetir 15-19 para pc-aurgi.

Fase B — spec + capability manifest + bot Matrix

  1. Issue 0134 spec protocol: envelope JSON {request_id, capability, args, signature, nonce}, error model, approval flow, audit chain hash.
  2. function: capability_manifest_sign_go_infra (operator firma).
  3. function: capability_manifest_verify_go_infra (device verifica antes de aceptar request).
  4. function: enrollment_token_create_go_infra (token QR firmado, TTL 10min).
  5. function: enrollment_token_verify_go_infra (hub valida en /enroll).
  6. Implementar apps/device_agent/ (Go cross-compile) — Matrix client + capability dispatcher + sandbox firejail.
  7. Panel "Devices" en agents_dashboard — lista + capability matrix + approval queue + boton revoke.
  8. Bot Matrix por device: cuando hablas en el room #dev-aurgi:organic-machine.com, agents_and_robots parsea, valida capability, despacha a device_agent, devuelve resultado al room.

Fase D — agentes-contenedores docker

  1. function: docker_container_list_go_infra — corre en host con docker socket access.
  2. function: docker_container_exec_go_infra — exec en container con whitelist binarios.
  3. function: docker_container_logs_go_infra — tail logs SSE.
  4. Modo "light": container expuesto via host's device_agent capability docker.*. Element room: #host-aurgi:organic-machine.com con comando !docker exec mycontainer ps.
  5. Modo "deep": container = peer WG propio. container_agent_sidecar corre WG dentro del container (privileged) o sidecar gluetun-wg. Manifest firmado mapea agent_X → container_id.
  6. Sub-bot Matrix por container: #cont-mycontainer:organic-machine.com (opcional, modo deep).

Acceptance

  • 9 funciones wg_* creadas + indexadas + sin huerfanas.
  • Hub WG corriendo en organic-machine.com, wg show muestra interface wg0.
  • home-wsl y pc-aurgi con IP estable 10.42.0.10/11, ping OK.
  • agents_and_robots accesible solo desde subnet 10.42.0.0/24 (publico = DROP en :8080).
  • agents_dashboard panel "Mesh" muestra peers vivos via SSE.
  • Chat en #dev-aurgi ejecuta capability (ej. !ls /home/lucas) y devuelve resultado.
  • Capability fuera del manifest rechazada con error en room.
  • Capability requires_approval=true espera confirmacion en #operator-approvals antes de ejecutar.
  • docker.container.list invocado desde Element devuelve containers del host.
  • docker.container.exec con binario fuera de whitelist rechazado.
  • Revoke device desde agents_dashboard → device pierde acceso en <5s.
  • Audit log append-only inviolable (hash chain) sobrevive reinicio.

Definition of Done

Triada obligatoria (ver .claude/rules/dod_quality.md). Sin las 3 capas + 0 anti-criterios el flow NO se mueve a completed/.

Mecanica (pre-requisito)

  • Build device_agent: cd apps/device_agent && CGO_ENABLED=0 GOOS=linux go build -o device_agent . exit 0; cross-compile GOOS=windows + GOOS=android GOARCH=arm64 tambien verdes.
  • Build agents_and_robots + agents_dashboard: ./fn run redeploy_cpp_app_windows agents_dashboard apps/agents_dashboard --build + Go build de agents_and_robots exit 0.
  • Tests unitarios funciones nuevas verdes: CGO_ENABLED=1 go test -tags fts5 -count=1 ./functions/infra/... cubriendo wg_, capability_, enrollment_, device_audit_. Lista de IDs en ## Notas.
  • ./fn index sin warnings nuevos tras anadir las ~20 funciones.
  • ./fn doctor unused --json | jq '.[]|select(.id|startswith("wg_"))' vacio (las wg_* tienen consumidores reales).
  • ./fn doctor uses-functions verde para apps/device_agent/app.md, apps/wg_hub/app.md, apps/agents_dashboard/app.md.
  • ./fn doctor services-spec verde para wg_hub.service y device_agent.service con bloque service: completo.

Cobertura de comportamiento

Minimo: golden + 8 edge/error documentados aqui con assert ejecutable. Cada uno deja entry en e2e_runs de la app afectada (apps/device_agent/operations.db, apps/wg_hub/operations.db).

Escenario Tipo Comando / evidencia Resultado esperado
Golden: comando whitelist OK e2e Element !exec ls /home/lucas en #dev-home-wsl output ls en <3s, entry en device_audit con hash valido
Edge: comando NO whitelist rechazado e2e Element !exec rm -rf / reply capability rejected: shell.exec.rm not in manifest; entry device_audit status=rejected_capability
Edge: capability fuera de manifest e2e Element !camera.snapshot en device sin esa capability reply capability not in manifest; alerta a #operator-approvals
Edge: replay nonce viejo e2e reenviar mismo envelope con nonce ya visto (cmd test: device_agent --replay-test <envelope.json>) rechazo + log nonce_replay; entry device_audit status=rejected_nonce
Edge: ed25519 manifest invalido e2e servir manifest firmado por clave que no es operator; device_agent lo recibe en enrollment device_agent rechaza + no instala wg_peer; hub log muestra manifest_invalid_signature
Edge: token enrollment expirado e2e enrollment_token_create con TTL=1s, esperar 5s, POST /enroll hub responde 401 token_expired; cmd curl ... exit != 0
Approval flow honrado e2e Element !fs.write /tmp/x hello (requires_approval=true); operador hace 👍 en #operator-approvals exec ocurre SOLO tras approval; sin approval no escribe; entry device_audit con approval_msg_id
Approval flow no se salta e2e Forzar via API directa salto del approval queue (test negativo: cmd curl --data ... directo al device) device rechaza + log; sin approval_msg_id en envelope = rechazo
Mesh-down handled e2e wg-quick down wg0 en hub mientras device manda comando device entra en degraded, comando encolado o respuesta mesh_unreachable; al volver hub: handshake reanuda, cola se vacia
Dos devices simultaneos sin interferencia e2e home-wsl y pc-aurgi ejecutan capabilities en paralelo (script python con 2 threads) cada audit chain es independiente, sin cross-contamination; device_audit muestra 2 chains separadas, hash chain valido en cada una
Audit chain valida tras restart e2e matar device_agent mid-flight (kill -9) + relanzar; cmd: device_audit_verify_chain --device home-wsl chain integra, hash anterior coincide, sin huecos
Revoke device <5s e2e desde agents_dashboard panel "Mesh" boton "Revoke home-wsl"; medir tiempo hasta wg show no liste peer peer ausente en <5s; siguientes comandos a #dev-home-wsl -> peer_revoked

Regla: cada fila genera e2e_check en app.md correspondiente (issue 0068). fn-analizador los corre periodicamente.

Vida util validada

Metrica Umbral Donde se observa Ventana
Peers vivos en mesh >=2 constantes (home-wsl + pc-aurgi) agents_dashboard panel "Mesh" (last_handshake < 3min) 7 dias
Crashes device_agent 0 journalctl --user -u device_agent.service en cada device 7 dias
Crashes wg_hub 0 ssh vps journalctl -u wg_hub.service 7 dias
Huecos en audit chain 0 cmd: device_audit_verify_chain --all continuo
Rollback de wg config 0 ocurrencias hub: git -C /etc/wireguard status debe ser clean; sin restore manual 7 dias
Handshake fail rate <5% wg show all dump parseado por agents_dashboard 7 dias
Approval queue stuck 0 pendientes >24h agents_dashboard panel "Approvals" continuo
Comandos exec latencia p95 <3s call_monitor.function_stats para capability.shell.exec 7 dias
Replay attacks bloqueados >=1 detectado y bloqueado (pen-test real) device_audit status=rejected_nonce count 30 dias

User-facing (reforzado)

  • User-facing surface: humano abre Element en movil/web (element.organic-machine.com), entra a #dev-<nombre> y escribe comandos. Output en el mismo room. NO en una BD, NO en un log.
  • User-facing usage real: el operador (humano) usa Element con home-wsl Y pc-aurgi (>=2 maquinas reales), >=1 sesion/dia durante >=7 dias consecutivos, >=20 comandos totales repartidos entre devices.
  • User-facing variado: cubre capabilities de >=4 tipos: read (!fs.read, !ls), write (!fs.write), exec (!exec), approval-required (!fs.write en path sensible), docker (!docker exec).
  • User-facing onboarding: parrafo en ## Notas con pasos numerados: abrir Element -> entrar a room -> !help -> ejemplo de comando. Sin leer el flow entero.
  • User-facing latencia: tras enviar mensaje en Element, output visible en <3s (read/exec) o <5s (con approval) — medido y registrado en ## Notas.

Anti-criterios (invalidan DoD aunque checkboxes verdes)

  • Solo-en-home-wsl: el flow funciona en mi WSL pero falla en pc-aurgi u otro device fisico.
  • device_agent muere cada noche: cualquier crash recurrente del proceso device_agent en los 7 dias de validacion.
  • Approval flow se salta: alguna entrada en device_audit con capability requires_approval=true ejecutada sin approval_msg_id valido.
  • Audit chain rota: device_audit_verify_chain reporta huecos o hash mismatch en algun device.
  • wg config drift: cambios manuales en /etc/wireguard/wg0.conf del hub sin pasar por wg_peer_add/remove/revoke. Git status muestra cambios sin trackear.
  • Dashboard fantasma: agents_dashboard declarado pero el operador no lo abre durante la ventana de 7 dias. Telemetria muerta.
  • Pen-test no ejercitado: replay attack / capability fuera de manifest / token expirado declarados pero sin entry real en device_audit con status rejected_* en los 7 dias.
  • Silent-fail: peer cae >24h y nadie se entera (sin alerta a #operator-approvals ni badge rojo en dashboard).
  • Secrets en repo: cualquier hit de git grep -E 'PrivateKey|PSK|operator/ed25519' -- ':!*.md' en cualquier rama.

Custom (security-specific, deben tener evidencia en device_audit)

  • (custom) Pen-test capability fuera de manifest: entry device_audit status=rejected_capability ejercitado intencionalmente >=1 vez.
  • (custom) Pen-test replay: entry device_audit status=rejected_nonce ejercitado >=1 vez con cmd reproducible.
  • (custom) Stale device: forzar home-wsl offline >24h, verificar badge stale en agents_dashboard + mensaje en #operator-approvals.
  • (custom) Operator key rotation: ejecutar rollover de la clave ed25519 maestra + revoke-all + re-enroll, sin perder audit chain historica. Documentado en ## Notas.

Telemetria esperada

  • call_monitor.calls: cada wg_*, capability.*, docker.* con duration_ms, success.
  • apps/wg_hub/operations.db: tabla wg_peers + device_audit (hash-chained append-only).
  • apps/agents_and_robots/operations.db: tabla matrix_capability_dispatches.
  • apps/agents_dashboard/local_files/agents_dashboard.db: cache devices + approval queue.
  • Dashboards visibles: agents_dashboard panel "Mesh" (peers vivos + last handshake + bytes rx/tx).
  • Matrix room #operator-approvals recibe cada approval_request.
  • Element en movil aprueba/rechaza con reacciones (👍/👎) o comando !approve <id>.

Riesgos / gotchas

  • VPS UDP/51820: firewall del proveedor del VPS puede bloquearlo. Verificar con nc -u -v vps 51820.
  • NAT carrier-grade (4G/5G): device tras NAT estricto → PersistentKeepalive = 25 obligatorio.
  • Sleep laptop / android doze: handshake muere. Auto-reconnect via systemd-networkd-wait-online + script.
  • Privilegio sudo: wg-quick requiere root. Devices necesitan sudo-NOPASSWD para wg-quick@wg0.
  • Clock skew: tokens enrollment + nonces dependen de NTP. Forzar chrony en VPS y devices.
  • Container privileged: modo "deep" docker requiere --cap-add NET_ADMIN. Riesgo si container compromised. Mitigacion: solo modo "deep" para containers de tu propio control (ej. agents_and_robots self-hosted), no third-party.
  • Operator key compromise: si tu ed25519 leaks → cualquiera firma manifests. Plan B: rotacion + revoke-all + re-enroll.
  • Matrix homeserver compromise: chat E2EE protege contenido, pero metadata (quien habla con quien) leak. Aceptable porque homeserver es tuyo en organic-machine.com.

Notas

(rellenar tras ejecutar fases A/C/B/D)

Para hablar con un device desde Element (onboarding)

  1. Abre Element en movil o web (element.organic-machine.com).
  2. Entra al room #dev-<nombre> (un room por device).
  3. Escribe !help → bot del room (agents_and_robots) responde con capability matrix del device.
  4. Escribe comando, ej. !exec ls /home/lucas o !fs.read /var/log/syslog.
  5. Si capability requiere approval, te llega notification a #operator-approvals → reaccionas 👍 → ejecuta.
  6. Output aparece en el mismo room del device.

Para hablar con un container docker

  1. Si el host del container ya esta en la mesh: room #dev-<host> con !docker exec <container> <cmd>.
  2. Modo deep: room dedicado #cont-<container> (solo containers enrolled).