---
name: services_api
lang: go
domain: infra
version: 0.1.0
description: "Backend HTTP que monitoriza apps con tag 'service' en el PC local y en PCs remotos via SSH. Loop de checks cada 15s, persistencia en operations.db. Frontend dedicado: app C++ services_monitor. Issue 0106."
tags: [service, monitoring, sqlite, ssh, systemd, http]
uses_functions:
  - sqlite_apply_versioned_migrations_go_infra
  - ssh_exec_go_infra
uses_types:
  - ssh_conn_go_infra
framework: "net/http"
entry_point: "main.go"
dir_path: "apps/services_api"
service:
  port: 8485
  health_endpoint: /api/health
  health_timeout_s: 3
  systemd_unit: services_api.service
  systemd_scope: user
  restart_policy: always
  runtime: systemd-user
  pc_targets:
    - aurgi-pc
    - home-wsl
  is_local_only: false
---

# services_api

## Que hace

Monitor cross-PC de los services del registry (issue 0106).

1. Lee `registry.db` (read-only) → apps con `tag: service` + `service_targets`.
2. Loop cada 15s: por cada (app, pc) chequea systemd + port listening + HTTP health.
3. Local (pc == self): `systemctl is-active`, TCP dial, `http.Client`.
4. Remoto: mismo set de comandos a traves de `ssh_exec_go_infra`. Si no hay ruta SSH → `no-route`.
5. Persistencia en `operations.db`: `service_state` (estado actual) + `service_transition` (cambios).

## Cuando usarla

- Saber de un vistazo que services estan vivos en cada PC.
- Detectar caidas silenciosas (ej. `sqlite_api` murio 20h sin alerta el 2026-05-17).
- Auditar cobertura por PC antes de un deploy.

## Lanzar

```bash
cd apps/services_api
CGO_ENABLED=1 go build -tags fts5 -o services_api .
./services_api --bind 127.0.0.1:8485
# o ./services_api --once para un solo ciclo (smoke)
```

Abrir `http://127.0.0.1:8485` en el navegador.

## Endpoints

| Ruta | Que devuelve |
|---|---|
| `GET /api/health` | `{"status":"ok","self_pc":"..."}` |
| `GET /api/services` | Snapshot completo (`services[]`) + `self_pc` + `ts` |
| `POST /api/check` | Fuerza un ciclo de checks; bloquea hasta completar |
| `GET /api/pcs` | Lista PCs con `services_count` |

## Gotchas

- **PCs remotos sin entrada en `~/.ssh/config`** quedan en `no-route`/`unknown`. Anadir alias antes de esperar status real (ej. `aurgi-pc` no esta en config hoy).
- **Solo lectura de registry.db**; no escribe en el. Las migraciones son sobre la propia operations.db de la app (`apps/services_api/operations.db`, tabla `service_state` + `service_transition`).
- **`overall`** se computa por runtime:
  - `systemd-*` / `stdio`: requiere `systemctl is-active == active`. Si hay puerto, ademas TCP + HTTP 2xx/3xx.
  - `docker-compose` / `manual`: solo puerto + HTTP.
- **Reload de targets** cada 5 min (background) sin reiniciar el proceso. Cambios en `app.md` requieren `./fn index` primero.
- **No expone tools mutadoras** en v1 (start/stop/restart). Solo alerta. Issue 0106 marca auto-fix detras de feature flag para v2.

## Validacion

```bash
./services_api --once && \
  sqlite3 operations.db \
  "SELECT app_id, pc_id, overall FROM service_state ORDER BY app_id, pc_id;"
```


## Capability growth log

Una linea por bump SemVer. Bump-type segun `.claude/commands/version.md`:
- `major`: breaking observable (CLI args, schema BBDD propia, formato wire).
- `minor`: feature aditiva (nuevo panel, endpoint, opcion).
- `patch`: bugfix sin cambio observable.

- v0.1.0 (2026-05-18) — baseline.
