fix(ops): la sauvegarde des contrats archivait le mauvais repertoire

OBS-006. Trois racines etaient baties sur os.getcwd() : le magasin de
documents, les journaux et les sauvegardes. La vague G a corrige la
premiere, parce qu'elle bloquait aussi OPS-011, et a laisse les deux autres.
C'est la lecon deja consignee deux fois : un motif fautif corrige dans une
seule couche reste dans les autres.

Le plus serieux n'est pas le motif, c'est l'ecart qu'il a ouvert.
backup.py gardait sa propre constante DOCUMENTS_DIR sur os.getcwd(), donc
il ignorait DOCUMENTS_ROOT -- la variable que la vague G a introduite et que
docs/deployment.md dit maintenant de regler pour sortir les televersements
des repertoires de version. Des qu'un exploitant suit cette consigne, le
script archive un repertoire ou l'application n'a jamais rien ecrit. Et
comme il repond a un repertoire absent par une ligne d'information et un
code de sortie 0, une tache planifiee qui surveille le code de sortie voit
vert indefiniment.

Autrement dit : plus l'exploitant suivait correctement la documentation de
deploiement, plus surement ses sauvegardes de contrats etaient vides.

Les trois racines viennent desormais d'app/storage.py, resolues a l'appel et
non a l'import, et la sauvegarde imprime la source qu'elle a utilisee. Le
message d'absence nomme le chemin ou elle a cherche : "No documents
directory found" se lisait comme "il n'y a pas de documents" plutot que
comme "je regarde au mauvais endroit".

Le test qui porte est celui qui ouvre l'archive : un zip vide est un fichier
de taille non nulle, donc verifier qu'un fichier a ete produit ne prouvait
rien. Verifie par mutation.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
GGThed
2026-08-11 18:34:52 -04:00
co-authored by Claude Opus 5
parent 66f2838402
commit bda23dbb67
6 changed files with 287 additions and 11 deletions
+15 -1
View File
@@ -270,7 +270,7 @@ Three prerequisites. One is done, two are not:
| # | Prerequisite | State |
|---|---|---|
| 1 | The Pterodactyl startup command must run the app from `current/`, and the server must be restarted on switch | **Panel change.** Cannot be made or verified from the repository |
| 2 | `documents/`, `logs/` and `.env` must sit beside the releases, not inside one. `DOCUMENTS_ROOT` points the document store at a fixed path (`app/storage.py`) | Mechanism ready, **not yet configured on the node** |
| 2 | `documents/`, `logs/` and `.env` must sit beside the releases, not inside one. `DOCUMENTS_ROOT` and `LOG_DIR` point the document store and the logs at fixed paths (`app/storage.py`) | Mechanism ready, **not yet configured on the node** |
| 3 | Contract paths must be relative to that root, or the first switch strands every contract ever uploaded | **Done.** New rows store a relative path; rows written earlier keep their absolute one and still resolve, so no data migration is needed |
Prerequisite 3 was a defect on its own, not just a blocker: paths were built
@@ -278,6 +278,20 @@ from `os.getcwd()`, so starting the server from a different directory would
have sent new contracts to a new tree and made the existing ones unreadable
— with the database still claiming they were there.
**The same defect was in two more places, and one of them mattered more.**
`logs/` and `backups/` were built from `os.getcwd()` too (OBS-006), and the
backup script kept its own copy of the document path — so it archived
`./documents` no matter what `DOCUMENTS_ROOT` said. Following prerequisite 2
was therefore enough, on its own, to make every contract backup empty; the
script prints `No documents directory…` and still exits 0, so a scheduled
task watching the exit code would have seen green indefinitely. All three
roots now come from `app/storage.py`, and the backup run prints the document
source it used.
**After setting `DOCUMENTS_ROOT` on the node, run the backup once by hand**
and check the `Document source:` line and the size of the resulting
`documents_backup_*.zip`.
## Security Checklist
- [ ] `.env` is not committed to repository