---
name: project_export_restore
description: "Fonctionnalité export complet prod→dev — ZIP DB+assets, stockage serveur, restauration pending-restore, job 3h00"
metadata: 
  node_type: memory
  type: project
  originSessionId: 5cf6a868-7a3f-44e5-a0f8-0499f84b1afc
---

# Export / Restore prod → dev

Fonctionnalité permettant à un admin d'extraire l'état complet d'un environnement (DB + logos + icônes) et de le restaurer ailleurs.

## Fichiers concernés

- `backend/src/routes/admin.js` — routes export/restore
- `backend/src/jobs/autoExport.js` — job automatique 3h00
- `frontend/src/pages/admin/ExportSection.jsx` — UI complète
- `frontend/src/pages/admin/JobLogsSection.jsx` — KNOWN_JOBS inclut `auto_export`
- `backend/src/db/index.js` — bloc pending-restore au démarrage

## Routes backend (`/api/admin/`)

| Route | Rôle |
|---|---|
| `GET /export-full` | Génère un ZIP (VACUUM INTO + assets), sauvegarde sur disque, retourne au navigateur |
| `GET /exports` | Liste les exports stockés sur le serveur |
| `POST /exports/upload` | Upload d'un ZIP externe, validation manifest, sauvegarde |
| `GET /exports/:filename` | Téléchargement d'un export stocké |
| `DELETE /exports/:filename` | Suppression d'un export stocké |
| `POST /exports/:filename/restore` | Restauration : backup sécurité + assets + pending-restore + process.exit(0) |

## Mécanisme pending-restore

1. La route restore écrit `{DB_PATH}.pending-restore`
2. `process.exit(0)` → Docker redémarre le container
3. Au démarrage, `db/index.js` détecte le fichier `.pending-restore`, le copie vers `DB_PATH`, supprime les fichiers WAL/SHM, puis supprime le `.pending-restore`

## Stockage

- `DATA_DIR/exports/` — max 10 fichiers ZIP, auto-purge des plus anciens
- Les exports générés automatiquement et manuellement partagent le même dossier
- Les backups de sécurité pré-restore portent le préfixe `pre-restore-backup-`

## Job automatique

- `startAutoExportJob()` — planifié à 3h00 locale chaque jour (sans dérive)
- Tracé dans `job_logs` (job_name = `auto_export`)
- Démarré dans `server.js` aux côtés de `startAutoStatutJob()`

## Incident SQLITE_CORRUPT (2026-06-16)

Voir [[feedback_sqlite_vacuum_into]] — root cause : `db.backup()` produisait un fichier WAL-mode incomplet. Fix : `VACUUM INTO`. Le serveur a été récupéré manuellement via container temporaire node:20-alpine avec bind mount sur `/root/volumes/crowdlending/data`.
