L'ancien serveur gardait les sessions en mémoire : la table sessions de production n'avait pas la forme attendue (sid, sess, expire) et la connexion échouait (« column "sid" does not exist »). Au démarrage, une telle table est renommée (sessions_ancienne_<date>, rien n'est supprimé), son index aussi, puis la bonne table est créée. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ke2qyS8rgacP3ap5iezDbM
Serveur LogiFlow (Rust)
Serveur unique de l'application : il sert l'API (src/router.rs) et l'interface construite par Vite (dist/public), applique les migrations au démarrage (src/startup.rs) et lance les tâches de fond (src/jobs.rs : sauvegarde automatique quotidienne, purge des caches, compte admin par défaut sur une base vide). Il a remplacé le serveur Node/Express, dont il reprend le comportement à l'identique (docs/PLAN-MIGRATION-RUST.md) : mêmes réponses, même cookie de session (connect.sid, table sessions), mêmes secrets chiffrés.
Lancer en local
npx vite build # interface dans dist/public
DATABASE_URL=postgres://… SESSION_SECRET=… cargo run --manifest-path server-rs/Cargo.toml
Puis ouvrir http://localhost:3000. Pour travailler sur l'interface : npm run dev:server et, à côté, npm run dev (Vite sur http://localhost:5173, qui relaie /api vers le port 3000).
| Variable | Rôle | Défaut |
|---|---|---|
PORT |
port d'écoute | 3000 |
DATABASE_URL |
base PostgreSQL | obligatoire |
STATIC_DIR |
interface construite par Vite | dist/public |
SESSION_SECRET |
signature du cookie de session | fallback-secret-key |
ENCRYPTION_KEY |
clé des secrets chiffrés en base (à défaut SESSION_SECRET) |
— |
BACKUP_DIR |
dossier des sauvegardes (pg_dump doit être installé) |
backups |
NODE_ENV |
renvoyé par /api/health |
production |
ALLOWED_ORIGINS |
origines acceptées en plus de l'hôte du serveur pour les requêtes d'écriture (https://a.fr,https://b.fr), voir src/origin.rs |
— |
RUST_LOG |
niveau des journaux (info, debug…) |
info |
Ne pas changer SESSION_SECRET ni ENCRYPTION_KEY d'une installation existante : les sessions ouvertes et les secrets déjà chiffrés (mot de passe SMTP, jeton NocoDB) deviendraient illisibles.
Vérifier
cargo fmt --check && cargo clippy --all-targets -- -D warnings && cargo test
Puis le banc de comparaison avec le serveur Node de référence (scripts/bench/README.md) : aucun écart attendu, hors écarts déclarés.
Organisation
src/router.rs: table des adresses de l'API.src/express_routes.rsretrouve l'adresse qu'Express aurait servie (casse, « / » final) ;src/static_files.rssert l'interface et la page 404 d'Express.src/modules/: un fichier par module de l'application ;src/services/: services partagés (NocoDB, vérification des factures, courriels, dates).- Socle : session et utilisateur (
auth.rs), droits (access.rs, matrice deshared/permissions.json), validation au format zod (zod.rs), accès aux tables (db.rs), formats JSON de Node (json.rs,js.rs), secrets chiffrés (crypto.rs), erreurs (error.rs). src/schema.rsest généré depuisshared/schema.ts: après un changement de schéma,DATABASE_URL=… npm run gen:rust-schema, et la migration correspondante danssrc/startup.rs.- Ajouter ou modifier une adresse :
PORTAGE.md(règles et outils du socle).
Maintenance (décision R6)
- Mainteneur et relecteur : @R0m1k3 (
.github/CODEOWNERS). Toute modification passe par une PR dont la CI est verte :cargo fmt,clippy -D warnings, tests, contrôle de type de l'interface et banc. - Dans les réglages GitHub du dépôt, protéger
main: relecture des CODEOWNERS et vérifications « Serveur Rust » obligatoires. - Dépendances :
cargo updatepuis banc complet, une fois par mois ; Rust stable, imagerust:1.97-alpinemontée en même temps. - Heure : « aujourd'hui » se calcule à Paris (
src/clock.rs, décision R5) ; ne jamais utiliserUtc::now().date_naive()pour une date du jour. - Écritures d'un autre site refusées (
src/origin.rs, décision R4) : un nouveau service qui appelle l'API depuis un navigateur sur une autre adresse se déclare dansALLOWED_ORIGINS.