- Serveur Rust (server-rs/, axum + sqlx) : les 148 adresses de l'API, l'interface, les migrations de démarrage et les tâches de fond ; même comportement que Node (banc : 2027 cas, 0 écart hors écarts déclarés USERS-02, RAPPRO-21, R4, R5). - Node retiré : server/, dépendances serveur, image Docker sans Node (51 Mo), docker-compose à un seul service applicatif. - R4 : écritures d'un autre site refusées (Sec-Fetch-Site / Origin). - R5 : « aujourd'hui » et sauvegarde automatique à l'heure de Paris. - R6 : mainteneur dans .github/CODEOWNERS. - Menu latéral : Accueil puis Calendrier en tête. - Plan et état : docs/PLAN-MIGRATION-RUST.md. 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.