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