# VPS Health API API sante minimaliste pour le VPS. ~127 lignes, Node 22 + HTTP natif. ## Endpoints - `GET /health` — CPU, memoire, disque, uptime, logto (`{status, responseTimeMs, error?}`) - `GET /defenseurs` — contenu de status.json (rapports defenseurs) - `GET /reports/scans?date=YYYY-MM-DD` — agrege les rapports `defenseur-_*.json` du jour, format `{ date, count, reports: Report[] }`. Filtre `isScanReport` (exclut `defenseur-auto_*.json`). Date validee par regex (path traversal bloque). Consommateur : `defenseur-auto` workstation cron (remplace le pre-rsync SSH). Exemple : `curl -H "Authorization: Bearer $TOKEN" "https://health.lacompagniemaximus.com/reports/scans?date=2026-05-07"`. - `GET /defenseurs/findings?project=X` — findings detailles du Defenseur correspondant. Query params : `project=` (obligatoire, lookup via `agents-map.json`), `category=` (optionnel, exact match), `severity=` (optionnel, threshold inclusif vers le haut). Sans `severity` -> MEDIUM+HIGH+CRITICAL (cache LOW+INFO). `severity=LOW` -> LOW+MEDIUM+HIGH+CRITICAL (cache toujours INFO, asymetrie volontaire). `severity=INFO` -> INFO uniquement (opt-in explicite). Reponses : 200 `{ agent, project, timestamp, findings[] }` si report present (sans champ `status`) ; 200 `{ findings: [], status: "no_data" }` si pas de report ; 400 sans project ou param invalide ; 404 projet inconnu ; 500 si `agents-map.json` corrompu. Consommateurs : admin dashboard Vercel (drill-down), futur skill `/analyse-vulnerabilite`. Exemple : `curl -H "Authorization: Bearer $TOKEN" "https://health.lacompagniemaximus.com/defenseurs/findings?project=la-suite-booking&severity=HIGH"`. ## Auth - Bearer token via env `HEALTH_TOKEN` - Fail-closed : si `HEALTH_TOKEN` non configure, toutes les requetes sont refusees - **Coolify** : `HEALTH_TOKEN` doit etre `is_runtime=true, is_buildtime=false`. Buildtime fait fuiter le secret en clair dans `application_deployment_queues.logs`. Voir `la-compagnie-maximus/docs/coolify-ops.md` section "Secrets en buildtime". ## Config - Port : `3001` (env `PORT`) - `LOGTO_HEALTH_URL` : URL du `.well-known/openid-configuration` (default auth.lacompagniemaximus.com) - `REPORTS_DIR` : dossier lu par `/reports/scans` et `/defenseurs/findings` (default `/data/defenseurs/reports`) - `DEFENSEURS_AGENTS_MAP_PATH` : snapshot project->agent ecrit par le Sergent (default `/data/defenseurs/agents-map.json`) - Bind-mounts read-only sur Coolify : - `/home/defenseur/defenseurs/status.json` -> `/data/defenseurs/status.json` - `/home/defenseur/defenseurs/reports/` -> `/data/defenseurs/reports/` - `/home/defenseur/defenseurs/agents-map.json` -> `/data/defenseurs/agents-map.json` ## Deploy Coolify auto-rebuild depuis push Forgejo. Aucune action manuelle requise. ## Tests - `npm test` (vitest) — couvre `/defenseurs/findings` (14 cas : auth, validation, filtres severity/category, asymetrie INFO, scan clean vs no_data, JSON corrompu) - Runtime reste 0-dep ; vitest en devDep uniquement ## Gotchas - Pas d'Express — HTTP natif Node.js uniquement - Le `status.json` et `agents-map.json` sont ecrits par le Sergent defenseurs, pas par cette API (read-only) - `agents-map.json` doit etre present sur le VPS avant le deploy : verifier via `ssh ubuntu@vps 'ls /home/defenseur/defenseurs/agents-map.json'`. Sinon `/defenseurs/findings` retourne 500. - Severity threshold est asymetrique : `?severity=LOW` retourne LOW+MEDIUM+HIGH+CRITICAL mais cache INFO. INFO est seulement accessible via `?severity=INFO` explicite (cache le bruit par defaut).