vps-health-api : endpoint GET /defenseurs/state #27

Closed
opened 2026-09-23 01:35:10 +00:00 by maximus · 0 comments
Owner

Refs: maximus/agent-defenseurs — spec-decisions-signal-honnete.md + spec-plan-signal-honnete.md (Issue 5 du plan). Origine : docs/revue-2026-09-21.md §8.1.

Contexte

Le Sergent (maximus/agent-defenseurs#127, fermee) persiste desormais un etat par identifiant de finding (firstSeen, unverified, historique 30 jours) dans findings-state.json, a cote de status.json. Le dashboard admin (Issue 6 du plan) le recupere en parallele de /defenseurs pour le drill-down : seul cet etat porte l'age et le statut « non verifie ». /defenseurs/findings reste en place pour findings-cli et les skills.

Chemin : le Sergent ecrit par defaut dans dirname(realpath(statusPath))/findings-state.json, soit /data/defenseurs/findings-state.json sur le VPS. Le bind-mount /data/defenseurs (lecture seule) le couvre deja : aucun nouveau Persistent Storage.

Depend de maximus/agent-defenseurs#127 (format du fichier) — deja fermee, rien ne bloque.

Decisions (analyse du 2026-09-24)

  • Service brut, meme contrat que /defenseurs : lecture du fichier et renvoi tel quel, sans JSON.parse. Le Sergent ecrit en atomique (tmp + rename) et isole lui-meme un etat illisible en .corrupt-*. Un fichier illisible cote lecteur fait echouer le .json() du dashboard, qui bascule alors en mode degrade (deja prevu).
  • Pas de controle de fraicheur ici : l'alarme de peremption est calculee cote dashboard (decision de la spec).
  • Helper partage serveJsonFile(res, path) utilise par handleDefenseurs et le nouveau handler : un seul comportement no_data pour les deux routes.

Taches

  • index.js : extraire serveJsonFile(res, path) (200 + contenu brut, ou 200 {"status":"no_data"} sur toute erreur de lecture) ; handleDefenseurs l'utilise.
  • index.js : handleDefenseursState qui lit process.env.DEFENSEURS_FINDINGS_STATE_PATH || "/data/defenseurs/findings-state.json" (lu a la requete, comme DEFENSEURS_STATUS_PATH, pour que les tests puissent le surcharger).
  • Table ROUTES : { method: "GET", path: "/defenseurs/state", tokenKind: "read", handle: handleDefenseursState } a cote de /defenseurs et /defenseurs/findings. Aucun changement a resolveRoute ni checkAuth.
  • Tests (nouveau __tests__/state.test.js, ou section dans findings.test.js) : fichier present -> 200 et corps identique octet pour octet ; fichier absent -> 200 {status:"no_data"} ; sans token -> 401 ; mauvais token -> 401 ; POST /defenseurs/state -> 404 (pas 401).
  • __tests__/auth.test.js : ajouter /defenseurs/state a la liste ROUTES de la matrice 401.
  • Non-regression /defenseurs apres extraction du helper (present / absent).
  • Doc : README.md (table des endpoints + section, variable DEFENSEURS_FINDINGS_STATE_PATH dans la table de config, montage) et CLAUDE.md (endpoint, config, mention que le montage /data/defenseurs couvre findings-state.json, compteur de tests).

Fichiers concernes

  • index.js — helper, handler, entree ROUTES
  • __tests__/state.test.js (nouveau) ou __tests__/findings.test.js — tests de la route
  • __tests__/auth.test.js — matrice 401
  • README.md, CLAUDE.md — doc
  • test-curl.sh — optionnel : un cas 200/no_data et un 401 au niveau socket
  • Dockerfile — pas de changement (aucun nouveau module)

Criteres d'acceptation

  • GET /defenseurs/state avec HEALTH_TOKEN -> 200 et contenu brut de findings-state.json
  • Fichier absent -> 200 {"status":"no_data"}
  • Sans token / token faux -> 401 ; methode autre que GET -> 404
  • HOSTS_INGEST_TOKEN refuse sur cette route (401)
  • /defenseurs inchange (tests existants verts)
  • npm test et bash test-curl.sh verts
  • Apres merge : redeploy Coolify force (pas d'auto-deploy), puis curl -H "Authorization: Bearer $TOKEN" https://health.lacompagniemaximus.com/defenseurs/state -> 200 (ou no_data si le Sergent v2 n'a pas encore tourne)

Complexite estimee

Simple.

Refs: maximus/agent-defenseurs — `spec-decisions-signal-honnete.md` + `spec-plan-signal-honnete.md` (Issue 5 du plan). Origine : `docs/revue-2026-09-21.md` §8.1. ## Contexte Le Sergent (maximus/agent-defenseurs#127, **fermee**) persiste desormais un etat par identifiant de finding (`firstSeen`, `unverified`, historique 30 jours) dans `findings-state.json`, a cote de `status.json`. Le dashboard admin (Issue 6 du plan) le recupere en parallele de `/defenseurs` pour le drill-down : seul cet etat porte l'age et le statut « non verifie ». `/defenseurs/findings` reste en place pour `findings-cli` et les skills. Chemin : le Sergent ecrit par defaut dans `dirname(realpath(statusPath))/findings-state.json`, soit `/data/defenseurs/findings-state.json` sur le VPS. Le bind-mount `/data/defenseurs` (lecture seule) le couvre deja : aucun nouveau Persistent Storage. Depend de maximus/agent-defenseurs#127 (format du fichier) — deja fermee, rien ne bloque. ## Decisions (analyse du 2026-09-24) - **Service brut**, meme contrat que `/defenseurs` : lecture du fichier et renvoi tel quel, sans `JSON.parse`. Le Sergent ecrit en atomique (tmp + rename) et isole lui-meme un etat illisible en `.corrupt-*`. Un fichier illisible cote lecteur fait echouer le `.json()` du dashboard, qui bascule alors en mode degrade (deja prevu). - **Pas de controle de fraicheur** ici : l'alarme de peremption est calculee cote dashboard (decision de la spec). - **Helper partage** `serveJsonFile(res, path)` utilise par `handleDefenseurs` et le nouveau handler : un seul comportement `no_data` pour les deux routes. ## Taches - [ ] `index.js` : extraire `serveJsonFile(res, path)` (200 + contenu brut, ou 200 `{"status":"no_data"}` sur toute erreur de lecture) ; `handleDefenseurs` l'utilise. - [ ] `index.js` : `handleDefenseursState` qui lit `process.env.DEFENSEURS_FINDINGS_STATE_PATH || "/data/defenseurs/findings-state.json"` (lu a la requete, comme `DEFENSEURS_STATUS_PATH`, pour que les tests puissent le surcharger). - [ ] Table `ROUTES` : `{ method: "GET", path: "/defenseurs/state", tokenKind: "read", handle: handleDefenseursState }` a cote de `/defenseurs` et `/defenseurs/findings`. Aucun changement a `resolveRoute` ni `checkAuth`. - [ ] Tests (nouveau `__tests__/state.test.js`, ou section dans `findings.test.js`) : fichier present -> 200 et corps identique octet pour octet ; fichier absent -> 200 `{status:"no_data"}` ; sans token -> 401 ; mauvais token -> 401 ; `POST /defenseurs/state` -> 404 (pas 401). - [ ] `__tests__/auth.test.js` : ajouter `/defenseurs/state` a la liste `ROUTES` de la matrice 401. - [ ] Non-regression `/defenseurs` apres extraction du helper (present / absent). - [ ] Doc : `README.md` (table des endpoints + section, variable `DEFENSEURS_FINDINGS_STATE_PATH` dans la table de config, montage) et `CLAUDE.md` (endpoint, config, mention que le montage `/data/defenseurs` couvre `findings-state.json`, compteur de tests). ## Fichiers concernes - `index.js` — helper, handler, entree `ROUTES` - `__tests__/state.test.js` (nouveau) ou `__tests__/findings.test.js` — tests de la route - `__tests__/auth.test.js` — matrice 401 - `README.md`, `CLAUDE.md` — doc - `test-curl.sh` — optionnel : un cas 200/no_data et un 401 au niveau socket - `Dockerfile` — **pas** de changement (aucun nouveau module) ## Criteres d'acceptation - [ ] `GET /defenseurs/state` avec `HEALTH_TOKEN` -> 200 et contenu brut de `findings-state.json` - [ ] Fichier absent -> 200 `{"status":"no_data"}` - [ ] Sans token / token faux -> 401 ; methode autre que GET -> 404 - [ ] `HOSTS_INGEST_TOKEN` refuse sur cette route (401) - [ ] `/defenseurs` inchange (tests existants verts) - [ ] `npm test` et `bash test-curl.sh` verts - [ ] Apres merge : redeploy Coolify **force** (pas d'auto-deploy), puis `curl -H "Authorization: Bearer $TOKEN" https://health.lacompagniemaximus.com/defenseurs/state` -> 200 (ou `no_data` si le Sergent v2 n'a pas encore tourne) ## Complexite estimee Simple.
maximus added this to the spec-signal-honnete milestone 2026-09-23 01:35:10 +00:00
maximus added the
status:ready
type:feature
source:human
labels 2026-09-23 01:35:10 +00:00
maximus added
status:review
and removed
status:ready
labels 2026-09-25 00:31:38 +00:00
maximus added
status:approved
and removed
status:review
labels 2026-09-25 00:34:13 +00:00
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: maximus/vps-health-api#27
No description provided.