# 🔍 AUDIT EXHAUSTIF - VEZA CHAT SERVER
## Module: `veza-chat-server` (Rust)

**Date**: 2025-01-27  
**Auditeur**: Auto (Cursor AI)  
**Version analysée**: 0.2.0  
**Statut compilation**: ❌ **ÉCHEC** (conflit de dépendances SQLx)

---

# PHASE A — CARTOGRAPHIE DU MODULE

## 1. But du module

**Rôle**: Serveur de chat temps réel avec WebSocket pour la plateforme Veza.

**Fonctionnalités principales**:
- Communication WebSocket bidirectionnelle (Axum + tokio-tungstenite)
- Gestion de conversations (directes, groupes, channels)
- Messages avec édition/suppression
- Read receipts et delivered status
- Typing indicators
- Recherche et synchronisation d'historique
- Authentification JWT avec refresh tokens
- Permissions RBAC (admin, moderator, member)
- Event Bus RabbitMQ (optionnel)
- Métriques Prometheus

## 2. Entrées / Sorties

### APIs exposées

**HTTP REST** (port 8081 par défaut):
- `GET /health` - Health check
- `GET /healthz` - Health check (alias)
- `GET /readyz` - Readiness check (DB + RabbitMQ)
- `GET /metrics` - Métriques Prometheus
- `GET /api/messages/stats` - Statistiques serveur
- `GET /api/messages/{conversation_id}` - Récupération messages (authentifié)
- `POST /api/messages` - Envoi message (authentifié)

**WebSocket** (port 8081):
- `GET /ws?token=<JWT>` - Connexion WebSocket

**Formats**:
- JSON pour HTTP REST
- JSON pour WebSocket (messages structurés)
- Protobuf pour gRPC (présent mais non utilisé dans main.rs)

### Events WebSocket

**Incoming** (`IncomingMessage`):
- `SendMessage`, `JoinConversation`, `LeaveConversation`
- `MarkAsRead`, `Typing`, `Delivered`
- `EditMessage`, `DeleteMessage`
- `FetchHistory`, `SearchMessages`, `SyncMessages`
- `Ping`

**Outgoing** (`OutgoingMessage`):
- `NewMessage`, `MessageRead`, `MessageDelivered`
- `UserTyping`, `MessageEdited`, `MessageDeleted`
- `HistoryChunk`, `SearchResults`, `SyncChunk`
- `ActionConfirmed`, `Error`, `Pong`

## 3. Dépendances internes

- `veza-common` (path: `../veza-common`) - Types partagés
- Modules internes: `config`, `database`, `error`, `jwt_manager`, `repository`, `security`, `services`, `websocket`

## 4. Dépendances externes

**Base de données**:
- PostgreSQL (via SQLx 0.8.6)
- Migrations SQL dans `migrations/`

**Cache** (optionnel):
- Redis (via `redis` crate, feature `redis-cache`)

**Message Broker** (optionnel):
- RabbitMQ (via `lapin` 2.3)

**Monitoring**:
- Prometheus (via `metrics-exporter-prometheus`)

## 5. Exécution

### Build
```bash
cargo build --release
```

### Run
```bash
./target/release/chat-server
```

### Variables d'environnement critiques
- `DATABASE_URL` (requis) - PostgreSQL connection string
- `JWT_SECRET` (requis, min 32 chars) - Secret pour JWT
- `CHAT_SERVER_PORT` (défaut: 8081)
- `CHAT_SERVER_HOST` (défaut: 0.0.0.0)
- `RABBITMQ_URL` (optionnel)
- `RABBITMQ_ENABLE` (défaut: true)

### Docker
- `Dockerfile` présent (multi-stage, Alpine)
- `docker-compose.yml` présent
- Healthcheck configuré (`/health`)

## 6. Points d'intégration

**Backend Go**:
- JWT tokens partagés (audience: `veza-chat`, issuer: `veza-backend`)
- Schéma DB partagé (UUID pour users, conversations, messages)

**Frontend React**:
- WebSocket: `ws://<host>:8081/ws?token=<JWT>`
- REST API: `http://<host>:8081/api/*`
- Headers: `Authorization: Bearer <JWT>`

**Auth**:
- JWT HS256 (configurable)
- Claims: `sub` (user_id UUID), `username`, `role`, `aud`, `iss`, `exp`, `iat`, `jti`

---

