feat(api): HTTP API REST+SSE para gestion remota de agentes (issue 0128)

Nuevo paquete internal/api con servidor HTTP stdlib (sin gin/echo):
- Auth Bearer via AGENTS_API_KEY con subtle.ConstantTimeCompare
- REST: GET /health (sin auth), GET/POST /agents, /agents/{id}, /{id}/{start,stop,restart,logs}
- SSE: /sse/status (broadcast diffs cada 2s) y /sse/agents/{id}/logs (tail -f)
- Pubsub in-memory (TODO: NATS cuando haya 2do cliente)
- Tail de logfiles: retroalimenta ultimos 50KB + poll 200ms para streaming

Integracion en cmd/launcher/main.go:
- Flag --api-port (0=desactivado, 8487 en produccion)
- Flag --api-key (override de AGENTS_API_KEY env var)
- Si apiPort>0 y sin clave, WARN y deshabilita en vez de fallar

Systemd unit en systemd/agents_and_robots.service:
- Restart=always (no on-failure — evita que exit limpio mate el service)
- EnvironmentFile para AGENTS_API_KEY y demas tokens
- WorkingDirectory=/home/ubuntu/CodeProyects/agents_and_robots

app.md v0.2.0:
- port: 8487, health_endpoint: /health (fix drift anterior donde era null)
- e2e_checks: build, tests, smoke_health, smoke_auth
- Documentacion Traefik+DNS pendiente humano post-merge

Tests: 12 tests unitarios en internal/api (auth, health, bus, agents, logs)
Smoke: /health 200, /agents sin auth 401, /agents con key 200 — verificado local

Co-Authored-By: fn-constructor (agent)
This commit is contained in:
2026-05-22 21:19:10 +02:00
parent 1f90953ccc
commit 98839cd8a8
10 changed files with 1110 additions and 7 deletions
+67
View File
@@ -43,6 +43,73 @@ Desde la TUI puedes:
---
## HTTP API (v0.1)
El launcher expone una API REST + SSE cuando se arranca con `--api-port <N>`.
### Arrancar con API habilitada
```bash
# Requiere AGENTS_API_KEY en .env (generar con: openssl rand -hex 32)
./bin/launcher --log-level info --api-port 8487
# Con systemd (VPS):
sudo systemctl start agents_and_robots.service
```
### Autenticacion
Todos los endpoints (excepto `/health`) requieren:
```
Authorization: Bearer <AGENTS_API_KEY>
```
Comparacion con `crypto/subtle.ConstantTimeCompare` — resistente a timing attacks.
### Endpoints REST
```bash
# Liveness (sin auth)
curl http://localhost:8487/health
# Listar agentes
curl -H "Authorization: Bearer $AGENTS_API_KEY" http://localhost:8487/agents
# Detalle + logs de un agente
curl -H "Authorization: Bearer $AGENTS_API_KEY" http://localhost:8487/agents/assistant-bot
# Control
curl -X POST -H "Authorization: Bearer $AGENTS_API_KEY" http://localhost:8487/agents/assistant-bot/stop
curl -X POST -H "Authorization: Bearer $AGENTS_API_KEY" http://localhost:8487/agents/assistant-bot/start
curl -X POST -H "Authorization: Bearer $AGENTS_API_KEY" http://localhost:8487/agents/assistant-bot/restart
# Logs snapshot
curl -H "Authorization: Bearer $AGENTS_API_KEY" "http://localhost:8487/agents/assistant-bot/logs?n=50"
```
### Endpoints SSE
```bash
# Stream de cambios de estado (stop/start) — un evento por transicion
curl -N -H "Authorization: Bearer $AGENTS_API_KEY" http://localhost:8487/sse/status
# Tail en vivo del logfile de un agente (< 1s de lag)
curl -N -H "Authorization: Bearer $AGENTS_API_KEY" http://localhost:8487/sse/agents/assistant-bot/logs
```
### En produccion (VPS)
El VPS expone la API via Traefik con TLS en `agents.organic-machine.com`.
Los pasos DNS + Traefik los configura el humano tras el merge (ver `app.md` seccion Traefik).
```bash
# Con Traefik configurado:
curl -fsS -H "Authorization: Bearer $AGENTS_API_KEY" https://agents.organic-machine.com/agents
```
---
## Principio de diseño
El proyecto usa el patrón **pure core / impure shell**: