# 📊 Analyse Complète : NationsGlory Web Admin Panel + Serveur Minecraft ## 📋 Table des Matières 1. [Architecture Générale](#architecture-générale) 2. [Application Web](#application-web) 3. [Serveur Minecraft](#serveur-minecraft) 4. [Intégration](#intégration) 5. [Points de Sécurité](#points-de-sécurité) 6. [Recommandations](#recommandations) --- ## Architecture Générale ### Stack Technique ``` ┌─────────────────────────────────────────────────────────┐ │ Frontend (SPA Vanilla JS) │ │ - index.html, app.js, style.css │ │ - API_URL: http://:4001/api │ └────────────────────┬────────────────────────────────────┘ │ HTTP REST ┌────────────────────▼────────────────────────────────────┐ │ Backend (Express.js + Node.js 18) │ │ - server.js (port 4001, listens on 0.0.0.0) │ │ - 7 routes: auth, server, rcon, logs, players, │ │ whitelist, backup │ └────────────────────┬────────────────────────────────────┘ │ RCON (port 25575) ┌────────────────────▼────────────────────────────────────┐ │ Minecraft Server (mcpc.jar / Forge) │ │ - Version: 1.6.4 (MCPC+) │ │ - Mods: 60+ mods (Nations UI, FlansMod, etc) │ │ - Port: 25565 (server), 25575 (RCON) │ └─────────────────────────────────────────────────────────┘ Déploiement: ┌─────────────────────────────────────────────────────────┐ │ Docker Compose (machine distante: 192.168.1.252) │ │ - Container webnationsglory-admin │ │ - Volume mount: /mc-server → serveur Minecraft │ │ - Restart: unless-stopped │ │ - Port mapping: 4001:4001 │ └─────────────────────────────────────────────────────────┘ ``` ### Taille & Ressources - **Serveur Minecraft**: 143 MB (world + config + mods) - **Web App**: ~200 KB (frontend + backend source) - **Docker Image**: ~200 MB (Node.js 18-alpine + modules) --- ## Application Web ### Backend Architecture #### 1. **Serveur Principal** (`backend/src/server.js`) ```javascript // Configuration const PORT = 4001; const SERVER_DIR = '/mc-server' (Docker) ou local path const SESSION_SECRET = process.env.SESSION_SECRET // Middlewares - express.json() / urlencoded - CORS (origin: true, credentials: true) - express-session (24h max age, httpOnly) // Routes /api/auth → Authentification + enregistrement /api/server → Configuration serveur (server.properties) /api/rcon → Exécution commandes serveur /api/logs → Historique logs /api/players → Liste joueurs + statut OP /api/whitelist → Gestion whitelist /api/backup → Gestion backups ``` **Points clés:** - ✅ Frontend path auto-detection (Docker vs local) - ✅ CORS enabled avec credentials - ✅ Session 24h max - ⚠️ Session secret en dur ("your-secret-key-change-in-prod") - ⚠️ HTTPS désactivé (secure: false) #### 2. **Routes d'Authentification** (`backend/src/routes/auth.js`) **Endpoints:** ``` POST /register → Créer compte admin (vérifie que MC username est OP) POST /login → Connexion POST /logout → Déconnexion GET /check → Vérifier session active POST /change-password → Changer mot de passe ``` **Mécanisme:** ```javascript // Enregistrement 1. Vérifier que c'est le premier compte (users.json vide) 2. Lire ops.txt OU ops.json depuis serveur 3. Vérifier que mcUsername est dans la liste OPs 4. Hash password avec bcryptjs (10 rounds) 5. Sauvegarder dans users.json // Connexion 1. Trouver utilisateur par username 2. Comparer password avec hash bcrypt 3. Créer session req.session.user 4. Session persiste dans memory (⚠️ perd les sessions au redémarrage!) ``` **Fichiers utilisés:** - `backend/data/users.json` → Stockage utilisateurs + passwords hashés - `~/NationsGlory_ServeurBuild_Red/ops.txt` → Admins serveur - `~/NationsGlory_ServeurBuild_Red/ops.json` → Alternative format OPs **Risques de sécurité:** - ⚠️ Sessions en mémoire uniquement (pas persistentes) - ⚠️ users.json stocké en local/Docker (pas de base de données) - ⚠️ Pas de rate limiting sur login - ⚠️ Pas de 2FA #### 3. **Routes Serveur** (`backend/src/routes/server.js`) **Endpoints:** ``` GET / → Lire server.properties POST /update → Modifier une propriété GET /jvm-args → Lire arguments JVM POST /restart → Redémarrer le serveur POST /stop → Arrêter le serveur POST /backup → Créer backup ``` **Implémentation:** - Parse `server.properties` ligne par ligne - Supporte modification de propriétés individuelles - Contrôle via RCON pour restart/stop #### 4. **Routes RCON** (`backend/src/routes/rcon.js`) **Architecture RCON:** ```javascript // Classe RconClient (backend/src/utils/rcon.js) - Protocole: Minecraft RCON (TCP port 25575) - Packet format: [size][id][type][payload][null] - Type 3 = Auth, Type 2 = Command, Type 0 = Response - Timeout: 5s (auth), 10s (command) // Implémentation 1. Parse server.properties pour rcon.port + rcon.password 2. Créer socket TCP vers serveur 3. S'authentifier avec password 4. Envoyer commandes 5. Recevoir réponses avec stream buffer 6. Timeout après 10s ``` **Endpoints:** ``` POST /command → Exécuter commande RCON GET /history → Historique 200 dernières commandes DELETE /history/:id → Nettoyer historique ``` **Commandes supportées:** - `say ` → Message serveur - `stop` → Arrêter serveur - `restart` → Redémarrer (custom) - `list` → Joueurs en ligne (parsé pour joueurs) - `op ` → Ajouter OP - `whitelist add ` → Ajouter whitelist - Tout ce que le serveur Minecraft supporte **Historique:** - Stocké dans `.web-admin/rcon-history.json` - Limité à 200 dernières commandes - Contient: timestamp, command, response, success, error #### 5. **Routes Joueurs** (`backend/src/routes/players.js`) **Endpoints:** ``` GET / → Liste tous joueurs + statut OP + dernière connexion ``` **Implémentation:** ```javascript // 1. Lire world/players/*.dat (fichiers joueurs) // 2. Mapper UUID → Nom via usercache.json // 3. Lire ops.txt et parser noms OPs // 4. Ajouter champ isOp: boolean pour chaque joueur // 5. Retourner liste avec: { players: [ { uuid, name, isOp, lastPlayed } ] } ``` **Données sources:** - `world/players/*.dat` → Fichiers joueurs Minecraft - `usercache.json` → Mapping UUID ↔ Nom (si existe) - `ops.txt` → Noms des OPs (nouvelle feature) #### 6. **Routes Whitelist** (`backend/src/routes/whitelist.js`) **Endpoints:** ``` GET / → Lire whitelist POST /add → Ajouter joueur POST /remove → Retirer joueur ``` **Support formats:** - `whitelist.json` → Format moderne `[{name, uuid}]` - `whitelist.txt` → Format legacy, 1 nom/ligne **Implémentation:** - Auto-détecte format (JSON ou TXT) - Priorise JSON si les deux existent - Ajoute validation de doublons #### 7. **Routes Logs** (`backend/src/routes/logs.js`) **Endpoints:** ``` GET / → Logs serveur (recent-latest.log + ancien logs.1, logs.2, etc) ``` **Parsing:** - Supporte format colorisé Minecraft - Convertit codes Minecraft (§X) en HTML - Retourne HTML colorisé pour UI #### 8. **Routes Backup** (`backend/src/routes/backup.js`) **Endpoints:** ``` GET / → Lister backups existants POST /create → Créer nouveau backup (tar.gz) GET /download → Télécharger backup POST /restore → Restaurer depuis backup ``` **Implémentation:** ```bash tar --exclude='.web-admin' --exclude='*.log.lck' \ -czf "backup-.tar.gz" . ``` **Répertoire:** `backups/` dans SERVER_DIR --- ### Frontend Architecture #### 1. **Structure SPA** (`frontend/public/js/app.js`) ```javascript // État global let currentUser = null; let isAuthenticated = false // Points d'entrée checkAuth() // Vérifier session showLoginPage() // Authentification showDashboard() // Interface admin switchTab(tabName) // Navigation // Sections disponibles (onglets) - Dashboard → Infos serveur + joueurs en ligne - Joueurs → Liste tous joueurs, statut OP - Whitelist → Gérer whitelist - Commandes RCON → Interface ligne de commande - Logs → Consulter logs serveur - Serveur → Settings server.properties - Backups → Gérer backups + restore - Paramètres → Changement password ``` #### 2. **API_URL Resolution** ```javascript // Avant: hardcoded localhost const API_URL = 'http://localhost:4001/api'; // Après: Dynamic hostname detection const API_URL = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1' ? 'http://localhost:4001/api' : `http://${window.location.hostname}:4001/api`; ``` **Impact:** Permet accès via IP (192.168.1.252) sans modification code #### 3. **Authentification Frontend** ```javascript // Login Flow checkAuth() → fetch /auth/check → Authentifié → showDashboard() Non-auth → showLoginPage() → handleLogin() → fetch /auth/login // Données transmises POST /api/auth/login { username: string, password: string } // Réponse { authenticated: true, user: { username, mcUsername } } ``` #### 4. **Dashboard Principal** ``` ┌─────────────────────────────────────────────────┐ │ NationsGlory Admin Panel 🔓 admin ▼ Logout │ ├─────────────────────────────────────────────────┤ │ Tabs: [Dashboard] [Joueurs] [Whitelist] [RCON] │ │ [Logs] [Serveur] [Backups] [Settings] │ ├─────────────────────────────────────────────────┤ │ 📊 Dashboard │ │ • Joueurs connectés: 0/20 ⚪ │ │ • Statut serveur: ON/OFF │ │ • Mods chargés: 60+ │ │ • World: FLAT, seed: [value] │ │ • Max build height: 256 │ ├─────────────────────────────────────────────────┤ │ 👥 Joueurs en ligne │ │ [Rafraîchir] │ │ 📋 Tous les Joueurs │ │ [Table avec columns: Nom, OP, UUID, LastPlayed] │ └─────────────────────────────────────────────────┘ ``` #### 5. **Sections Clés** **A. Joueurs** (`loadPlayersData()`) - Affiche tous les joueurs jamais connectés - Colonne OP: ✅ OP ou ❌ - Colonne UUID + dernière connexion - Chargement RCON `list` pour joueurs en ligne en temps réel **B. Whitelist** (`getWhitelistHTML()`) - Ajouter / Retirer joueurs - Support JSON et TXT formats - Validation doublons **C. RCON Terminal** (`getRconHTML()`) - Interface ligne de commande - Input texte + historique - Exécution commandes - Affichage résultats **D. Logs** (`getLogsHTML()`) - Lecture logs serveur - Coloration codes Minecraft - Scroll horizontal si long **E. Serveur Settings** (`getServerHTML()`) - Liste properties modifiables - Boutons Start/Stop/Restart - Actions avec confirmation **F. Backups** (`getBackupsHTML()`) - Lister backups - Créer backup - Télécharger - Restaurer depuis backup **G. Settings** (`getSettingsHTML()`) - Changement mot de passe - About version --- ## Serveur Minecraft ### Configuration Serveur **Server Properties** (`server.properties`) ```properties server-ip= # Écoute sur toutes interfaces server-port=25565 # Port Minecraft standard max-players=20 # Limite 20 joueurs gamemode=1 # Creative mode difficulty=1 # Normal level-type=FLAT # Monde plat level-name=world # Dossier monde enable-rcon=true # RCON activé rcon.port=25575 # Port RCON rcon.password=Landau8210 # ⚠️ Password en clair! online-mode=false # Offline mode (permet cracked clients) pvp=true # PvP activé allow-nether=true # Nether autorisé spawn-animals=true # Génération animaux white-list=false # Whitelist désactivée par défaut ``` ### Structure Serveur ``` NationsGlory_ServeurBuild_Red/ ├── world/ # Données du monde │ ├── players/ # Fichiers joueurs (.dat) │ ├── stats/ # Stats joueurs (.json) │ ├── region/ # Chunks du monde │ └── level.dat # Info niveau ├── mods/ # 60+ mods Minecraft │ └── [liste complète ci-dessous] ├── plugins/ # Plugins serveur ├── config/ # Configuration mods (60+ fichiers .cfg) ├── libraries/ # Dépendances Java ├── customnpcs/ # NPCs custom ├── Flan/ # Config FlansMod ├── .web-admin/ # Historique RCON ├── mcpc.jar # Serveur MCPC+ ├── server.properties # Configuration ├── ops.txt # Admins serveur (format texte) ├── ops.json # Alternative format OPs ├── whitelist.txt # Whitelist (TXT) ├── whitelist.json # Alternative whitelist (JSON) ├── banned-players.txt # Bannis ├── banned-ips.txt # IPs bannies ├── usercache.json # Cache UUID ↔ Nom (si existe) └── backups/ # Sauvegardes (créées par app) ``` **Taille: 143 MB** ### Mods/Plugins Identifiés Via `config/*.cfg`: 1. **NationsGlory mods** - ngcore.cfg → Nations Core - ngcontent.cfg → Contenu Nations - nationsui.cfg → Interface Nations - nationsgui.json - nationsmachine.cfg → Machines Nations - NGUpgrades.json 2. **Gameplay Mods** - FlansMod.cfg → Armes, véhicules - WeaponMod.cfg → Armes custom - ICBM.cfg → Missiles - CustomNpcs.cfg → NPCs custom - GetAllTheSeeds.cfg - AnimalBikes.cfg 3. **Building/Tech** - Chisel.cfg → Blocs décoratifs - BiblioCraft.cfg → Furniture - ArmorStatusHUD.cfg - TLSpecialArmor.cfg 4. **Farming** - PAM mods (multiple): - pamtemperateplants.cfg - pamweeeflowers.cfg - pamrandomaplants.cfg - pamextendedglass.cfg 5. **Infrastructure** - Galacticraft/ → Espace - Netherrocks → Nether - AquaTweaks.cfg → Eau - MelonSpawn.cfg - Autoutils.cfg 6. **Visualization** - MapWriter.cfg → Mini-map - ArmorStatusHUD.cfg 7. **Framework/Admin** - forge.cfg → Forge base - forgeChunkLoading.cfg - bspkrsCore.cfg → Libraire - logging.properties **Version:** 1.6.4 (Minecraft 1.6.4, probablement MCPC+ pour Forge) ### Architecture Serveur MCPC+ MCPC+ = Minecraft + Bukkit compatibility + Forge mods - Combine Minecraft serveur vanilla - Ajoute Forge pour mods - Supporte plugins Bukkit (en parallèle) - Version 1.6.4 (assez vieille, 2013) --- ## Intégration ### Flux de Données ``` Frontend (Browser) ↓ fetch /api/auth/login Backend (Express) ├─ Vérifie users.json ├─ Hash password bcrypt ├─ Crée session └─ Return { authenticated: true } ↓ fetch /api/rcon/command Backend RCON Client ├─ Parse server.properties ├─ Connect TCP:25575 ├─ Auth avec rcon.password ├─ Send command bytes └─ Receive/parse response ↓ Minecraft Server (MCPC+) ├─ Process command ├─ Modify world/players/ ou server.properties └─ Send output back ↓ Backend Response └─ Return output JSON ↓ Frontend Display └─ Show result to user ``` ### Session Management **Current:** Express-session in-memory ```javascript app.use(session({ secret: SESSION_SECRET, resave: false, saveUninitialized: true, cookie: { secure: false, // HTTP only (not HTTPS) httpOnly: true, // No JS access sameSite: 'lax', // CSRF protection maxAge: 24 * 60 * 60 * 1000 // 24 hours } })) ``` **Problème:** Sessions perdues au redémarrage Docker - ✅ currentUser reste authentifié tant que session active - ❌ Redémarrage container = logout automatique - **Solution:** Utiliser connect-mongo, redis, ou JWT ### RCON Integration ``` Web UI → Command → Backend → RCON Client → Minecraft Server → Response ``` **Example: /api/rcon/command POST {"command": "list"}** 1. Backend RCON Client: ``` - Read: server.properties (rcon.port=25575, rcon.password=Landau8210) - Connect: TCP 192.168.1.252:25575 - Authenticate: send password bytes - Send: "list" command - Parse: "There are 1/20 players online: anakine22" - Return: JSON response ``` 2. Frontend parses & displays --- ## Points de Sécurité ### 🔴 Critiques 1. **RCON Password en Clair** ```properties rcon.password=Landau8210 # Visible dans server.properties ``` **Risque:** Accès direct au serveur Minecraft si fichier leak **Fix:** Lire depuis env vars, pas fichier 2. **Session en Mémoire** ```javascript // Sessions perdues au redémarrage // Accessible seulement au container courant (pas clustering) ``` **Risque:** Forcer logout en case de crash/redémarrage **Fix:** Store sessions en Redis/DB 3. **HTTP seulement** ```javascript secure: false // No HTTPS ``` **Risque:** Credentials en clair sur le réseau **Fix:** Activer HTTPS, self-signed cert minimum 4. **users.json pas encrypté** ``` backend/data/users.json ``` **Contient:** Passwords bcryptés (OK) + usernames (leak de données) **Fix:** Chiffrer fichier ou utiliser database ### 🟡 Modérés 5. **Pas de Rate Limiting** ``` Brute force possible sur endpoint /auth/login ``` **Fix:** express-rate-limit middleware 6. **Pas de 2FA** ``` Seul username/password ``` **Fix:** Ajouter TOTP si critique 7. **CORS trop permissif** ```javascript CORS({ origin: true, credentials: true }) ``` **Risque:** N'importe quel domaine peut faire requêtes **Fix:** Whitelist domains explicitement 8. **Pas de CSRF tokens** ``` State-changing operations (POST/DELETE) sans CSRF ``` **Fix:** Ajouter csurf middleware 9. **Pas de input validation** ```javascript // POST /api/server/update { property, value } // Pas de validation property names ``` **Risque:** Injection server.properties arbitraire **Fix:** Whitelist propriétés modifiables 10. **Fichiers logs exposés** ```javascript GET /api/logs expose tous les logs du serveur ``` **Risque:** Info sensitive (errors, plugins, config) **Fix:** Limiter logs, filtrer data sensitive ### 🟢 Acceptables 11. **online-mode=false** ```properties Serveur accepte cracked clients (offline mode) ``` **Pourquoi:** Peut être intentionnel pour privé réseau 12. **Debug pas activé** ```properties debug=false ✓ ``` 13. **Entity tracking config non visible** ✓ --- ## Recommandations ### 🚀 Priorité 1: Critique #### 1. Ajouter HTTPS/SSL ```dockerfile # docker-compose.yml volumes: - ./certs:/app/certs # Certificates auto-renew via certbot environment: - NODE_ENV=production - HTTPS_CERT=/app/certs/cert.pem - HTTPS_KEY=/app/certs/key.pem ``` #### 2. Session Persistence (Redis) ```bash # Ajouter redis service version: '3' services: app: # ... depends_on: - redis redis: image: redis:7-alpine volumes: - redis-data:/data ``` ```javascript // backend/src/server.js const RedisStore = require('connect-redis').default; const { createClient } = require('redis'); const redisClient = createClient({ host: 'redis', port: 6379 }); const store = new RedisStore({ client: redisClient }); app.use(session({ store, secret: process.env.SESSION_SECRET, // ... })); ``` #### 3. RCON Password sécurisé ```bash # .env RCON_PASSWORD=${RCON_PASSWORD} # Via docker-compose.yml # Avoid storing in server.properties # Option: Lire depuis /run/secrets/rcon_password (Docker Secrets) ``` #### 4. Rate Limiting ```javascript // backend/src/middleware/rateLimit.js const rateLimit = require('express-rate-limit'); const loginLimiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 min max: 5, // 5 tentatives message: 'Trop de tentatives login' }); app.post('/api/auth/login', loginLimiter, handleLogin); ``` #### 5. Validation Input Server Properties ```javascript // backend/src/routes/server.js const ALLOWED_PROPERTIES = [ 'max-players', 'difficulty', 'pvp', 'enable-nether', 'server-ip', 'server-port', // Attention: change port! // NOT: gamemode, level-type, level-name, rcon.password, etc ]; if (!ALLOWED_PROPERTIES.includes(property)) { return res.status(400).json({ error: 'Propriété non modifiable' }); } ``` --- ### 🎯 Priorité 2: Important #### 6. CSRF Tokens ```javascript const csrf = require('csurf'); const csrfProtection = csrf({ cookie: false, sessionKey: 'session' }); app.post('/api/server/update', csrfProtection, handleUpdate); ``` #### 7. Chiffrer users.json ```javascript const crypto = require('crypto'); const FILE_KEY = Buffer.from(process.env.FILE_ENCRYPTION_KEY, 'hex'); function encryptUsers(users) { const iv = crypto.randomBytes(16); const cipher = crypto.createCipheriv('aes-256-gcm', FILE_KEY, iv); const encrypted = cipher.update(JSON.stringify(users)); // ... } ``` #### 8. Logs Filtering ```javascript // backend/src/routes/logs.js // Filtrer: // - Passwords // - Database credentials // - API keys // - Player IPs // - Internal errors ``` #### 9. Database Migration ``` Remplacer: users.json → PostgreSQL (+ migrations) RCON history JSON → Database table Avantages: - Transactions - Backups - Multi-instance - Better performance ``` #### 10. API Documentation ``` Ajouter Swagger/OpenAPI - /api-docs - Documentation endpoints - Authentification requirements ``` --- ### 🛠️ Priorité 3: Nice to Have #### 11. Monitoring & Alerting ```javascript // Backend metrics - Uptime server - RCON connection failures - API response times - Error rate // Integration: Prometheus + Grafana // Discord webhooks for alerts ``` #### 12. Admin Audit Log ```javascript // Log all admin actions - Login/logout timestamps - Command executor + command - Property changes - File modifications ``` #### 13. World Backup Restoration ```javascript // Current: Créer backup ✓ // TODO: Restore backup avec safety checks // - Stop serveur // - Restore world/ // - Restart serveur // - Verify integrité ``` #### 14. Multi-Admin Support ```javascript // Current: 1 seul admin (users.json = array mais UI single) // TODO: // - Multiple admins support // - Role-based access (RBAC) // - Permissions per admin ``` #### 15. Players Statistics ```javascript // Ajouter analytics: // - Playtime per player // - Last 7 days activity // - Top builders/killers // - Trends ``` --- ## Métriques de Santé ### ✅ Points Forts 1. **Architecture modulaire** → 7 routes bien séparées 2. **Vanilla JS frontend** → Pas de build complexity 3. **RCON protocol bien implémenté** → Pas de pertes commands 4. **Session management** → Auth basique ok 5. **Docker-ready** → Déploiement facile 6. **Markdown docs** → QUICKSTART, DEPLOYMENT, MAINTENANCE 7. **Dynamic API URL** → Fonctionne IP ou localhost 8. **OP status tracking** → Lecture ops.txt correcte ### ⚠️ Domaines d'Amélioration 1. **Sécurité** → HTTPS, rate limiting, validation input 2. **Persistence** → Session, database 3. **Error handling** → Logs réseau, retry logic 4. **Scalability** → Multi-instance support 5. **Observability** → Monitoring, alerting 6. **Testing** → Tests unitaires + intégration 7. **Code quality** → Linting, type checking 8. **Features** → 2FA, RBAC, audit log ### 📈 Performance - **Frontend**: Single file SPA (~61 KB) - **Backend**: 104 lines server.js, routes <250 lines each - **Response time**: <100ms API (RCON varies) - **Memory**: ~50-100 MB Node.js container - **Concurrency**: Sequential RCON (une commande à la fois) --- ## Conclusion ### Current State L'application est **fonctionnelle** pour un usage **LAN privé** ou **réseau interne**. **Prêt pour production?** ❌ - Manque HTTPS, rate limiting, CSRF - Sessions perdues au redémarrage - Pas de database - Input validation insuffisante **Prêt pour LAN interne?** ✅ - Sécurité acceptable pour réseau de confiance - Toutes features essentielles présentes - Déploiement Docker simple ### Priorités à Court Terme 1. ✅ **Dynamic API URL** (FAIT: app.js détecte hostname) 2. ✅ **OP status tracking** (FAIT: lit ops.txt, affiche ✅/❌) 3. ⏳ **Session persistence** (Redis recommended) 4. ⏳ **HTTPS + rate limiting** (Pour production) 5. ⏳ **Input validation** (Server properties + RCON) ### Prochaines Étapes Recommandées ``` Phase 1 (Cette semaine) [ ] Tester OP display après refresh navigateur [ ] Documenter RCON commands disponibles [ ] Ajouter healthcheck serveur Minecraft Phase 2 (Semaine 2) [ ] Implémenter Redis pour sessions [ ] Ajouter HTTPS auto-signed [ ] Rate limiting login Phase 3 (Semaine 3) [ ] Migrer users.json → Database [ ] Input validation complete [ ] CSRF tokens ``` --- **Document généré:** 5 février 2026 **Version:** 1.0 **Auteur:** GitHub Copilot