# PHASE B — SANTÉ TECHNIQUE

## Build Status

### ❌ **P0 - BUILD CASSÉ**

**Erreur**: Conflit de dépendances SQLx

```
error: failed to select a version for `libsqlite3-sys`.
package `libsqlite3-sys v0.30.1` (sqlx 0.8.6)
conflicts with `libsqlite3-sys v0.26.0` (sqlx 0.7.0 via veza-common)
```

**Fichiers concernés**:
- `Cargo.toml` ligne 43: `sqlx = "0.8.6"`
- `veza-common` (externe): `sqlx = "^0.7"`

**Impact**: **Impossible de compiler le projet**

**Fix minimal**: Aligner les versions SQLx entre `chat_server` et `veza-common`, ou exclure SQLite de `veza-common` si non utilisé.

## Tests

### Couverture
- Tests unitaires présents dans plusieurs modules
- Tests d'intégration avec `#[ignore]` (nécessitent DB)
- Tests JWT présents (`jwt_manager.rs`)
- Tests permissions partiels

### Problèmes détectés
- Beaucoup de tests ignorés (`#[ignore]`) car nécessitent DB
- Pas de tests E2E WebSocket
- Tests de sécurité manquants (injection, rate limiting)

## Gestion des erreurs

### ✅ Points positifs
- Type `ChatError` exhaustif avec `thiserror`
- Helpers pour création d'erreurs (`ChatError::not_found`, etc.)
- Mapping HTTP status codes approprié
- Logging structuré avec `tracing`

### ⚠️ Points d'attention
- **169 occurrences de `unwrap()` / `expect()` / `panic!`** détectées
- Certains `unwrap()` dans code de production (ex: `src/config.rs:21`, `src/main.rs:489`)
- Panics possibles dans `SecurityConfig::default()` (ligne 192) si appelé hors test

## Linters / Qualité

### Clippy
- Non exécuté dans l'audit (nécessite build)
- Recommandation: `cargo clippy --all-targets --all-features -- -D warnings`

### Conventions
- ✅ Structure modulaire claire
- ✅ Documentation rustdoc présente
- ⚠️ Mix de noms français/anglais (ex: `conversation_id` vs `room_id`)
- ⚠️ Code mort potentiel (`security_legacy.rs`, `simple_message_store.rs`)

---

# PHASE C — SÉCURITÉ

## Top 10 Risques Critiques

### **P0-001: Conflit de dépendances SQLx (Build cassé)**
- **Impact**: Impossible de déployer
- **Fichier**: `Cargo.toml:43` vs `veza-common`
- **Fix**: Aligner versions ou exclure SQLite
- **Effort**: S (1h)

### **P0-002: JWT Secret faible par défaut**
- **Impact**: Tokens compromis si secret faible
- **Fichier**: `src/main.rs:158`, `env.example:20`
- **Preuve**: `JWT_SECRET=your-super-secret-jwt-key-change-this-in-production`
- **Fix**: Validation stricte min 64 chars, génération aléatoire au démarrage si absent
- **Effort**: S (30min)

### **P0-003: Panics dans code de production**
- **Impact**: Crash serveur
- **Fichiers**: 
  - `src/main.rs:489` - `expect("failed to install Ctrl+C handler")`
  - `src/config.rs:192` - `panic!` dans `SecurityConfig::default()`
  - `src/env.rs:30,61` - `panic!` dans helpers
- **Fix**: Remplacer par `Result` et gestion d'erreurs
- **Effort**: M (2h)

### **P0-004: Validation JWT incomplète**
- **Impact**: Tokens expirés ou invalides acceptés
- **Fichier**: `src/jwt_manager.rs:266-303`
- **Preuve**: Vérification `exp` manuelle après décodage (ligne 290-293), mais pas de vérification `nbf` (not before)
- **Fix**: Ajouter validation `nbf`, vérifier `iss`/`aud` strictement
- **Effort**: S (1h)

### **P1-005: SQL Injection potentielle dans recherche**
- **Impact**: Exécution de requêtes SQL arbitraires
- **Fichier**: `src/repository/message_repository.rs:563`
- **Preuve**: `format!("%{}%", query)` - si `query` contient `%` ou `_`, comportement inattendu
- **Fix**: Échapper caractères spéciaux ou utiliser `ILIKE` avec paramètre bindé
- **Effort**: S (30min)

