diff --git a/TODO.md b/TODO.md
index edb6198..6240798 100644
--- a/TODO.md
+++ b/TODO.md
@@ -163,6 +163,9 @@
# Current tasks
+- [x] Add ZipArchive guard to legacy export-files.php
+- [x] Add composer install --no-dev step to deploy recipe + composer.json/composer.lock rsync (vendor/ excluded from rsync, de-librairisation requires Composer deps on server; composer.json lives in repo root, deploy only syncs app/)
+
- [x] Cleanup modal: list files that will be removed (not just counts)
- [x] Storage restructure: documents/ → {objet}/ (tfe/theses/frart)
- [x] Migration script: move files + update DB paths
diff --git a/app/public/admin/actions/export-files.php b/app/public/admin/actions/export-files.php
index b44cc9e..7ddad32 100644
--- a/app/public/admin/actions/export-files.php
+++ b/app/public/admin/actions/export-files.php
@@ -17,6 +17,12 @@ require_once APP_ROOT . '/src/Controllers/ExportController.php';
require_once APP_ROOT . '/src/AdminLogger.php';
require_once APP_ROOT . '/src/ErrorHandler.php';
+if (!class_exists('ZipArchive')) {
+ http_response_code(500);
+ header('Content-Type: text/html; charset=UTF-8');
+ exit('Module PHP zip non installé sur le serveur. Contactez l\'administrateur système (apt install php8.4-zip).');
+}
+
try {
$controller = ExportController::create();
diff --git a/justfile b/justfile
index 96af243..53cb433 100644
--- a/justfile
+++ b/justfile
@@ -75,6 +75,9 @@ deploy:
ssh -t xamxam "sudo bash /tmp/deploy-server.sh"
ssh xamxam "rm -f /tmp/deploy-server.sh /tmp/xamxam.conf"
ssh xamxam "mkdir -p /var/www/xamxam/var/{cache,logs,tmp}"
+ # Install/update Composer dependencies (vendor/ excluded from rsync above)
+ rsync -v composer.json composer.lock xamxam:/var/www/xamxam/
+ ssh xamxam "cd /var/www/xamxam && composer install --no-dev --no-interaction --optimize-autoloader"
# Run pending migrations (creates DB from schema if missing, idempotent)
rsync -v scripts/migrate.sh xamxam:/tmp/migrate.sh
ssh xamxam "cd /var/www/xamxam && REPO_ROOT=/var/www/xamxam bash /tmp/migrate.sh"