Ajouter les routes POST et GET /claude-usage #48
Labels
No labels
autopilot:pending-human
source:analyste
source:defenseur
source:human
source:medic
status:approved
status:blocked
status:in-progress
status:needs-clarification
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#48
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Refs : spec-decisions-suivi-claude.md + spec-plan-suivi-claude.md (dépôt la-compagnie-maximus). Ce corps est autosuffisant : tout ce qu'il faut pour implémenter est ci-dessous.
Route d'ingestion du snapshot de consommation Claude poussé par l'agent du ThinkPad, et route de lecture pour le dashboard
/admin. C'est la deuxième route d'écriture de l'API : elle a son propre token et ne doit jamais accepter celui des postes.Contrat du snapshot (
schemaVersion: 1, figé)Corps de
POST /claude-usage, partagé entrevps-health-api(agent + serveur) etla-compagnie-maximus(dashboard) :Bornes serveur (
sanitizeClaudeUsage, liste blanche, tout champ inconnu jeté) : corps ≤ 64 Ko ;days≤ 31,date^\d{4}-\d{2}-\d{2}$;models≤ 12 clés^[a-z0-9][a-z0-9.\-]{0,63}$;limits.items≤ 12 ;projects≤ 9 ; nombresNumber.isSafeInteger≥ 0,percent0-100 ;statusdans l'enum ;detail^[a-z0-9_]{1,32}$sinon jeté ; autres chaînes ≤ 128 car. ; dates ISO validées. Le serveur ajoutereceivedAt.Réponse de
GET /claude-usage:{ staleAfterSeconds, receivedAt, ageSeconds, stale, snapshot }, ou{ "status": "no_data" }si le fichier est absent ou illisible.Tâches
checkAuth(aujourd'hui binaire :tokenKind === "ingest"→HOSTS_INGEST_TOKEN, sinonHEALTH_TOKEN) lit une tabletokenKind→ token :read→HEALTH_TOKEN,ingest→HOSTS_INGEST_TOKEN,claude-ingest→CLAUDE_USAGE_INGEST_TOKEN. Réponse quand le token manque définie par entrée :read→ 401 comme aujourd'hui, chaque ingestion → 503 nommant sa propre variable. Comparaison viatokenMatchespour toutes les entrées. Le gate reste le point unique d'authentification.readBody(req, res, maxBytes):/hosts/<id>garde 4096 (constante actuelleMAX_BODY_BYTES),/claude-usagepasse 65536. Plafond compté sur les octets reçus.claude-usage.jsà la racine, à côté demetrics.js:sanitizeClaudeUsage+ bornes du contrat, exporté.index.jsne fait que brancher les routes. Ajouterclaude-usage.jsà la ligneCOPYduDockerfileet mettre à jour le test de__tests__/agent.test.jsqui fige cette liste (il interditCOPY . .et l'agent, pas un nouveau fichier serveur).CLAUDE_USAGE_INGEST_TOKEN,CLAUDE_USAGE_PATH(défaut/data/claude-usage/claude-usage.json),CLAUDE_USAGE_STALE_SECONDS(défaut 2700).POST /claude-usage(tokenKind: "claude-ingest") : JSON invalide → 400 ;sanitizeClaudeUsage;receivedAtserveur ; écriture atomique (tmp suffixé pid + rename, mode 600, patronwriteHostSnapshot) ; 204.GET /claude-usage(tokenKind: "read") : fichier re-sanitisé +ageSeconds,stale(ageSeconds > CLAUDE_USAGE_STALE_SECONDS),staleAfterSeconds;{status:"no_data"}si absent ou illisible.README.md: les deux routes, les trois env vars, le montage/data/claude-usage(lecture-écriture, propriétaire uid 1000).Fichiers concernés
index.jsclaude-usage.js(nouveau)Dockerfile__tests__/agent.test.js__tests__/claude-usage.test.js(nouveau)README.mdCritères d'acceptation
HOSTS_INGEST_TOKENsur/claude-usage→ 401 ; token Claude surPOST /hosts/<id>→ 401CLAUDE_USAGE_INGEST_TOKENnon posé → 503 dont le message nommeCLAUDE_USAGE_INGEST_TOKEN(et/hostsgarde son 503 nommantHOSTS_INGEST_TOKEN)/hosts/<id>toujours 413 à 4 097 octetsdetailhors regex,statushors enum : jetés (testé)receivedAt,ageSeconds,stale{status:"no_data"}hosts,auth,findings,health,state,agent) passe sans modification autre que la listeCOPYdu test agentReview caveats
detailjamais en texte libre (risque de transporter un corps de réponse amont).Décisions prises en planification
CLAUDE_USAGE_INGEST_TOKEN(rotation indépendante, isolation des routes).stale) ; le dashboard ne la recalcule pas.index.js, pour que l'agent (issue suivante) teste son snapshot contre le vrai sanitizer.Spec source
la-compagnie-maximus :
spec-plan-suivi-claude.md, Issue 1