### **P1-006: Rate limiting non implémenté**
- **Impact**: DoS possible, spam
- **Fichier**: `src/security/mod.rs:94` - TODO comment
- **Preuve**: `// TODO: Implémenter le Rate Limiting réel via Redis ou mémoire partagée`
- **Fix**: Implémenter rate limiter avec Redis ou in-memory (DashMap)
- **Effort**: M (4h)

### **P1-007: CORS non configuré**
- **Impact**: XSS via requêtes cross-origin
- **Fichier**: `src/main.rs` - Pas de middleware CORS
- **Preuve**: Aucune configuration CORS dans Axum router
- **Fix**: Ajouter middleware CORS avec origines whitelistées
- **Effort**: S (1h)

### **P1-008: Secrets dans logs**
- **Impact**: Fuite de secrets en production
- **Fichier**: `src/config.rs:55` - Logging de `database_url` potentiellement
- **Preuve**: `info!("Initializing database connection pool with config: {:?}", config)` - peut logger credentials
- **Fix**: Masquer credentials dans logs (remplacer par `***`)
- **Effort**: S (30min)

### **P1-009: WebSocket sans rate limiting**
- **Impact**: Spam de messages, DoS
- **Fichier**: `src/websocket/handler.rs:200-894`
- **Preuve**: Aucune limite sur fréquence de messages WebSocket
- **Fix**: Ajouter rate limiter par client (ex: max 100 messages/sec)
- **Effort**: M (3h)

### **P1-010: Blacklist JWT en mémoire (non persistant)**
- **Impact**: Tokens révoqués revalidés après redémarrage
- **Fichier**: `src/jwt_manager.rs:142`
- **Preuve**: `revoked_tokens: Arc<RwLock<HashSet<String>>>` - perdu au redémarrage
- **Fix**: Persister blacklist dans Redis ou DB
- **Effort**: M (2h)

## Autres Risques (P2/P3)

### P2-011: Validation de contenu basique
- **Fichier**: `src/security_legacy.rs` - Regex patterns, mais module "legacy"
- **Fix**: Utiliser `ammonia` (déjà dans deps) pour sanitization HTML

### P2-012: Pas de protection CSRF pour REST API
- **Fichier**: `src/security/csrf.rs` existe mais non utilisé dans `main.rs`
- **Fix**: Activer middleware CSRF pour routes POST/PUT/DELETE

### P2-013: Heartbeat WebSocket fixe (60s)
- **Fichier**: `src/websocket/handler.rs:121`
- **Preuve**: `keepalive_timeout = Duration::from_secs(60)` - hardcodé
- **Fix**: Configurable via env var

### P2-014: Pas de validation de taille de message
- **Fichier**: `src/websocket/handler.rs:214` - Pas de check `content.len()`
- **Fix**: Valider `MAX_MESSAGE_LENGTH` (défini dans `env.example:57` mais non utilisé)

### P3-015: Logs verbeux en production
- **Fichier**: `src/main.rs:84-101` - Logs avec `debug`/`info` même en prod
- **Fix**: Utiliser `RUST_LOG` avec niveaux appropriés

---

# PHASE D — ROBUSTESSE & OBSERVABILITÉ

## Logs structurés

### ✅ Points positifs
- `tracing` avec `tracing-subscriber` configuré
- Format JSON en production (`main.rs:92`)
- Format détaillé en dev (`main.rs:95-100`)
- Champs structurés (`user_id = %user_id`, `conversation_id = %conversation_id`)

### ⚠️ Gaps
- **Pas de `request_id` / `trace_id`** pour corrélation
- **Pas de log rotation** configuré (mentionné dans `env.example:83` mais non implémenté)
- **Secrets potentiellement loggés** (voir P1-008)

## Métriques

### ✅ Présent
- Prometheus exporter (`/metrics`)
- `ChatMetrics` avec compteurs/gauges
- Métriques système (CPU, mémoire) via `sysinfo`

### ⚠️ Manquants
- **Latence P50/P95/P99** pour requêtes DB
- **Taux d'erreur par endpoint**
- **Connexions WebSocket actives** (compteur)
- **Taille de la blacklist JWT**

## Healthchecks

### ✅ Présent
- `/health` - Basic health check
- `/readyz` - Readiness (DB + RabbitMQ)

### ⚠️ Améliorations
- **Liveness check** séparé (actuellement `/health` fait DB check aussi)
- **Timeout configurable** pour healthchecks
- **Circuit breaker** pour DB/RabbitMQ

