Ajouter l'ingestion et la lecture des postes (POST /hosts/<id>, GET /hosts) #13
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#13
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?
Ouvrir la premiere surface d'ecriture de l'API : les postes de travail poussent leur snapshot CPU / RAM / disque, le dashboard admin le relit date. Le routage passe d'une liste exacte a une table de descripteurs, en conservant un point de controle d'auth unique.
Contrat
POST /hosts/<id>—Authorization: Bearer $HOSTS_INGEST_TOKEN. Corps JSON de la forme deGET /healthmoinslogtoettimestamp:hostname,uptime,cpu{model,cores,loadAvg,usagePercent},memory{totalGB,usedGB,freeGB,usagePercent},disk{...}.<id>bien forme mais hors allowlist<id>hors format (la requete n'atteint jamais le handler)HOSTS_INGEST_TOKENnon configure (fail-closed)GET /hosts—Authorization: Bearer $HEALTH_TOKEN. Retourne{ staleAfterSeconds, hosts: [{ id, hostname, uptime, cpu, memory, disk, receivedAt, ageSeconds, online, neverSeen? }] }.online = ageSeconds <= 900. Horodatage pose par le SERVEUR a la reception, jamais par le client.Fichiers concernes
index.js(modifier : routage, auth, deux routes).env.example(modifier)CLAUDE.md(modifier)README.md(modifier : table des endpoints, table de config, liste des bind-mounts)Depends on
Criteres d'acceptation
{ method, handler, requiredToken }, refus par defaut si aucune route ne correspond, puis UN SEUL controle de token avant dispatch^/hosts/([a-z0-9][a-z0-9-]{0,31})$restreinte a POST, jamais elargietokenMatches()entimingSafeEqualsur empreintes SHA-256, applique au seul nouveau chemin d'ingestionreq.destroy()au-dela, sans se fier auContent-LengthHOSTS_ALLOWED_IDS; ses propres entrees validees par la meme regex au demarrage, entrees refusees journalisees et ecarteesNumber.isFinite, chaines plafonnees a 128 caracteres — jamais le payload verbatimrenameSyncX-Real-IP, l'identifiant et le motifGET /hostsdegrade une entree corrompue sans faire tomber la reponse entiereHOSTS_DIR,HOSTS_ALLOWED_IDS,HOSTS_INGEST_TOKEN,HOSTS_STALE_SECONDS(defaut 900) dans.env.exampleReview caveats
new URL()normalise/hosts/../../etc/passwden/etc/passwd, et..%2fcommeTHINKPADechouent la regex. Tous tombent en 404. La regex etroite EST le controle anti-traversee : ne jamais l'elargir en^/hosts/(.+)$pour faire passer un test.GET /hostset finit dans l'arbre React de l'admin — d'ou la liste blanche de champs (une cle__proto__ou unhostnamede 4 Kio ne doit jamais y arriver).Decisions prises en planification
thinkpadseul : le Pop!_OS est hors scope.neverSeenest conserve, mais justifie par le diagnostic de mise en service (entre le deploiement et le premier battement, la carte dit « agent non installe » au lieu de rester muette).HEALTH_TOKENexistant est explicitement HORS de cette issue (issue separee) : il touche tous les chemins de lecture en production.Spec source
la-compagnie-maximus/spec-plan-monitoring-postes.md + spec-decisions-monitoring-postes.md (depot different : ce body est auto-suffisant, ne pas compter sur le fichier) (Issue 3)