feat(backups): pass the files[] block of status.json through GET /backups #61
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#61
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?
Contexte
Since la-compagnie-maximus#295 (installed on the VPS 2026-10-12, vps-health-api#55),
backup-postgres.sharchives the host directories listed inFILE_SOURCES(todayclaude-usage=/data/claude-usage) and writes one entry per directory in a newfiles[]block ofstatus.json:sanitizeBackupsStatus()(backups.js) rebuilds the status from a whitelist, so it dropsfilessilently today. The globalokalready accounts for the files (the script folds them in), so a failed archive turns the status red, butGET /backupsgives no cause.Scope decided on 2026-10-12 (Max): this issue covers vps-health-api only. Showing the block on
/adminbelongs to la-compagnie-maximus#254 (the card does not exist yet), noted there in a comment.Travail
backups.js:FILE_NAME_RE = /^[a-z0-9_-]{1,63}$/(the script's own pattern, plus the 63 bound), a separateFILE_ERROR_CODESclosed list (source_missing,archive_failed,encrypt_failed,invalid_name, exactly what the script can write; decided 2026-10-12),MAX_FILESbound (16),sanitizeFile()on the model ofsanitizeDatabase()(name,sizeBytes,archivedAtnullable viaputNullable,ok,error), andstatus.filesfilled likestatus.databases(only when the payload has an array). ExportMAX_FILESandFILE_ERROR_CODES.__tests__/backups.test.js: addfilestovalidStatus()(the script's real output, so the identity and idempotence tests cover it), then cases on the model ofdatabases: unknown field and__proto__dropped inside an entry;archivedAt: nullkept; invalidsizeBytes/archivedAt/okdropped, never forced; each of the four codes kept; a database-only code (dump_failed) dropped on a file entry, and a file-only code (source_missing) dropped on a database entry; a name outside the regex dropped with the entry kept; bound atMAX_FILES; non-object entries filtered;filesabsent (older script) -> nofileskey, novpsError;filesnot an array -> dropped, the rest served.GET /backupsservesvps.filesfrom a fixture file (one case in theGET /backupsblock).CLAUDE.md:GET /backupsparagraph (thefilesblock, its regex, codes, bound), the test count line forbackups.test.jsand the total.Fichiers concernés
backups.js(sanitizer, constants, exports)__tests__/backups.test.jsCLAUDE.mdNo change to the routes, auth, the Dockerfile
COPY(backups.jsalready in it) nortest-curl.sh(pure sanitizer logic, nothing a real socket adds).Surface de test
__tests__/backups.test.js, blocksanitizeBackupsStatus — the whitelist(around line 202, the model for every new case) andGET /backups(around line 581).writes.test.jsandauth.test.js: unaffected (no new route, no new write).filesinvalidStatus()pins the real script output.Critères d'acceptation
GET /backupsreturnsvps.filesas written by the script, unchanged.status.jsonwithoutfileskeeps working (novpsError, nofileskey).npm test,bash test-curl.sh,sh scripts/boot-from-copy.shgreen; mutation check on the regex, the code list and the bound.GET /backupsin prod showsvps.files[0].name == "claude-usage".Complexité
Simple: one pure function and one test block, on an existing pattern.
Done on 2026-10-12.
main@9fa1f39), review APPROVE; suggestion 1 (wording of the shared codes inCLAUDE.md) applied in9fa1f39, suggestion 2 noted as harmless.lw8skook4c80o0kgcg0gkkc0: finished.RW=falseon both Defenseurs mounts and/data/backups-status,RW=trueon/data/hosts,/data/claude-usage,/data/backups-pull.GET /backups:vps.ok: true, novpsError,vps.files = [{ name: "claude-usage", sizeBytes: 2466, archivedAt: "2026-10-12T23:52:38Z", ok: true }].Display on
/admin: la-compagnie-maximus#254. Closing.