## Timeouts & Retries

### ✅ Présent
- Timeout WebSocket inactivité (60s)
- Retry RabbitMQ (`max_retries`, `retry_interval_secs`)

### ⚠️ Manquants
- **Timeout pour requêtes DB** (seulement `acquire_timeout` dans pool)
- **Retry avec backoff exponentiel** pour DB
- **Circuit breaker** pour services externes

## Gestion de charge

### ✅ Présent
- Pool DB configuré (max 20, min 5)
- Limite messages (100 max dans `fetch_history`)

### ⚠️ Gaps
- **Pas de backpressure** pour WebSocket (clients peuvent spam)
- **Pas de limite de connexions WebSocket simultanées**
- **Pas de queue pour messages en attente**

## Migrations

### ✅ Présent
- Migrations SQL dans `migrations/`
- SQLx migrate supporté

### ⚠️ Problèmes
- **16 fichiers de migration** - risque de confusion
- **Migrations archivées** dans `migrations/archive/` - à nettoyer
- **Pas de rollback** automatique en cas d'échec

---

# PHASE E — PERFORMANCE & SCALABILITÉ

## Hotspots identifiés

### 1. Broadcast WebSocket inefficace
**Fichier**: `src/websocket/mod.rs:228-244`
**Problème**: Itération sur tous les clients pour chaque broadcast
```rust
for client in clients.iter() {
    let conversations = client.conversations.read().await;
    if conversations.contains(&conversation_id) {
        let _ = client.send_message(message.clone()).await;
    }
}
```
**Impact**: O(n) où n = nombre total de clients, même si seulement quelques-uns sont dans la conversation
**Fix**: Index inversé `conversation_id -> Vec<client_id>` pour O(1) lookup
**Effort**: M (3h)

### 2. Clonage de messages pour broadcast
**Fichier**: `src/websocket/mod.rs:239`
**Problème**: `message.clone()` pour chaque client
**Impact**: Allocations inutiles pour gros messages
**Fix**: Utiliser `Arc<OutgoingMessage>` ou sérialiser une fois, cloner bytes
**Effort**: S (1h)

### 3. Requêtes DB N+1 potentielles
**Fichier**: `src/repository/message_repository.rs:82-144`
**Problème**: Pas de batch loading pour conversations multiples
**Impact**: Latence élevée si plusieurs conversations chargées
**Fix**: Ajouter méthode `get_multiple_conversations_messages`
**Effort**: M (2h)

### 4. Blacklist JWT en mémoire (HashSet)
**Fichier**: `src/jwt_manager.rs:142`
**Problème**: `HashSet<String>` - recherche O(1) mais mémoire illimitée
**Impact**: Fuite mémoire si beaucoup de tokens révoqués
**Fix**: LRU cache ou TTL-based cleanup (déjà partiellement implémenté ligne 473)
**Effort**: S (1h)

### 5. Parsing JSON répété
**Fichier**: `src/websocket/handler.rs:210`
**Problème**: `serde_json::from_str(text)` à chaque message
**Impact**: CPU overhead pour gros payloads
**Fix**: Cache de schémas JSON ou validation pré-compilée
**Effort**: P3 (optimisation future)

## Streaming & I/O

### WebSocket
- ✅ Utilisation de `tokio-tungstenite` (async)
- ⚠️ Pas de compression WebSocket (per-message deflate)
- ⚠️ Pas de fragmentation pour gros messages

### Base de données
- ✅ Pool de connexions configuré
- ⚠️ Pas de prepared statements caching explicite (SQLx le fait mais non configuré)
- ⚠️ Pas de connection pooling metrics exposées

## Async Runtime

### ✅ Points positifs
- Tokio avec features "full"
- Pas de blocking dans async (sauf `sysinfo` potentiellement)

### ⚠️ Points d'attention
- **Pas de configuration de worker threads** (utilise par défaut)
- **Pas de metrics Tokio** (task spawns, park/unpark)

---

# PHASE F — LISTE EXHAUSTIVE DES PROBLÈMES

## P0 - CRITIQUES (Build / Sécurité / Crash)

