feat(defenseurs): add GET /defenseurs/findings?project=X route #9
No reviewers
Labels
No labels
source:analyste
source:defenseur
source:human
source:medic
status:approved
status:blocked
status:in-progress
status:needs-fix
status:ready
status:review
status:triage
type:bug
type:feature
type:infra
type:refactor
type:schema
type:security
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: maximus/vps-health-api#9
Loading…
Reference in a new issue
No description provided.
Delete branch "issue-3-defenseurs-findings"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Fixes #3
Summary
Adds
GET /defenseurs/findings?project=Xto drill into a project's Defenseur findings via HTTP+Bearer. Designed for the Vercel admin dashboard (no SSH/Tailscale path) and a future portable/analyse-vulnerabiliteskill.Behavior
projectparamcategory/severityagents-map.json){findings: [], status: "no_data"}{agent, project, timestamp, findings: []}(nostatusfield){agent, project, timestamp, findings: [...]}agents-map.jsonunreadable / corruptedSeverity rule (asymmetric — see issue #3 clarif 2026-05-12)
severity->MEDIUM+HIGH+CRITICAL(default hides noise)severity=LOW->LOW+MEDIUM+HIGH+CRITICALbut always hidesINFOseverity=INFO->INFOonly (explicit opt-in)Implementation
allowedSeverities(threshold),findLatestReportForAgent(agent)(scansREPORTS_DIRandREPORTS_DIR/archive, picks the freshest bytimestamp)DEFENSEURS_AGENTS_MAP_PATH(default/data/defenseurs/agents-map.json)validRoutesserver.listenguarded byrequire.main === moduleso tests can spin up ephemeral serversTests
Bootstraps vitest (devDep; runtime stays 0-dep). 14 tests, all green:
?category=depsexact match?severity=HIGH→ HIGH+CRITICAL?severity=LOW→ LOW+MEDIUM+HIGH+CRITICAL, hides INFO?severity=INFO→ INFO onlyarchive+ top-levelstatusfield{findings:[], status:"no_data"}agents-map.jsonPre-merge checklist (operational, out of repo)
ls /home/defenseur/defenseurs/agents-map.json(j'ai pas pu valider — Tailscale SSH demande auth navigateur)/home/defenseur/defenseurs/agents-map.json->/data/defenseurs/agents-map.jsonavant le deploy (sinon la route renvoie 500)Test plan
npm test-> 14/14 vertagents-map.jsonpresent sur le VPScurl -H "Authorization: Bearer $TOKEN" "https://health.lacompagniemaximus.com/defenseurs/findings?project=la-suite-booking&severity=HIGH"🤖 Generated with Claude Code
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>Verdict: APPROVE
Clean implementation of
/defenseurs/findingsmatching the issue #3 spec (asymmetric INFO severity rule included). 14 vitest tests cover auth, validation, filter combinations, latest-report-across-archive, scan-clean vs no_data, and corruptagents-map.json— all green locally. No security regressions: path traversal is structurally prevented (projectis a map key, never a path component); theagentvalue used as filename prefix comes from the server-controlledagents-map.jsonwritten by the Sergent.Suggestions (non-blocking)
.env.examplemissingDEFENSEURS_AGENTS_MAP_PATH— the new env var is documented inCLAUDE.mdandREADME.mdbut not in.env.example. Worth adding for parity._tsmutation infindLatestReportForAgent(index.js:195-205) — assigning thendelete-ing_tson the parsed report works but mutates the user-facing payload. A separatelatestTsvariable would keep the parsed object pristine. Cosmetic.err.messagefor corruptagents-map.json(index.js:307-309). Consistent with the existing/reports/scans500 branch — not a new regression, but worth either suppressing in both places or explicitly accepting as intentional for a Bearer-gated internal API.{findings:[], status:"no_data"}omitsagent/project/timestampwhile the present-report case includes them. Spec-aligned and tested, but consumers (Vercel dashboard,/analyse-vulnerabilite) will need to handle the union. Worth flagging in the README field table.agents-map.jsonpresence on VPS) is the real risk — code is correct but deploy without those surfaces as 500s. Verify both before merging.Checks
npm test-> 14/14)feat(defenseurs): ...)require.main === moduleguard) is correctly scoped — only theserver.listenis gated, the handler/exports are always available/defenseurs/findingschecked before the fallthrough to/healthand not shadowed by/defenseurs(exact-equality routing)Adversarial review by Claude Code.
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.