feat(backups): pass the files[] block of status.json through GET /backups #62
No reviewers
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#62
Loading…
Reference in a new issue
No description provided.
Delete branch "issue-61-backups-files"
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 #61
backup-postgres.shwritesfiles[]instatus.jsonsince la-compagnie-maximus#295 (installed on the VPS 2026-10-12).sanitizeBackupsStatus()dropped it as an unknown field: a failed archive turned the status red with no cause.Change
backups.js:sanitizeFile()on the model ofsanitizeDatabase().FILE_ERROR_CODESis a closed list of its own (source_missing,archive_failed,encrypt_failed,invalid_name): a database code is dropped on a file entry and the reverse.FILE_NAME_RE = /^[a-z0-9_-]{1,63}$/(the script's pattern, hyphen allowed; the 63 cap is the API's own bound, as for databases).archivedAtnullable.MAX_FILES = 16. An empty list is kept, an absent one gives no key and no error (script older than #295).__tests__/backups.test.js:validStatus()now carriesfilesin the script's real shapes (ok entry,source_missingwith null and 0,encrypt_failedwith a time and a size), so the identity, idempotence and route tests cover it. 13 new cases (102 -> 115).CLAUDE.md:GET /backupscontract and test counts.No change to the routes, auth, the Dockerfile
COPYortest-curl.sh. The/admindisplay belongs to la-compagnie-maximus#254 (contract noted there).Verification
npm test879/879,bash test-curl.sh57/57,sh scripts/boot-from-copy.shPASS.backups.js, each restored from a copy (suite green again after):invalid_nameremoved from the file listarchivedAtnull not keptfilesblock removedPost-merge checklist (hence
Refs, not a closing keyword)GET /backupsin prod:vps.files[0].name == "claude-usage",ok: true, novpsError.🤖 Generated with Claude Code
Verdict : APPROVE
Résumé :
sanitizeFile()reprend fidèlement le patron desanitizeDatabase()et colle au contrat réel debackup-postgres.sh(la-compagnie-maximusbd38f21) : mêmes clés{ name, sizeBytes, archivedAt, ok, error? },archivedAtànullviaat or None, regex de nom^[a-z0-9_-]+$, quatre codes d'erreur possibles et aucun autre. Routes, auth,COPYet surfaces d'écriture inchangés.Vérifications rejouées par le relecteur
329d83e: 879/879.329d83e:success(statut de commit).pull_refenref_action: "none". Aucune fermeture au merge, cohérent avec leRefset la checklist post-merge.entries(lines, "archivedAt"),encrypt_failedqui gardearchivedAtetsizede l'archive en clair,invalid_namequi peut porter un nom arbitraire (filtré parFILE_NAME_RE), liste vide quandFILE_SOURCESest vide.Mutations du relecteur (
backups.js, copie hors dépôt,backups.test.js)VPS_ERROR_CODES) sur un fichiersliceavantfilterarchivedAtnon nullable^sizeBytesrecopié tel quelokrecopié tel quelfilesrecopié tel quelFichier restauré, puis suite complète de nouveau à 879/879.
Suggestions (non bloquantes)
CLAUDE.md: « un code de base est jeté sur un fichier et l'inverse » est vrai pour les codes exclusifs seulement.encrypt_failedetinvalid_namefigurent dans les deux listes et passent des deux côtés. Une précision d'une ligne (« sauf les deux codes communs ») éviterait une lecture trop stricte.invalid_namedont la paire n'a pas de=(name = pair) garde un nom conforme à la regex. C'est sans danger (le nom passe la liste blanche) et l'affichage/admin(la-compagnie-maximus#254) n'a rien à prévoir de particulier. Je le note pour mémoire.Actions faites
scratchpad/pr62-copysupprimée en fin de revue.