| ID | Titre | Impact | Fichier | Fix minimal | Validation | Effort |
|---|---|---|---|---|---|---|
| **MOD-P0-001** | Conflit dépendances SQLx (build cassé) | Impossible de compiler | `Cargo.toml:43` | Aligner versions SQLx (0.8.6 partout) ou exclure SQLite de veza-common | `cargo check` passe | S (1h) |
| **MOD-P0-002** | JWT Secret faible par défaut | Tokens compromis | `src/main.rs:158`, `env.example:20` | Validation min 64 chars, génération aléatoire si absent | Test: secret < 64 chars rejeté | S (30min) |
| **MOD-P0-003** | Panics dans code production | Crash serveur | `src/main.rs:489`, `src/config.rs:192`, `src/env.rs:30,61` | Remplacer `expect/panic` par `Result` | Tests: pas de panic sur erreurs attendues | M (2h) |
| **MOD-P0-004** | Validation JWT incomplète | Tokens invalides acceptés | `src/jwt_manager.rs:266-303` | Ajouter validation `nbf`, vérifier `iss/aud` strictement | Test: token avec `nbf` futur rejeté | S (1h) |

## P1 - HAUTE PRIORITÉ (Bugs fréquents / Dette bloquante)

| ID | Titre | Impact | Fichier | Fix minimal | Validation | Effort |
|---|---|---|---|---|---|---|
| **MOD-P1-005** | SQL Injection potentielle recherche | Exécution SQL arbitraire | `src/repository/message_repository.rs:563` | Échapper `%` et `_` ou utiliser paramètre bindé | Test: query avec `%` ne match pas littéralement | S (30min) |
| **MOD-P1-006** | Rate limiting non implémenté | DoS, spam | `src/security/mod.rs:94` | Implémenter avec Redis ou DashMap | Test: 1000 req/sec rejetées | M (4h) |
| **MOD-P1-007** | CORS non configuré | XSS cross-origin | `src/main.rs:246` | Ajouter middleware CORS Axum | Test: requête cross-origin rejetée sans header | S (1h) |
| **MOD-P1-008** | Secrets dans logs | Fuite credentials | `src/config.rs:264` | Masquer credentials (remplacer par `***`) | Test: logs ne contiennent pas `password=` | S (30min) |
| **MOD-P1-009** | WebSocket sans rate limiting | Spam messages, DoS | `src/websocket/handler.rs:200` | Rate limiter par client (100 msg/sec) | Test: client spammant rejeté | M (3h) |
| **MOD-P1-010** | Blacklist JWT non persistant | Tokens révoqués revalidés | `src/jwt_manager.rs:142` | Persister dans Redis ou DB | Test: token révoqué reste révoqué après restart | M (2h) |
| **MOD-P1-011** | Pas de validation taille message | Messages trop longs | `src/websocket/handler.rs:214` | Valider `MAX_MESSAGE_LENGTH` (2000 chars) | Test: message > 2000 chars rejeté | S (30min) |
| **MOD-P1-012** | Broadcast WebSocket O(n) | Performance dégradée | `src/websocket/mod.rs:228` | Index inversé conversation -> clients | Test: broadcast à 1000 clients < 10ms | M (3h) |
| **MOD-P1-013** | Pas de limite connexions WS | DoS par connexions | `src/websocket/manager.rs:209` | Limiter max connexions (ex: 10000) | Test: 10001ème connexion rejetée | S (1h) |
| **MOD-P1-014** | Healthcheck timeout non configuré | Healthcheck bloque | `src/main.rs:298` | Timeout configurable (ex: 5s) | Test: DB lent retourne 503 | S (30min) |

## P2 - MOYENNE PRIORITÉ (Qualité / Maintenabilité)

