From 1b7a46e05f39efb33cbef0b538f90e9e47c2ae1c Mon Sep 17 00:00:00 2001 From: Manus Date: Thu, 3 Sep 2026 15:35:55 +0000 Subject: [PATCH] =?UTF-8?q?Checkpoint:=20Le=20garde-fou=20de=20stockage=20?= =?UTF-8?q?distingue=20d=C3=A9sormais=20les=20environnements=20:=20les=20s?= =?UTF-8?q?erveurs=20Santinova=20exigent=20explicitement=20REQUIRE=5FSTORA?= =?UTF-8?q?GE=5FVOLUME=3Dtrue=20et=20bloquent=20sans=20volume=20PDF=20mont?= =?UTF-8?q?=C3=A9,=20tandis=20que=20l=E2=80=99h=C3=A9bergement=20cloud=20c?= =?UTF-8?q?r=C3=A9e=20le=20r=C3=A9pertoire=20local=20n=C3=A9cessaire=20san?= =?UTF-8?q?s=20arr=C3=AAter=20le=20d=C3=A9marrage.=20Les=20tests,=20TypeSc?= =?UTF-8?q?ript,=20build=20et=20une=20sonde=20de=20d=C3=A9marrage=20cloud?= =?UTF-8?q?=20sont=20valid=C3=A9s.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yml | 2 ++ scripts/ensure-storage-volume.sh | 29 ++++++++++++++++++----------- server/deploymentRouting.test.ts | 9 +++++++++ todo.md | 5 +++++ 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index f3048bc..2c9b2b5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -42,6 +42,8 @@ services: UPLOAD_DIR: /app/uploads # Chemin unique utilisé par le serveur et vérifié au démarrage. STORAGE_BASE_PATH: /app/storage + # Le déploiement Santinova requiert le volume historique des PDF. + REQUIRE_STORAGE_VOLUME: "true" # Manus OAuth (optionnel en recette) VITE_APP_ID: ${VITE_APP_ID:-demat-facturation-recette} OAUTH_SERVER_URL: ${OAUTH_SERVER_URL:-} diff --git a/scripts/ensure-storage-volume.sh b/scripts/ensure-storage-volume.sh index c6c060f..bef1129 100644 --- a/scripts/ensure-storage-volume.sh +++ b/scripts/ensure-storage-volume.sh @@ -5,20 +5,27 @@ set -eu storage_path="${STORAGE_BASE_PATH:-/app/storage}" +require_storage_volume="${REQUIRE_STORAGE_VOLUME:-false}" -if [ ! -d "$storage_path" ]; then - echo "[StorageGuard] Répertoire de stockage absent : $storage_path" >&2 - exit 1 -fi +if [ "$require_storage_volume" = "true" ]; then + if [ ! -d "$storage_path" ]; then + echo "[StorageGuard] Répertoire de stockage absent : $storage_path" >&2 + exit 1 + fi -if ! awk -v expected="$storage_path" '$2 == expected { mounted = 1 } END { exit mounted ? 0 : 1 }' /proc/mounts; then - echo "[StorageGuard] Volume persistant non monté sur $storage_path ; démarrage annulé." >&2 - exit 1 -fi + if ! awk -v expected="$storage_path" '$2 == expected { mounted = 1 } END { exit mounted ? 0 : 1 }' /proc/mounts; then + echo "[StorageGuard] Volume persistant non monté sur $storage_path ; démarrage annulé." >&2 + exit 1 + fi -if [ ! -w "$storage_path" ]; then - echo "[StorageGuard] Volume persistant non inscriptible : $storage_path" >&2 - exit 1 + if [ ! -w "$storage_path" ]; then + echo "[StorageGuard] Volume persistant non inscriptible : $storage_path" >&2 + exit 1 + fi +else + # L’hébergement cloud n’expose pas de volume Docker local. Il utilise le + # stockage applicatif disponible à l’exécution et doit donc pouvoir démarrer. + mkdir -p "$storage_path" fi exec node dist/index.js diff --git a/server/deploymentRouting.test.ts b/server/deploymentRouting.test.ts index 2d94757..4482fb0 100644 --- a/server/deploymentRouting.test.ts +++ b/server/deploymentRouting.test.ts @@ -26,4 +26,13 @@ describe("routage et persistance de déploiement", () => { expect(guardScript).toContain("Volume persistant non monté"); expect(guardScript).toContain("/proc/mounts"); }); + + it("réserve le contrôle bloquant du volume aux environnements Santinova", () => { + const composeFile = readFileSync(join(process.cwd(), "docker-compose.yml"), "utf8"); + const guardScript = readFileSync(join(process.cwd(), "scripts", "ensure-storage-volume.sh"), "utf8"); + + expect(composeFile).toContain('REQUIRE_STORAGE_VOLUME: "true"'); + expect(guardScript).toContain('REQUIRE_STORAGE_VOLUME:-false'); + expect(guardScript).toContain('mkdir -p "$storage_path"'); + }); }); diff --git a/todo.md b/todo.md index c275c15..b8c1347 100644 --- a/todo.md +++ b/todo.md @@ -905,3 +905,8 @@ - [x] Auditer les montages de stockage et la chaîne de reconstruction en recette et production - [x] Ajouter un contrôle bloquant avant reconstruction et une vérification après démarrage du volume `/app/storage` - [x] Vérifier les garde-fous sur les deux environnements sans modifier les données + +## Correctif du démarrage cloud après garde-fou PDF +- [x] Adapter le garde-fou afin qu’il soit obligatoire uniquement avec `REQUIRE_STORAGE_VOLUME=true` +- [x] Conserver le contrôle strict du volume sur recette et production Santinova +- [x] Valider le démarrage du déploiement cloud sans volume local