Drill-down endpoint exposing detailed findings per project. Resolves the
HTTP gap for the Vercel admin dashboard, which cannot SSH/Tailscale to
the VPS, plus a future portable /analyse-vulnerabilite skill.
- Project -> agent lookup via /data/defenseurs/agents-map.json (Sergent snapshot)
- findLatestReportForAgent scans REPORTS_DIR + REPORTS_DIR/archive (post-07:30 UTC rotation)
- Filters: category exact match, severity threshold inclusive upward
- Asymmetric severity rule: default hides LOW+INFO; ?severity=LOW returns
LOW+MEDIUM+HIGH+CRITICAL but still hides INFO; INFO opt-in via explicit param
- Distinguishes "report present + scan clean" (no status field) from
"no report at all" ({findings:[], status:"no_data"})
- Bootstraps vitest (devDep; runtime stays 0-dep), 14 tests covering auth,
validation, filters, asymmetry, mtime selection, error paths
- Refactor: export handler so tests can spin up ephemeral servers; server.listen
guarded by require.main === module
Closes #3
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3.6 KiB
3.6 KiB
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 rapportsdefenseur-<agent>_<date>*.jsondu jour, format{ date, count, reports: Report[] }. FiltreisScanReport(exclutdefenseur-auto_*.json). Date validee par regex (path traversal bloque). Consommateur :defenseur-autoworkstation 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=<name>(obligatoire, lookup viaagents-map.json),category=<deps|secrets|code|acces|infra>(optionnel, exact match),severity=<CRITICAL|HIGH|MEDIUM|LOW|INFO>(optionnel, threshold inclusif vers le haut). Sansseverity-> 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 champstatus) ; 200{ findings: [], status: "no_data" }si pas de report ; 400 sans project ou param invalide ; 404 projet inconnu ; 500 siagents-map.jsoncorrompu. 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_TOKENnon configure, toutes les requetes sont refusees - Coolify :
HEALTH_TOKENdoit etreis_runtime=true, is_buildtime=false. Buildtime fait fuiter le secret en clair dansapplication_deployment_queues.logs. Voirla-compagnie-maximus/docs/coolify-ops.mdsection "Secrets en buildtime".
Config
- Port :
3001(envPORT) LOGTO_HEALTH_URL: URL du.well-known/openid-configuration(default auth.lacompagniemaximus.com)REPORTS_DIR: dossier lu par/reports/scanset/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.jsonetagents-map.jsonsont ecrits par le Sergent defenseurs, pas par cette API (read-only) agents-map.jsondoit etre present sur le VPS avant le deploy : verifier viassh ubuntu@vps 'ls /home/defenseur/defenseurs/agents-map.json'. Sinon/defenseurs/findingsretourne 500.- Severity threshold est asymetrique :
?severity=LOWretourne LOW+MEDIUM+HIGH+CRITICAL mais cache INFO. INFO est seulement accessible via?severity=INFOexplicite (cache le bruit par defaut).