| ID | Titre | Impact | Fichier | Fix minimal | Validation | Effort |
|---|---|---|---|---|---|---|
| **MOD-P2-015** | Pas de request_id/trace_id | Debug difficile | `src/main.rs:82` | Ajouter middleware tracing avec `request_id` | Test: logs contiennent `request_id` | M (2h) |
| **MOD-P2-016** | Log rotation non implémenté | Disque plein | `env.example:83` | Implémenter avec `tracing-appender` | Test: logs rotent après 100MB | M (2h) |
| **MOD-P2-017** | Métriques latence manquantes | Monitoring incomplet | `src/monitoring.rs` | Ajouter histogrammes P50/P95/P99 | Test: métriques exposées sur `/metrics` | M (2h) |
| **MOD-P2-018** | Circuit breaker manquant | Cascading failures | N/A | Implémenter avec `tower` ou custom | Test: DB down -> circuit ouvert | M (4h) |
| **MOD-P2-019** | Migrations multiples confuses | Risque d'erreur | `migrations/` (16 fichiers) | Nettoyer migrations archivées | Test: migrations appliquent dans ordre | S (1h) |
| **MOD-P2-020** | Code mort (security_legacy) | Maintenance inutile | `src/security_legacy.rs` | Supprimer ou documenter usage | Test: build sans ce fichier | S (30min) |
| **MOD-P2-021** | CSRF non activé | CSRF attacks | `src/security/csrf.rs` | Activer middleware CSRF | Test: requête sans token CSRF rejetée | M (2h) |
| **MOD-P2-022** | Heartbeat WebSocket hardcodé | Non configurable | `src/websocket/handler.rs:121` | Configurable via env var | Test: heartbeat = 30s fonctionne | S (30min) |
| **MOD-P2-023** | Clonage messages broadcast | Allocations inutiles | `src/websocket/mod.rs:239` | Utiliser `Arc<OutgoingMessage>` | Test: broadcast 100 clients < 5ms | S (1h) |
| **MOD-P2-024** | Requêtes N+1 potentielles | Latence élevée | `src/repository/message_repository.rs` | Batch loading conversations | Test: 10 conversations < 100ms | M (2h) |

## P3 - BASSE PRIORITÉ (Cosmétique / Refactors)

| ID | Titre | Impact | Fichier | Fix minimal | Validation | Effort |
|---|---|---|---|---|---|---|
| **MOD-P3-025** | Mix français/anglais | Confusion | Multiple | Standardiser sur anglais | Review code | L (8h) |
| **MOD-P3-026** | Logs verbeux en production | Bruit | `src/main.rs:84` | Utiliser `RUST_LOG` approprié | Test: prod logs = info seulement | S (30min) |
| **MOD-P3-027** | Pas de compression WebSocket | Bande passante | `src/websocket/handler.rs:47` | Activer per-message deflate | Test: messages compressés | M (2h) |
| **MOD-P3-028** | Tests ignorés nombreux | Couverture faible | Multiple `#[ignore]` | Setup DB de test ou mocks | Test: tous tests passent | L (8h) |
| **MOD-P3-029** | Documentation rustdoc incomplète | DX | Multiple | Compléter doc comments | Test: `cargo doc` sans warnings | M (4h) |
| **MOD-P3-030** | Pas de benchmarks | Performance non mesurée | N/A | Ajouter `criterion` benchmarks | Test: benchmarks passent | M (4h) |

---

# PHASE G — PLAN D'EXÉCUTION

## Checklist P0 (Ordre strict)

1. ✅ **MOD-P0-001**: Fix conflit SQLx
   - Modifier `veza-common/Cargo.toml` pour utiliser `sqlx = "0.8.6"` OU exclure SQLite
   - Vérifier: `cargo check` passe
   - **PR**: `fix: align sqlx versions to 0.8.6`

2. ✅ **MOD-P0-002**: Validation JWT Secret
   - Modifier `src/env.rs` pour valider min 64 chars
   - Générer secret aléatoire si absent (dev seulement)
   - **PR**: `security: enforce strong JWT secret (min 64 chars)`

3. ✅ **MOD-P0-003**: Remplacer panics
   - `src/main.rs:489` -> `Result` pour signal handlers
   - `src/config.rs:192` -> Supprimer `panic!` ou rendre test-only
   - `src/env.rs:30,61` -> Retourner `Result` au lieu de `panic!`
   - **PR**: `fix: replace panics with Result types`

4. ✅ **MOD-P0-004**: Validation JWT complète
   - Ajouter validation `nbf` dans `validate_access_token`
   - Vérifier `iss`/`aud` strictement (déjà fait partiellement)
   - **PR**: `security: add nbf validation to JWT tokens`

## Checklist P1 (Par lots)

### Lot 1: Sécurité WebSocket (1 sprint)
- **MOD-P1-009**: Rate limiting WebSocket
- **MOD-P1-011**: Validation taille message
- **MOD-P1-013**: Limite connexions WS
- **PR**: `security: add rate limiting and validation for WebSocket`

### Lot 2: Sécurité REST (1 sprint)
- **MOD-P1-006**: Rate limiting REST
- **MOD-P1-007**: CORS middleware
- **MOD-P1-008**: Masquer secrets dans logs
- **PR**: `security: add rate limiting, CORS, and secure logging`

