# Audit Technique Exhaustif — Module Frontend Veza (`apps/web`)

**Date**: 2025-12-12  
**Auditeur**: Auto (Cursor AI)  
**Module**: Frontend React (Vite + TypeScript)  
**Version**: 1.0.0

---

## Table des matières

1. [Module Overview + Runbook](#module-overview--runbook)
2. [Health/Build/Test Status](#healthbuildtest-status)
3. [Security Findings](#security-findings)
4. [Observability & Prod Readiness Gaps](#observability--prod-readiness-gaps)
5. [Performance Notes](#performance-notes)
6. [Issue List Priorisée (P0→P3)](#issue-list-priorisée-p0p3)
7. [Execution Plan](#execution-plan)

---

# Module Overview + Runbook

## But du module

Le module `apps/web` est l'application frontend React de la plateforme Veza, une plateforme audio collaborative avec streaming, chat en temps réel, bibliothèque musicale, playlists collaboratives, et marketplace.

**Rôle exact** : Interface utilisateur web (SPA) pour :
- Authentification (JWT, 2FA, OAuth)
- Streaming audio (HLS.js, WebRTC)
- Chat en temps réel (WebSocket)
- Gestion de bibliothèque et playlists
- Marketplace de tracks
- Profils utilisateurs et collaboration

## Entrées / Sorties

### APIs exposées (consommées)

**HTTP REST** :
- Base URL : `VITE_API_BASE_URL` (défaut: `http://localhost:8080/api/v1`)
- Client : Axios (`src/services/api.ts`, `src/services/api/client.ts`)
- Endpoints principaux :
  - `/auth/*` : login, register, refresh, logout, me
  - `/users/*` : CRUD utilisateurs
  - `/tracks/*` : CRUD tracks, upload, download
  - `/library/*` : bibliothèque utilisateur
  - `/conversations/*`, `/messages/*` : chat
  - `/playlists/*` : playlists

**WebSocket** :
- URL : `VITE_WS_BASE_URL` (défaut: `ws://localhost:8081/ws`)
- Service : `src/services/websocket.ts`
- Protocole : JSON messages avec types (`join_conversation`, `send_message`, `typing`, etc.)

**Streaming** :
- URL : `VITE_STREAM_URL` (défaut: `http://localhost:8082`)
- Protocole : HLS.js pour audio streaming

### Formats

- **JSON** : Toutes les APIs REST et WebSocket
- **FormData** : Upload de fichiers (tracks, avatars)
- **Schémas Zod** : Validation côté client (`src/services/api.ts`)

## Dépendances internes

- **Stores Zustand** : `src/stores/auth.ts`, `src/stores/chat.ts`, `src/stores/library.ts`, `src/stores/ui.ts`
- **Types partagés** : `src/types/api.ts`, `src/types/index.ts`
- **Utils** : `src/utils/*` (sanitize, token-manager, validation, etc.)
- **Hooks** : `src/hooks/*` (useAuth, useDebounce, usePWA, etc.)

## Dépendances externes

- **Base de données** : Aucune (consomme API backend Go)
- **Redis** : Aucune (consomme via backend)
- **Storage** : `localStorage` (tokens), `sessionStorage` (refresh tokens), IndexedDB (PWA cache)
- **Services externes** : Pas de dépendances directes (tout via backend)

## Exécution

### Commandes de build/run/dev

```bash
# Dev
npm run dev                    # Vite dev server (port 3000)
npm run dev:lab                # Dev avec vraie BDD (via scripts/start_lab.sh)
npm run dev:mocks              # Dev avec MSW mocks

# Build
npm run build                  # Production build → dist/

# Tests
npm test                       # Vitest (unit)
npm run test:e2e               # Playwright E2E
npm run test:e2e:mocks         # E2E avec MSW

# Qualité
npm run typecheck              # TypeScript check
npm run lint                   # ESLint
npm run format                 # Prettier
```

### Configuration

**Variables d'environnement** (validées via Zod dans `src/config/env.ts`) :
- `VITE_API_BASE_URL` : URL API REST
- `VITE_WS_BASE_URL` : URL WebSocket
- `VITE_STREAM_URL` : URL streaming
- `VITE_UPLOAD_URL` : URL upload
- `VITE_APP_NAME` : Nom de l'app
- `VITE_DEBUG` : Mode debug (boolean)
- `VITE_USE_MSW` : Activer MSW mocks
- `VITE_FCM_VAPID_KEY` : Push notifications (optionnel)

**Fichiers de config** :
- `vite.config.ts` : Configuration Vite (aliases, plugins, CSP)
- `tsconfig.json` : TypeScript config
- `vitest.config.ts` : Tests config
- `eslint.config.js` : ESLint config
- `nginx.conf` : Config production (Docker)
- `Dockerfile` : Build production

### Docker

```bash
docker build -t veza-frontend .
docker run -p 80:80 veza-frontend
```

## Points d'intégration

### Contrats d'API

**Backend Go** (`veza-backend-api`) :
- Format réponse : `{ success: true, data: {...} }` ou `{ error: "...", message: "..." }`
- Auth : JWT dans header `Authorization: Bearer <token>`
- IDs : Backend retourne `int64`, frontend attend `string` (conversion nécessaire)

**Chat Server Rust** (`veza-chat-server`) :
- WebSocket sur `/ws`
- Token JWT en query param : `?token=<access_token>`
- Messages JSON : `{ type: string, data: any }`

**Stream Server Rust** (`veza-stream-server`) :
- HLS streaming via HTTP
- WebSocket pour synchronisation playback

### Auth

- **JWT** : Access token (15min) + Refresh token (30/90 jours selon `remember_me`)
- **Storage** : `localStorage` (access), `sessionStorage`/cookie (refresh)
- **Refresh automatique** : Intercepteur Axios (`src/services/api/client.ts`)
- **2FA** : Supporté via `src/services/2fa-service.ts`
- **OAuth** : Supporté via `src/features/auth/hooks/useOAuthCallback.ts`

### Headers / CORS

- CORS géré par backend
- Headers de sécurité : CSP, X-Frame-Options, etc. (via `vite.config.ts` et `nginx.conf`)

### Schéma DB / UUID

- **IDs** : Backend retourne `int64`, frontend utilise `string` (conversion dans `src/services/api.ts`)
- **UUID** : Pas utilisé (IDs numériques)

---

# Health/Build/Test Status

## Build Status

### TypeScript Errors

**Total** : ~100+ erreurs TypeScript (voir `ts_real_errors.log`)

**Catégories principales** :
1. **Modules manquants** (P0) :
   - `@/hooks/use-toast` : utilisé mais non exporté/existant
   - `@/stores/player` : utilisé mais non existant
   - `@/components/ui/progress` : utilisé mais non existant
   - `@/hooks/useIntersectionObserver` : utilisé mais non existant
   - `@/features/settings/pages/SettingsPage` : importé mais chemin incorrect
   - `@/features/profile/pages/UserProfilePage` : importé mais chemin incorrect
   - `@/features/roles/pages/RolesPage` : importé mais chemin incorrect
   - `@/features/tracks/pages/TrackDetailPage` : importé mais chemin incorrect
   - `@/features/playlists/routes` : importé mais chemin incorrect
   - `@/pages/marketplace/MarketplaceHome` : importé mais chemin incorrect

2. **Types incorrects** (P1) :
   - `Track` : propriétés manquantes (`url`, `cover_url`, `album`, `file_size`, `is_playing`, `progress`)
   - `User` : propriétés manquantes (`userId`, `username`)
   - `PaginatedResponse<Track>` : propriété `tracks` manquante
   - `ChatPage` : export par défaut manquant (lazy loading)

3. **React Query v5 incompatibilité** (P1) :
   - `onSuccess` déprécié (remplacé par `useEffect` + `data`)
   - `keepPreviousData` déprécié (remplacé par `placeholderData: keepPreviousData`)

4. **Types implicites `any`** (P2) : ~20 occurrences

### ESLint Warnings

**Total** : ~50+ warnings

**Principaux** :
- `no-console` : 121 occurrences (devrait être supprimé en prod)
- `@typescript-eslint/no-explicit-any` : ~30 occurrences
- `@typescript-eslint/no-unused-vars` : 2 erreurs (variables non utilisées)
- `react-hooks/exhaustive-deps` : 1 warning

## Test Status

### Coverage

**Configuré** : 80% threshold (branches, functions, lines, statements)  
**État actuel** : Non mesuré (pas de rapport de coverage visible)

### Tests unitaires (Vitest)

**Total** : 189 fichiers de test (`.test.ts`, `.test.tsx`)

**Résultats** :
- ✅ La plupart des tests passent
- ❌ **2 tests échouent** :
  1. `src/features/playlists/hooks/usePlaylistTrack.test.tsx` : `useAddTrackToPlaylist` — argument manquant
  2. `src/features/playlists/hooks/usePlaylistTrack.test.tsx` : `useRemoveTrackFromPlaylist` — fonction non exportée

**Problèmes identifiés** :
- MSW handlers manquants pour certains endpoints WebSocket
- Mocks incomplets pour certains services

### Tests E2E (Playwright)

**Config** : `playwright.config.ts`  
**Tests** : `e2e/qa-audit.spec.ts`  
**État** : Non exécuté dans cet audit

## Gestion des erreurs

### Points positifs

- ErrorBoundary React (`src/components/ErrorBoundary.tsx`)
- Intercepteurs Axios pour refresh token automatique
- Validation Zod pour les réponses API

### Points à améliorer

- Pas de centralisation des erreurs (chaque composant gère ses erreurs)
- Pas de logging structuré (console.log partout)
- Pas de retry automatique pour les requêtes échouées (sauf refresh token)

## Cohérence des conventions

### Naming

- ✅ Cohérent : PascalCase pour composants, camelCase pour fonctions
- ⚠️ Incohérences :
  - `useAuthStore` vs `useAuth` (deux hooks différents)
  - `apiService` vs `apiClient` (deux clients API différents)
  - `websocketService` vs `wsService` (aliases, confusion)

### Structure dossiers

- ✅ Feature-based : `src/features/*`
- ✅ Séparation claire : components, hooks, services, stores
- ⚠️ Duplication : `src/services/api.ts` et `src/services/api/client.ts` (deux implémentations)

### Séparation couches

- ✅ Services séparés des composants
- ✅ Stores Zustand pour state management
- ⚠️ Logique métier parfois dans les composants (ex: `src/features/library/components/LibraryManager.tsx`)

---

# Security Findings

## Top 10 Risques Sécurité

### P0 — Critiques (Exploitables immédiatement)

#### 1. **Tokens JWT stockés en localStorage (XSS vulnérable)**

**Fichiers** :
- `src/services/api.ts` : lignes 105-121
- `src/services/api/auth.ts` : lignes 64-68, 124-126
- `src/utils/token-manager.ts` : lignes 15-34, 40-54

**Problème** :
```typescript
// src/services/api.ts:105-106
private getAccessToken(): string | null {
  return localStorage.getItem('access_token');
}
```

Les tokens JWT sont stockés dans `localStorage`, vulnérables aux attaques XSS. Un script malveillant injecté peut voler les tokens.

**Impact** : Vol de session, accès non autorisé aux comptes utilisateurs

**Fix minimal** :
- Option 1 : Utiliser `httpOnly` cookies (nécessite backend)
- Option 2 : Utiliser `sessionStorage` + rotation fréquente des tokens
- Option 3 : Implémenter un service worker pour isoler les tokens

**Plan de validation** :
- Test XSS : Injecter `<script>alert(localStorage.getItem('access_token'))</script>`
- Vérifier que les tokens ne sont pas accessibles via XSS

**Effet de bord** : Nécessite modification backend pour cookies httpOnly

**Effort** : M (2-4h)

---

#### 2. **CSP non-strict en production (`unsafe-inline`, `unsafe-eval`)**

**Fichiers** :
- `vite.config.ts` : lignes 62-75

**Problème** :
```typescript
'script-src': [
  "'self'",
  "'unsafe-inline' 'unsafe-eval' blob:",  // ⚠️ Dangereux
],
'style-src': [
  "'self'",
  "'unsafe-inline'",  // ⚠️ Nécessaire pour Tailwind mais risqué
],
```

La CSP en dev contient `unsafe-inline` et `unsafe-eval`, permettant l'exécution de scripts inline (XSS).

**Impact** : Attaques XSS facilitées

**Fix minimal** :
- Utiliser des nonces CSP pour les scripts inline (déjà partiellement implémenté dans `src/utils/csp.ts`)
- Supprimer `unsafe-eval` en production
- Utiliser `nonce-` pour les styles inline si possible

**Plan de validation** :
- Tester avec CSP strict en production
- Vérifier que tous les scripts ont des nonces

**Effet de bord** : Peut casser certains composants si nonces mal gérés

**Effort** : S (1-2h)

---

#### 3. **Utilisation de `dangerouslySetInnerHTML` sans sanitisation complète**

**Fichiers** :
- `src/features/chat/components/ChatMessages.tsx` : ligne 102
- `src/features/chat/components/VirtualizedChatMessages.tsx` : ligne 75

**Problème** :
```typescript
// src/features/chat/components/ChatMessages.tsx:102
dangerouslySetInnerHTML={{ 
  __html: sanitizeChatMessage(message.content) 
}}
```

Bien que `sanitizeChatMessage` soit utilisé, la fonction `sanitizeHTML` dans `src/utils/sanitize.ts` peut avoir des failles (regex-based, pas de parser HTML complet).

**Impact** : XSS via messages de chat

**Fix minimal** :
- Utiliser `DOMPurify` (déjà dans `package.json` : `dompurify@^3.3.0`) au lieu de la sanitisation custom
- Vérifier que `DOMPurify` est bien utilisé partout

**Plan de validation** :
- Test XSS : Envoyer `<img src=x onerror=alert(1)>` dans un message
- Vérifier que le script ne s'exécute pas

**Effet de bord** : Aucun (DOMPurify est déjà une dépendance)

**Effort** : S (1h)

---

#### 4. **CSRF Token non implémenté**

**Fichiers** :
- `src/services/csrf.ts` : lignes 1-34

**Problème** :
```typescript
// src/services/csrf.ts:14-17
public async refreshCsrfToken(): Promise<void> {
  // Placeholder: fetch from backend if needed
  // this.csrfToken = ...
}
```

Le service CSRF existe mais n'est pas implémenté. Aucune protection CSRF pour les requêtes POST/PUT/DELETE.

**Impact** : Attaques CSRF possibles (actions non autorisées)

**Fix minimal** :
- Implémenter `refreshCsrfToken()` pour récupérer le token depuis le backend
- Ajouter le header `X-CSRF-Token` dans tous les intercepteurs Axios
- Backend doit générer et valider les tokens CSRF

**Plan de validation** :
- Test CSRF : Créer une requête POST depuis un site externe
- Vérifier que la requête est rejetée sans token CSRF valide

**Effet de bord** : Nécessite modification backend

**Effort** : M (2-3h)

---

#### 5. **WebSocket token en query param (exposé dans logs/URLs)**

**Fichiers** :
- `src/services/api.ts` : ligne 380
- `src/services/websocket.ts` : ligne 45

**Problème** :
```typescript
// src/services/api.ts:378-381
getWebSocketUrl(): string {
  const token = this.getAccessToken();
  return `${WS_BASE_URL}?token=${token}`;
}
```

Le token JWT est passé en query param, exposé dans :
- Logs serveur
- Historique navigateur
- URLs partagées

**Impact** : Fuite de token via logs/historique

**Fix minimal** :
- Utiliser le header `Authorization` si le serveur WebSocket le supporte
- Sinon, utiliser un token temporaire (one-time token) généré par le backend

**Plan de validation** :
- Vérifier que le token n'apparaît pas dans les logs serveur
- Vérifier que l'historique navigateur ne contient pas le token

**Effet de bord** : Nécessite modification serveur WebSocket Rust

**Effort** : M (2-3h)

---

### P1 — Haute priorité (Bugs fréquents / Dette bloquante)

#### 6. **Validation JWT côté client absente (expiration non vérifiée)**

**Fichiers** :
- `src/services/api/client.ts` : lignes 11-78
- `src/utils/token-manager.ts` : lignes 40-54

**Problème** :
Aucune vérification de l'expiration du token JWT côté client. Le token peut être expiré mais toujours utilisé jusqu'à ce que le backend renvoie 401.

**Impact** : Requêtes inutiles avec token expiré, UX dégradée

**Fix minimal** :
- Décoder le JWT (base64) et vérifier `exp` avant chaque requête
- Refresh automatique si expiration < 5min

**Plan de validation** :
- Test : Créer un token expiré, vérifier qu'il est refresh automatiquement

**Effet de bord** : Aucun

**Effort** : S (1h)

---

#### 7. **Pas de rate limiting côté client**

**Fichiers** :
- `src/services/api.ts` : toutes les méthodes
- `src/services/websocket.ts` : méthode `send()`

**Problème** :
Aucune protection contre le spam de requêtes (rate limiting). Un utilisateur malveillant peut spammer l'API.

**Impact** : DoS côté client, surcharge serveur

**Fix minimal** :
- Implémenter un rate limiter simple (ex: max 10 requêtes/seconde)
- Utiliser un debounce pour les requêtes répétées

**Plan de validation** :
- Test : Envoyer 100 requêtes simultanées, vérifier que seules 10 passent

**Effet de bord** : Peut ralentir certaines opérations légitimes

**Effort** : S (1-2h)

---

#### 8. **Secrets potentiels dans le code (VITE_FCM_VAPID_KEY)**

**Fichiers** :
- `src/config/env.ts` : ligne 18
- `vite.config.ts` : pas de validation

**Problème** :
`VITE_FCM_VAPID_KEY` est une clé publique (VAPID), mais elle est chargée côté client. Si elle est mal configurée, elle pourrait exposer une clé privée.

**Impact** : Fuite de clé si erreur de configuration

**Fix minimal** :
- Documenter que `VITE_FCM_VAPID_KEY` doit être la clé **publique** uniquement
- Ajouter une validation pour s'assurer que ce n'est pas une clé privée

**Plan de validation** :
- Vérifier que la clé dans `.env` est bien publique (commence par `BK` ou similaire)

**Effet de bord** : Aucun

**Effort** : S (30min)

---

#### 9. **Pas de validation de taille de fichier upload côté client**

**Fichiers** :
- `src/features/library/components/UploadModal.tsx`
- `src/features/tracks/components/TrackUpload.tsx`

**Problème** :
Aucune validation de la taille de fichier avant upload. Un utilisateur peut tenter d'uploader un fichier de 10GB.

**Impact** : Surcharge serveur, DoS

**Fix minimal** :
- Valider la taille max (ex: 100MB) avant upload
- Afficher une erreur claire si dépassement

**Plan de validation** :
- Test : Tenter d'uploader un fichier > 100MB, vérifier que c'est rejeté

**Effet de bord** : Aucun

**Effort** : S (1h)

---

#### 10. **CSP middleware non utilisé (créé mais jamais appelé)**

**Fichiers** :
- `src/utils/csp.ts` : lignes 185-202

**Problème** :
```typescript
// src/utils/csp.ts:185-202
export function createCSPMiddleware() {
  return (_req: any, res: any, next: any) => {
    // ... génère CSP header
  }
}
```

Le middleware CSP est créé mais jamais utilisé (c'est du code Node.js dans un frontend React). La CSP est gérée via `vite.config.ts` uniquement.

**Impact** : CSP peut être inconsistante entre dev et prod

**Fix minimal** :
- Supprimer le middleware inutile (code mort)
- S'assurer que la CSP dans `vite.config.ts` est correcte pour prod

**Plan de validation** :
- Vérifier que la CSP en prod est stricte (pas d'`unsafe-inline`)

**Effet de bord** : Aucun (code mort)

**Effort** : S (30min)

---

## Autres problèmes sécurité (P2/P3)

### P2 — Moyenne priorité

- **Pas de validation de format de fichier upload** : Seule la validation backend existe
- **Pas de protection contre clickjacking** : `X-Frame-Options: SAMEORIGIN` au lieu de `DENY` dans `nginx.conf`
- **Pas de HSTS** : Header `Strict-Transport-Security` manquant dans `nginx.conf`
- **Logs console en production** : 121 occurrences de `console.log/error/warn` (peuvent exposer des infos sensibles)

### P3 — Basse priorité

- **Pas de validation de rate limiting pour WebSocket** : Spam de messages possible
- **Pas de chiffrement des données sensibles en localStorage** : Tokens non chiffrés (mais localStorage est déjà vulnérable)

---

# Observability & Prod Readiness Gaps

## Logs structurés

### État actuel

❌ **Aucun logging structuré** :
- Utilisation de `console.log/error/warn` partout (121 occurrences)
- Pas de corrélation (pas de `request_id` / `trace_id`)
- Pas de niveaux de log cohérents
- Logs en production (devrait être désactivé)

**Fichiers concernés** :
- `src/services/websocket.ts` : 6 occurrences
- `src/features/streaming/services/playbackAnalyticsService.ts` : 11 occurrences
- `src/app/App.tsx` : 1 occurrence
- Et 50+ autres fichiers

### Fix recommandé

- Implémenter un logger structuré (ex: `pino` ou `winston` côté client)
- Ajouter `request_id` pour chaque requête API
- Désactiver les logs en production (`if (import.meta.env.DEV)`)

**Effort** : M (2-3h)

---

## Metrics

### État actuel

❌ **Aucune métrique** :
- Pas de Prometheus / StatsD
- Pas de métriques custom (erreurs, latence, etc.)
- Pas de healthcheck détaillé

### Healthcheck

✅ **Basique** : `/health` endpoint dans `nginx.conf` (ligne 26-30)
- Retourne simplement `200 "healthy\n"`
- Pas de vérification de dépendances (API, WebSocket, etc.)

### Fix recommandé

- Ajouter un healthcheck frontend qui vérifie :
  - Connectivité API
  - Connectivité WebSocket
  - État du storage (localStorage disponible)
- Exposer des métriques custom (optionnel, via API backend)

**Effort** : S (1-2h)

---

## Timeouts / Retries

### État actuel

⚠️ **Partiel** :
- Timeout Axios : 10s (`src/services/api.ts:58`)
- Retry : Seulement pour refresh token (intercepteur)
- Pas de retry pour autres erreurs réseau
- Pas de circuit breaker

### Fix recommandé

- Implémenter un retry avec backoff exponentiel pour les erreurs réseau (5xx, timeout)
- Ajouter un circuit breaker pour éviter de spammer un serveur down
- Configurer des timeouts différents selon le type de requête (upload: 60s, API: 10s)

**Effort** : M (2-3h)

---

## Gestion de charge

### État actuel

⚠️ **Basique** :
- Pas de pool de connexions (Axios gère automatiquement)
- Pas de limite de connexions WebSocket simultanées
- Pas de chunking pour les uploads volumineux

### Uploads

✅ **Chunked upload** : Implémenté dans `src/features/tracks/services/chunkedUploadService.ts`
- Upload par chunks pour fichiers volumineux
- Retry automatique en cas d'échec

### WebSocket

⚠️ **Pas de backpressure** :
- Pas de limite de messages en queue
- Pas de gestion de reconnexion intelligente (backoff exponentiel partiel)

**Fix recommandé** :
- Limiter la queue de messages WebSocket (max 100 messages)
- Implémenter un backpressure (pause si queue > 50)

**Effort** : S (1-2h)

---

## Migrations / Compatibilité

### État actuel

⚠️ **Conversion IDs** :
- Backend retourne `int64`, frontend attend `string`
- Conversion manuelle dans `src/services/api.ts` (lignes 339-344, 361-374)

**Problème** : Risque d'erreur si conversion oubliée

**Fix recommandé** :
- Créer un utilitaire centralisé pour la conversion
- Utiliser des types TypeScript stricts pour forcer la conversion

**Effort** : S (1h)

---

# Performance Notes

## Hotspots évidents

### 1. **Bundle size**

**État** : Non mesuré (bundle analyzer présent mais non exécuté)

**Fichiers** :
- `vite.config.ts` : lignes 34-39 (bundle analyzer configuré)
- `dist/bundle-analysis.html` : présent mais non analysé

**Recommandations** :
- Analyser le bundle (`npm run build` puis ouvrir `dist/bundle-analysis.html`)
- Identifier les dépendances lourdes
- Code splitting par route (déjà fait via lazy loading)

**Effort** : S (30min pour analyse)

---

### 2. **Re-renders inutiles**

**Problèmes identifiés** :
- `src/components/data/Table.tsx` : ligne 102 — `useCallback` avec dépendance manquante
- Pas de `React.memo` sur les composants lourds (liste de tracks, messages chat)

**Fix recommandé** :
- Ajouter `React.memo` sur les composants de liste
- Corriger les dépendances de `useCallback`/`useMemo`

**Effort** : M (2-3h)

---

### 3. **JSON parsing répétitif**

**Fichiers** :
- `src/services/websocket.ts` : ligne 59 — `JSON.parse` à chaque message

**Impact** : Faible (WebSocket messages sont petits)

**Fix recommandé** : Aucun (optimisation prématurée)

---

### 4. **N+1 queries potentielles**

**Fichiers** :
- `src/features/library/components/LibraryManager.tsx` : chargement de tracks un par un possible

**Impact** : Moyen (si beaucoup de tracks)

**Fix recommandé** :
- Utiliser la pagination côté API
- Charger les tracks par batch

**Effort** : S (1h)

---

## Streaming

### HLS.js

✅ **Bien configuré** : Utilisation de `hls.js@^1.6.14`
- Buffering automatique
- Adaptation de bitrate (si backend supporte)

**Pas de problème identifié**

---

## React Query

### Cache

✅ **Bien configuré** : React Query v5 avec cache automatique
- `staleTime` : défaut (0, toujours stale)
- `cacheTime` : défaut (5min)

**Recommandation** :
- Augmenter `staleTime` pour les données peu changeantes (profils, tracks)
- Configurer `staleTime: 5 * 60 * 1000` (5min) pour les tracks

**Effort** : S (30min)

---

## WebSocket

### Reconnexion

✅ **Bien implémenté** : Backoff exponentiel dans `src/services/websocket.ts` (lignes 76-98)
- Max 5 tentatives
- Délai exponentiel : `3000 * 2^(attempt-1)`

**Pas de problème identifié**

---

# Issue List Priorisée (P0→P3)

## Format des issues

Chaque issue suit le format :
- **ID** : `WEB-<P0|P1|P2|P3>-###`
- **Titre**
- **Impact** (concret, scénarios)
- **Preuve** : fichiers + symboles + extrait court
- **Cause racine**
- **Fix minimal** (patch-level, pas de refonte totale)
- **Plan de validation** (tests + commande + cas limites)
- **Effet de bord / risque de régression**
- **Effort estimé** (S/M/L) + dépendances

---

## P0 — Build Breakers / Sécurité Critique

### WEB-P0-001 : Modules manquants (build cassé)

**Impact** : Build TypeScript échoue, application ne compile pas

**Preuve** :
- `src/components/player/AudioPlayer.tsx:6` : `Cannot find module '@/hooks/use-toast'`
- `src/components/player/AudioPlayer.tsx:2` : `Cannot find module '@/stores/player'`
- `src/components/ui/optimized-image.tsx:2` : `Cannot find module '@/hooks/useIntersectionObserver'`
- `src/components/ui/LazyComponent.tsx:39` : `Cannot find module '@/features/settings/pages/SettingsPage'`
- Et 5+ autres modules manquants

**Cause racine** :
- Fichiers supprimés/déplacés sans mise à jour des imports
- Exports manquants dans les modules

**Fix minimal** :
1. Créer les modules manquants ou corriger les imports
2. Vérifier que tous les exports sont corrects

**Plan de validation** :
```bash
npm run typecheck  # Doit passer sans erreur
npm run build      # Doit compiler
```

**Effet de bord** : Aucun (fix nécessaire pour build)

**Effort** : M (2-3h)

---

### WEB-P0-002 : Tokens JWT en localStorage (XSS vulnérable)

**Voir [Security Finding #1](#1-tokens-jwt-stockés-en-localstorage-xss-vulnérable)**

**Effort** : M (2-4h)

---

### WEB-P0-003 : CSP non-strict (`unsafe-inline`, `unsafe-eval`)

**Voir [Security Finding #2](#2-csp-non-strict-en-production-unsafe-inline-unsafe-eval)**

**Effort** : S (1-2h)

---

### WEB-P0-004 : `dangerouslySetInnerHTML` sans sanitisation complète

**Voir [Security Finding #3](#3-utilisation-de-dangerouslysetinnerhtml-sans-sanitisation-complète)**

**Effort** : S (1h)

---

### WEB-P0-005 : CSRF Token non implémenté

**Voir [Security Finding #4](#4-csrf-token-non-implémenté)**

**Effort** : M (2-3h)

---

## P1 — Bugs fréquents / Dette bloquante

### WEB-P1-001 : Types Track/User incomplets (100+ erreurs TypeScript)

**Impact** : Erreurs TypeScript partout, développement ralenti, bugs runtime possibles

**Preuve** :
- `src/components/player/AudioPlayer.tsx:90` : `Property 'url' does not exist on type 'Track'`
- `src/components/player/AudioPlayer.tsx:179` : `Property 'cover_url' does not exist on type 'Track'`
- `src/features/library/components/VirtualizedTrackList.tsx:56` : `Property 'album' does not exist on type 'Track'`
- `src/features/chat/hooks/useChat.ts:9` : `Property 'userId' does not exist on type 'AuthState'`

**Cause racine** :
- Types `Track` et `User` dans `src/types/api.ts` ne correspondent pas à l'usage réel
- Backend retourne plus de champs que définis dans les types

**Fix minimal** :
1. Mettre à jour `src/types/api.ts` avec tous les champs utilisés
2. Vérifier la cohérence avec le backend Go

**Plan de validation** :
```bash
npm run typecheck  # Doit passer sans erreur
```

**Effet de bord** : Aucun (correction de types)

**Effort** : M (2-3h)

---

### WEB-P1-002 : React Query v5 incompatibilité (`onSuccess`, `keepPreviousData`)

**Impact** : Warnings React Query, comportement incorrect possible

**Preuve** :
- `src/features/chat/pages/ChatPage.tsx:28` : `'onSuccess' does not exist`
- `src/features/library/hooks/useMyTracks.ts:17` : `'keepPreviousData' does not exist`

**Cause racine** : Migration React Query v4 → v5 incomplète

**Fix minimal** :
1. Remplacer `onSuccess` par `useEffect` avec dépendance sur `data`
2. Remplacer `keepPreviousData` par `placeholderData: keepPreviousData`

**Plan de validation** :
```bash
npm run typecheck  # Doit passer sans erreur
npm test           # Tests doivent passer
```

**Effet de bord** : Aucun (migration standard)

**Effort** : S (1-2h)

---

### WEB-P1-003 : Tests échouent (usePlaylistTrack)

**Impact** : CI/CD peut échouer, confiance réduite dans les tests

**Preuve** :
- `src/features/playlists/hooks/usePlaylistTrack.test.tsx` : 2 tests échouent
  - `useAddTrackToPlaylist` : argument manquant
  - `useRemoveTrackFromPlaylist` : fonction non exportée

**Cause racine** :
- Signature de fonction changée sans mise à jour des tests
- Export manquant

**Fix minimal** :
1. Corriger les signatures de fonction
2. Ajouter les exports manquants
3. Mettre à jour les tests

**Plan de validation** :
```bash
npm test -- usePlaylistTrack  # Doit passer
```

**Effet de bord** : Aucun

**Effort** : S (1h)

---

### WEB-P1-004 : Validation JWT côté client absente

**Voir [Security Finding #6](#6-validation-jwt-côté-client-absente-expiration-non-vérifiée)**

**Effort** : S (1h)

---

### WEB-P1-005 : Duplication de clients API (`apiService` vs `apiClient`)

**Impact** : Confusion, maintenance difficile, bugs possibles

**Preuve** :
- `src/services/api.ts` : classe `ApiService` (singleton `apiService`)
- `src/services/api/client.ts` : `apiClient` (Axios instance)
- `src/lib/apiClient.ts` : autre `apiClient` (Axios instance)

**Cause racine** : Refactoring incomplet, plusieurs implémentations coexistent

**Fix minimal** :
1. Unifier en un seul client API
2. Migrer tous les usages vers le client unifié
3. Supprimer les clients dupliqués

**Plan de validation** :
```bash
grep -r "apiService\|apiClient" src/  # Vérifier qu'un seul client est utilisé
npm run typecheck                      # Doit passer
npm test                              # Tests doivent passer
```

**Effet de bord** : Risque de régression si migration incomplète

**Effort** : M (3-4h)

---

### WEB-P1-006 : WebSocket token en query param

**Voir [Security Finding #5](#5-websocket-token-en-query-param-exposé-dans-logsurls)**

**Effort** : M (2-3h)

---

### WEB-P1-007 : Conversion IDs int64 → string manuelle (risque d'erreur)

**Impact** : Bugs possibles si conversion oubliée, maintenance difficile

**Preuve** :
- `src/services/api.ts:339-344` : conversion manuelle `String(conv.id)`
- `src/services/api.ts:361-374` : conversion manuelle `String(data.id)`

**Cause racine** : Backend retourne `int64`, frontend attend `string`

**Fix minimal** :
1. Créer un utilitaire `convertBackendId(id: number | string): string`
2. Utiliser partout où nécessaire
3. Ajouter des types stricts pour forcer la conversion

**Plan de validation** :
```bash
grep -r "String(.*\.id)" src/  # Vérifier que toutes les conversions utilisent l'utilitaire
npm run typecheck              # Doit passer
```

**Effet de bord** : Aucun

**Effort** : S (1h)

---

## P2 — Qualité, maintenabilité, perf non critique

### WEB-P2-001 : 121 occurrences de `console.log/error/warn` (logs en production)

**Impact** : Performance légère, exposition d'infos sensibles possible, pollution console

**Preuve** :
```bash
grep -r "console\." src/ | wc -l  # 121 occurrences
```

**Cause racine** : Pas de logger structuré, logs de debug laissés

**Fix minimal** :
1. Créer un logger wrapper (`src/utils/logger.ts`)
2. Remplacer tous les `console.*` par le logger
3. Désactiver les logs en production

**Plan de validation** :
```bash
grep -r "console\." src/ | wc -l  # Doit être 0
npm run build && npm run preview    # Vérifier que pas de logs en prod
```

**Effet de bord** : Aucun

**Effort** : M (2-3h)

---

### WEB-P2-002 : Pas de rate limiting côté client

**Voir [Security Finding #7](#7-pas-de-rate-limiting-côté-client)**

**Effort** : S (1-2h)

---

### WEB-P2-003 : Re-renders inutiles (pas de `React.memo`)

**Impact** : Performance dégradée sur les listes longues

**Preuve** :
- `src/components/data/Table.tsx:102` : `useCallback` avec dépendance manquante
- Pas de `React.memo` sur `TrackList`, `ChatMessages`, etc.

**Cause racine** : Optimisation non faite

**Fix minimal** :
1. Ajouter `React.memo` sur les composants de liste
2. Corriger les dépendances de `useCallback`

**Plan de validation** :
- Profiler avec React DevTools
- Vérifier que les re-renders sont réduits

**Effet de bord** : Aucun

**Effort** : M (2-3h)

---

### WEB-P2-004 : Pas de validation de taille de fichier upload

**Voir [Security Finding #9](#9-pas-de-validation-de-taille-de-fichier-upload-côté-client)**

**Effort** : S (1h)

---

### WEB-P2-005 : Pas de logging structuré

**Voir [Observability - Logs structurés](#logs-structurés)**

**Effort** : M (2-3h)

---

### WEB-P2-006 : Healthcheck basique (pas de vérification dépendances)

**Voir [Observability - Healthcheck](#healthcheck)**

**Effort** : S (1-2h)

---

### WEB-P2-007 : Pas de retry automatique (sauf refresh token)

**Voir [Observability - Timeouts / Retries](#timeouts--retries)**

**Effort** : M (2-3h)

---

### WEB-P2-008 : Bundle size non analysé

**Voir [Performance - Bundle size](#1-bundle-size)**

**Effort** : S (30min)

---

### WEB-P2-009 : CSP middleware inutile (code mort)

**Voir [Security Finding #10](#10-csp-middleware-non-utilisé-créé-mais-jamais-appelé)**

**Effort** : S (30min)

---

### WEB-P2-010 : Naming incohérent (`useAuthStore` vs `useAuth`, `apiService` vs `apiClient`)

**Impact** : Confusion, maintenance difficile

**Preuve** :
- `src/stores/auth.ts` : exporte `useAuthStore`
- `src/features/auth/hooks/useAuth.ts` : exporte `useAuth` (utilise `useAuthStore` en interne)
- `src/services/api.ts` : `apiService`
- `src/services/api/client.ts` : `apiClient`

**Cause racine** : Refactoring incomplet, conventions non suivies

**Fix minimal** :
1. Documenter les conventions de naming
2. Unifier progressivement (dans le cadre de P1-005)

**Plan de validation** :
- Revue de code pour vérifier cohérence

**Effet de bord** : Aucun

**Effort** : S (1h pour documentation)

---

## P3 — Cosmétique, refactors non urgents

### WEB-P3-001 : 30+ occurrences de `any` (types implicites)

**Impact** : Perte de type safety, bugs possibles

**Preuve** :
```bash
grep -r ": any\|as any" src/ | wc -l  # ~30 occurrences
```

**Cause racine** : Types non définis, migration TypeScript incomplète

**Fix minimal** :
1. Remplacer progressivement les `any` par des types stricts
2. Utiliser `unknown` si type vraiment inconnu

**Plan de validation** :
```bash
npm run lint  # Doit passer sans warnings @typescript-eslint/no-explicit-any
```

**Effet de bord** : Aucun

**Effort** : L (4-6h, peut être fait progressivement)

---

### WEB-P3-002 : Pas de HSTS header

**Impact** : Sécurité légèrement réduite (manque protection HTTPS forcé)

**Preuve** :
- `nginx.conf` : pas de header `Strict-Transport-Security`

**Fix minimal** :
```nginx
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
```

**Plan de validation** :
- Vérifier avec `curl -I` que le header est présent

**Effet de bord** : Aucun

**Effort** : S (5min)

---

### WEB-P3-003 : `X-Frame-Options: SAMEORIGIN` au lieu de `DENY`

**Impact** : Protection clickjacking partielle

**Preuve** :
- `nginx.conf:14` : `X-Frame-Options "SAMEORIGIN"`

**Fix minimal** :
```nginx
add_header X-Frame-Options "DENY" always;
```

**Plan de validation** :
- Vérifier avec `curl -I`

**Effet de bord** : Aucun (pas d'iframe dans l'app)

**Effort** : S (5min)

---

### WEB-P3-004 : Pas de validation de format de fichier upload

**Voir [Security - Autres problèmes P2](#p2--moyenne-priorité)**

**Effort** : S (1h)

---

### WEB-P3-005 : TODO/FIXME dans le code (38 occurrences)

**Impact** : Dette technique, fonctionnalités incomplètes

**Preuve** :
```bash
grep -ri "TODO\|FIXME\|XXX\|HACK" src/ | wc -l  # 38 occurrences
```

**Exemples** :
- `src/features/chat/hooks/useChat.ts:114` : `// TODO: Add fetchHistory function`
- `src/features/library/components/LibraryManager.tsx:247` : `isLiked={() => false} // Todo`

**Fix minimal** :
1. Créer des issues GitHub pour chaque TODO
2. Supprimer les TODOs résolus
3. Documenter les TODOs non urgents

**Plan de validation** :
- Revue manuelle des TODOs

**Effet de bord** : Aucun

**Effort** : S (1h pour trier et documenter)

---

# Execution Plan

## Checklist P0 (ordre strict)

### Phase 1 : Build Fixes (Critique — 2-3h)

1. ✅ **WEB-P0-001** : Créer/corriger les modules manquants
   - Créer `src/hooks/use-toast.ts` (ou corriger import)
   - Créer `src/stores/player.ts` (ou corriger import)
   - Créer `src/hooks/useIntersectionObserver.ts` (ou corriger import)
   - Corriger les imports dans `src/components/ui/LazyComponent.tsx`
   - Valider : `npm run typecheck` passe

2. ✅ **WEB-P1-001** : Corriger les types Track/User
   - Mettre à jour `src/types/api.ts` avec tous les champs
   - Valider : `npm run typecheck` passe

### Phase 2 : Sécurité Critique (4-6h)

3. ✅ **WEB-P0-004** : Utiliser DOMPurify pour sanitisation
   - Remplacer `sanitizeChatMessage` par `DOMPurify.sanitize()`
   - Valider : Test XSS avec `<img src=x onerror=alert(1)>`

4. ✅ **WEB-P0-003** : Renforcer CSP (supprimer `unsafe-eval`)
   - Modifier `vite.config.ts` pour production
   - Utiliser nonces pour scripts inline
   - Valider : Build prod, vérifier CSP header

5. ✅ **WEB-P0-002** : Migrer tokens vers httpOnly cookies (nécessite backend)
   - **Option alternative** : Utiliser `sessionStorage` + rotation fréquente
   - Valider : Test XSS ne peut plus voler tokens

6. ✅ **WEB-P0-005** : Implémenter CSRF token (nécessite backend)
   - Implémenter `refreshCsrfToken()` dans `src/services/csrf.ts`
   - Ajouter header dans intercepteurs Axios
   - Valider : Test CSRF échoue sans token

### Phase 3 : Tests (1h)

7. ✅ **WEB-P1-003** : Corriger tests usePlaylistTrack
   - Corriger signatures et exports
   - Valider : `npm test -- usePlaylistTrack` passe

---

## Checklist P1 (par lots cohérents)

### Lot 1 : React Query v5 Migration (1-2h)

8. ✅ **WEB-P1-002** : Migrer `onSuccess` → `useEffect`
   - Remplacer dans `src/features/chat/pages/ChatPage.tsx`
   - Remplacer `keepPreviousData` → `placeholderData`
   - Valider : `npm run typecheck` + `npm test`

### Lot 2 : Unification Clients API (3-4h)

9. ✅ **WEB-P1-005** : Unifier `apiService` et `apiClient`
   - Choisir un client (recommandé : `apiClient` de `src/services/api/client.ts`)
   - Migrer tous les usages
   - Supprimer `src/services/api.ts` (ou le garder comme wrapper)
   - Valider : `npm run typecheck` + `npm test` + tests manuels

### Lot 3 : JWT & WebSocket (3-4h)

10. ✅ **WEB-P1-004** : Validation JWT expiration côté client
    - Décoder JWT et vérifier `exp`
    - Refresh automatique si < 5min
    - Valider : Test avec token expiré

11. ✅ **WEB-P1-006** : WebSocket token en header (nécessite backend)
    - **Option alternative** : Utiliser token temporaire (one-time)
    - Valider : Token n'apparaît pas dans logs

### Lot 4 : Utilitaires (1h)

12. ✅ **WEB-P1-007** : Créer utilitaire conversion IDs
    - Créer `src/utils/id-converter.ts`
    - Remplacer toutes les conversions manuelles
    - Valider : `grep -r "String(.*\.id)" src/` retourne 0

---

## Quick Wins (≤ 1h chacun)

### Sécurité

- ✅ **WEB-P2-009** : Supprimer CSP middleware inutile (30min)
- ✅ **WEB-P3-002** : Ajouter HSTS header (5min)
- ✅ **WEB-P3-003** : Changer `X-Frame-Options` à `DENY` (5min)
- ✅ **WEB-P2-004** : Validation taille fichier upload (1h)

### Qualité

- ✅ **WEB-P2-008** : Analyser bundle size (30min)
- ✅ **WEB-P3-005** : Trier et documenter TODOs (1h)

---

## Tests à ajouter en priorité

### P0 — Critiques

1. **Test XSS** : Injecter `<script>alert(1)</script>` dans chat, vérifier qu'il ne s'exécute pas
2. **Test CSRF** : Requête POST depuis site externe, vérifier rejet
3. **Test token expiration** : Vérifier refresh automatique

### P1 — Importants

4. **Test rate limiting** : Envoyer 100 requêtes, vérifier limitation
5. **Test upload taille max** : Tenter upload > 100MB, vérifier rejet
6. **Test WebSocket reconnexion** : Simuler déconnexion, vérifier reconnexion

---

## PR Plan

### PR 1 : Build Fixes (P0-001, P1-001)
**Titre** : `fix: resolve TypeScript build errors (missing modules, incomplete types)`
**Fichiers** :
- Créer modules manquants
- Mettre à jour `src/types/api.ts`
**Tests** : `npm run typecheck` passe

### PR 2 : Security - XSS & CSP (P0-003, P0-004)
**Titre** : `security: improve XSS protection (DOMPurify, strict CSP)`
**Fichiers** :
- `src/features/chat/components/ChatMessages.tsx`
- `src/features/chat/components/VirtualizedChatMessages.tsx`
- `vite.config.ts`
**Tests** : Test XSS manuel

### PR 3 : Security - Tokens & CSRF (P0-002, P0-005)
**Titre** : `security: migrate tokens to httpOnly cookies, implement CSRF protection`
**Fichiers** :
- `src/services/api/auth.ts`
- `src/services/csrf.ts`
- `src/services/api/client.ts`
**Tests** : Tests CSRF, test XSS token theft
**Note** : Nécessite coordination backend

### PR 4 : React Query v5 Migration (P1-002)
**Titre** : `chore: migrate to React Query v5 API (remove onSuccess, keepPreviousData)`
**Fichiers** :
- `src/features/chat/pages/ChatPage.tsx`
- `src/features/library/hooks/useMyTracks.ts`
**Tests** : `npm test` passe

### PR 5 : Unify API Clients (P1-005)
**Titre** : `refactor: unify API clients (remove duplication)`
**Fichiers** :
- `src/services/api.ts` (supprimer ou wrapper)
- `src/services/api/client.ts` (garder)
- Tous les fichiers utilisant `apiService`
**Tests** : Tests complets + tests manuels

### PR 6 : JWT & WebSocket Security (P1-004, P1-006)
**Titre** : `security: add JWT expiration validation, move WebSocket token to header`
**Fichiers** :
- `src/services/api/client.ts`
- `src/services/websocket.ts`
- `src/utils/token-manager.ts`
**Tests** : Tests expiration, tests WebSocket
**Note** : WebSocket nécessite backend

### PR 7 : Utilities & Tests (P1-007, P1-003)
**Titre** : `fix: add ID converter utility, fix usePlaylistTrack tests`
**Fichiers** :
- `src/utils/id-converter.ts`
- `src/services/api.ts` (utiliser converter)
- `src/features/playlists/hooks/usePlaylistTrack.test.tsx`
**Tests** : Tests unitaires

### PR 8 : Quick Wins (P2-009, P3-002, P3-003, P2-004, P2-008, P3-005)
**Titre** : `chore: quick wins (remove dead code, add security headers, validate uploads, analyze bundle, document TODOs)`
**Fichiers** :
- `src/utils/csp.ts` (supprimer middleware)
- `nginx.conf` (ajouter headers)
- `src/features/library/components/UploadModal.tsx` (validation taille)
- `package.json` (script bundle analysis)
- Documentation TODOs
**Tests** : Tests manuels

---

## Estimation totale

- **P0** : 8-12h (build fixes + sécurité critique)
- **P1** : 8-12h (bugs fréquents, dette bloquante)
- **P2** : 6-10h (qualité, maintenabilité)
- **P3** : 2-4h (cosmétique)

**Total** : **24-38h** de travail (3-5 jours développeur)

---

## Dépendances externes

### Backend Go (`veza-backend-api`)

- Support httpOnly cookies pour tokens (P0-002)
- Endpoint CSRF token (P0-005)
- Validation CSRF sur toutes les requêtes POST/PUT/DELETE (P0-005)

### Chat Server Rust (`veza-chat-server`)

- Support token JWT en header au lieu de query param (P1-006)

### Stream Server Rust (`veza-stream-server`)

- Aucune dépendance identifiée

---

## Notes finales

### Points positifs

✅ Architecture feature-based claire  
✅ Tests unitaires nombreux (189 fichiers)  
✅ Utilisation de Zod pour validation  
✅ ErrorBoundary React  
✅ Upload par chunks pour gros fichiers  
✅ WebSocket avec reconnexion intelligente  
✅ PWA support (service worker)  
✅ i18n (français/anglais)

### Points à surveiller

⚠️ Duplication de code (clients API)  
⚠️ Logs console partout (121 occurrences)  
⚠️ Types incomplets (Track/User)  
⚠️ Sécurité tokens (localStorage)

### Recommandations long terme

1. **Centraliser la gestion d'erreurs** : Créer un service d'erreurs global
2. **Logger structuré** : Implémenter un logger avec niveaux et corrélation
3. **Métriques** : Ajouter des métriques custom (erreurs, latence, etc.)
4. **Documentation** : Documenter les conventions de code et les patterns
5. **CI/CD** : Ajouter des checks automatiques (typecheck, lint, tests) dans CI

---

**Fin du rapport d'audit**