### Lot 3: Persistance & Robustesse (1 sprint)
- **MOD-P1-010**: Blacklist JWT persistant
- **MOD-P1-014**: Healthcheck timeout
- **MOD-P2-015**: Request ID tracing
- **PR**: `feat: persistent JWT blacklist, configurable healthcheck, request tracing`

### Lot 4: Performance WebSocket (1 sprint)
- **MOD-P1-012**: Index inversé broadcast
- **MOD-P2-023**: Arc pour messages
- **PR**: `perf: optimize WebSocket broadcast with index and Arc`

### Lot 5: Base de données (1 sprint)
- **MOD-P1-005**: Fix SQL injection recherche
- **MOD-P2-024**: Batch loading conversations
- **PR**: `fix: SQL injection in search, add batch loading`

## Quick Wins (≤ 1h chacun)

1. **MOD-P2-022**: Heartbeat configurable (30min)
2. **MOD-P2-020**: Supprimer code mort (30min)
3. **MOD-P3-026**: Logs production (30min)
4. **MOD-P2-019**: Nettoyer migrations (1h)

## Tests à ajouter en priorité

### Tests de sécurité
- [ ] Test: JWT secret < 64 chars rejeté
- [ ] Test: Token avec `nbf` futur rejeté
- [ ] Test: Recherche avec `%` ne match pas littéralement
- [ ] Test: Rate limiting (1000 req/sec rejetées)
- [ ] Test: CORS sans header rejeté
- [ ] Test: Message > 2000 chars rejeté

### Tests de robustesse
- [ ] Test: DB down -> healthcheck 503
- [ ] Test: Token révoqué reste révoqué après restart
- [ ] Test: Broadcast 1000 clients < 10ms
- [ ] Test: 10001ème connexion WS rejetée

### Tests E2E
- [ ] Test: Connexion WebSocket complète (join, send, leave)
- [ ] Test: Édition/suppression message
- [ ] Test: Read receipts et delivered status
- [ ] Test: Recherche et synchronisation

## PR Plan (Découpe proposée)

1. **`fix: resolve sqlx dependency conflict`** (P0-001)
2. **`security: enforce strong JWT secret and validation`** (P0-002, P0-004)
3. **`fix: replace panics with Result types`** (P0-003)
4. **`security: add rate limiting and validation for WebSocket`** (P1-009, P1-011, P1-013)
5. **`security: add rate limiting, CORS, and secure logging`** (P1-006, P1-007, P1-008)
6. **`feat: persistent JWT blacklist and request tracing`** (P1-010, P1-014, P2-015)
7. **`perf: optimize WebSocket broadcast`** (P1-012, P2-023)
8. **`fix: SQL injection and batch loading`** (P1-005, P2-024)
9. **`chore: cleanup migrations and dead code`** (P2-019, P2-020)
10. **`feat: add observability improvements`** (P2-016, P2-017, P2-018)

---

# RÉSUMÉ EXÉCUTIF

## Statut global: 🔴 **NON PRODUCTION-READY**

### Bloqueurs (P0): 4
- Build cassé (conflit SQLx)
- Sécurité JWT faible
- Panics en production
- Validation JWT incomplète

### Critiques (P1): 10
- SQL injection potentielle
- Rate limiting manquant
- CORS non configuré
- Secrets dans logs
- Performance WebSocket

### Améliorations (P2): 10
- Observabilité incomplète
- Robustesse (circuit breakers, timeouts)
- Code mort

### Cosmétiques (P3): 6
- Documentation
- Tests
- Refactors

## Estimation totale

- **P0**: 4.5h (1 sprint)
- **P1**: 20h (2-3 sprints)
- **P2**: 18h (2 sprints)
- **P3**: 24h (3 sprints)

**Total**: ~66.5h (~8-9 jours de travail)

## Recommandation

**Priorité immédiate**: Fixer P0 (build + sécurité) avant toute autre chose.

**Roadmap suggérée**:
1. **Sprint 1**: P0 complet (build + sécurité critique)
2. **Sprint 2-3**: P1 sécurité (rate limiting, CORS, validation)
3. **Sprint 4-5**: P1 performance + P2 observabilité
4. **Sprint 6+**: P2 robustesse + P3 refactors

---

**Fin du rapport d'audit**

