veza/veza-backend-api/AUDIT_MODULE_VEZA_BACKEND_API_ULTRA_EXHAUSTIF.md

1333 lines
41 KiB
Markdown
Raw Normal View History

2025-12-16 16:23:49 +00:00
# Audit Module Veza Backend API — Ultra Exhaustif, Priorisé, Actionnable
**Date**: 2025-01-27
**Auditeur**: Auto (Cursor AI)
**Module**: `veza-backend-api` (Backend Go)
**Version**: 1.2.0
**Environnement**: Production-ready audit
---
## Table des Matières
1. [PHASE A — Cartographie](#phase-a--cartographie)
2. [PHASE B — Santé Technique](#phase-b--santé-technique)
3. [PHASE C — Sécurité](#phase-c--sécurité)
4. [PHASE D — Robustesse & Observabilité](#phase-d--robustesse--observabilité)
5. [PHASE E — Performance & Scalabilité](#phase-e--performance--scalabilité)
6. [PHASE F — Liste Exhaustive des Problèmes (Priorisés)](#phase-f--liste-exhaustive-des-problèmes-priorisés)
7. [PHASE G — Plan d'Exécution](#phase-g--plan-dexécution)
---
# PHASE A — Cartographie
## A.1 But du Module
**Veza Backend API** est le serveur HTTP principal de la plateforme Veza (audio collaborative). Il expose une API REST pour :
- **Authentification & Autorisation** : JWT, sessions, RBAC
- **Gestion Utilisateurs** : Profils, settings, completion
- **Gestion Tracks** : Upload, streaming, métadonnées, likes, partage
- **Playlists** : Création, collaboration, tracks
- **Marketplace** : Produits, commandes, téléchargements
- **Chat** : Génération de tokens JWT pour WebSocket (délégué au Chat Server Rust)
- **Audit & Monitoring** : Logs, métriques Prometheus, health checks
- **Webhooks** : Système d'événements asynchrones
**Rôle dans Veza** :
- **Backend Go** : API REST principale (port 8080)
- **Frontend React** : Consommateur de l'API REST
- **Chat Server Rust** : WebSocket (port 8081) — reçoit tokens JWT depuis `/api/v1/chat/token`
- **Stream Server Rust** : Streaming audio WebRTC (port 8082) — reçoit callbacks depuis `/api/v1/internal/tracks/:id/stream-ready`
## A.2 Entrées / Sorties
### APIs Exposées
**Base URL**: `http://localhost:8080` (configurable via `APP_PORT`, défaut: 8080)
**Routes Principales** (`/api/v1/`):
```
/api/v1/
├── /auth/*
│ ├── POST /register # Inscription
│ ├── POST /login # Connexion (rate limited)
│ ├── POST /refresh # Renouvellement token
│ ├── POST /verify-email # Vérification email
│ ├── POST /resend-verification # Renvoyer vérification
│ ├── GET /check-username # Vérifier disponibilité username
│ ├── POST /password/reset-request # Demande reset password
│ ├── POST /password/reset # Reset password
│ ├── POST /logout # Déconnexion (protégé)
│ └── GET /me # Profil utilisateur (protégé)
├── /users/*
│ ├── GET /:id # Profil utilisateur
│ ├── GET /by-username/:username # Profil par username
│ ├── PUT /:id # Mise à jour profil (protégé)
│ └── GET /:id/completion # Complétion profil (protégé)
├── /tracks/*
│ ├── GET / # Liste tracks
│ ├── GET /:id # Détails track
│ ├── GET /:id/stats # Statistiques track
│ ├── GET /:id/history # Historique track
│ ├── GET /:id/download # Téléchargement track
│ ├── GET /shared/:token # Track partagé (public)
│ ├── POST / # Upload track (protégé, creator role)
│ ├── PUT /:id # Mise à jour track (protégé)
│ ├── DELETE /:id # Suppression track (protégé)
│ ├── POST /:id/like # Like track (protégé)
│ ├── DELETE /:id/like # Unlike track (protégé)
│ ├── GET /:id/likes # Liste likes (protégé)
│ ├── POST /:id/share # Partager track (protégé)
│ └── DELETE /share/:id # Révoquer partage (protégé)
├── /playlists/* # Gestion playlists (protégé)
├── /chat/*
│ └── POST /token # Génération token WS (protégé)
├── /marketplace/*
│ ├── GET /products # Liste produits
│ ├── POST /products # Créer produit (protégé, creator role)
│ ├── POST /orders # Créer commande (protégé)
│ └── GET /download/:product_id # URL téléchargement (protégé)
├── /sessions/* # Gestion sessions (protégé)
├── /uploads/* # Upload fichiers (protégé, rate limited)
├── /audit/* # Audit logs (protégé)
├── /conversations/* # Chat rooms (protégé)
├── /webhooks/* # Webhooks (protégé)
├── /admin/* # Routes admin (protégé, admin role)
├── /health # Health check simple
├── /healthz # Liveness probe
├── /readyz # Readiness probe
├── /status # Status complet (DB, Redis, Chat, Stream)
└── /metrics # Prometheus metrics
```
**Formats**:
- **Request/Response**: JSON (`application/json`)
- **Auth**: JWT Bearer tokens (`Authorization: Bearer <token>`)
- **Content-Type**: `application/json`
- **File Upload**: `multipart/form-data` (tracks, thumbnails)
- **WebSocket**: Chat Server (Rust) - tokens JWT fournis par `/api/v1/chat/token`
### Schémas JSON Principaux
**User**:
```json
{
"id": "uuid-v4",
"email": "user@example.com",
"username": "username",
"role": "user",
"created_at": "2025-01-27T10:00:00Z",
"updated_at": "2025-01-27T10:00:00Z"
}
```
**Track**:
```json
{
"id": "uuid-v4",
"user_id": "uuid-v4",
"title": "Track Title",
"artist": "Artist Name",
"duration": 180.5,
"file_path": "/uploads/tracks/...",
"status": "ready"
}
```
**JWT Claims**:
```json
{
"sub": "uuid-v4",
"iss": "veza-api",
"aud": "veza-app",
"exp": 1234567890,
"iat": 1234567890,
"token_version": 1,
"role": "user"
}
```
## A.3 Dépendances Internes
**Structure**:
```
internal/
├── api/ # Routes et handlers HTTP
├── core/ # Business logic (auth, track, marketplace, social)
├── config/ # Configuration (env, validation, secrets)
├── database/ # DB connection, migrations, pool
├── handlers/ # HTTP handlers (legacy + modern)
├── middleware/ # Auth, CORS, rate limiting, recovery, metrics
├── models/ # GORM models (User, Track, Playlist, etc.)
├── repositories/ # Data access layer (GORM)
├── services/ # Business services (JWT, Session, Upload, etc.)
├── workers/ # Background jobs (webhooks, analytics)
├── metrics/ # Prometheus metrics
├── logging/ # Structured logging (zap)
└── validators/ # Input validation
```
**Packages Partagés**:
- `internal/errors` : Error handling uniforme
- `internal/response` : Réponses HTTP standardisées
- `internal/common` : Types et utilitaires communs
## A.4 Dépendances Externes
**Base de Données**:
- **PostgreSQL** : Base principale (GORM + `database/sql`)
- **Redis** : Cache, rate limiting, sessions (optionnel via `REDIS_ENABLE=false`)
**Services Externes**:
- **Chat Server** (Rust) : `http://localhost:8081` — WebSocket pour chat
- **Stream Server** (Rust) : `http://localhost:8082` — Streaming audio WebRTC
- **RabbitMQ** : Event bus (optionnel via `RABBITMQ_ENABLE=false`)
- **ClamAV** : Scan antivirus uploads (optionnel, rejette uploads si indisponible)
- **Sentry** : Error tracking (optionnel via `SENTRY_DSN`)
**Infrastructure**:
- **File System** : Uploads stockés localement (`UPLOAD_DIR`, défaut: `uploads`)
- **SMTP** : Envoi emails (vérification, reset password)
## A.5 Exécution
### Commandes Build/Run/Dev
**Build**:
```bash
make build # Compile pour OS courant
make build-linux # Compile pour Linux
```
**Run**:
```bash
make run # Build + run
make dev # Mode développement (go run)
```
**Tests**:
```bash
make test # Tests unitaires (sans integration)
make test-coverage # Tests avec couverture
make test-integration # Tests d'intégration (requiert Docker)
```
**Qualité**:
```bash
make lint # golangci-lint
make vet # go vet
make security # gosec + govulncheck
```
### Configuration
**Variables d'Environnement Requises**:
```bash
JWT_SECRET=<32+ chars> # REQUIS - Secret JWT (min 32 chars)
DATABASE_URL=postgres://... # REQUIS - URL PostgreSQL
REDIS_URL=redis://... # Optionnel (défaut: redis://localhost:6379)
REDIS_ENABLE=true # Optionnel (défaut: true)
RABBITMQ_URL=amqp://... # Optionnel
RABBITMQ_ENABLE=true # Optionnel (défaut: true)
APP_PORT=8080 # Optionnel (défaut: 8080)
APP_ENV=production # development|staging|production
CORS_ALLOWED_ORIGINS=https://... # REQUIS en production
```
**Fichiers Config**:
- `.env` : Variables d'environnement (optionnel, chargé via `godotenv`)
- `.env.{APP_ENV}` : Variables spécifiques à l'environnement
- `migrations/*.sql` : Migrations SQL (exécutées au démarrage)
**Docker**:
```bash
make docker-build # Build image
make docker-run # Run container
```
**Health Checks**:
- `/health` : Health check simple
- `/healthz` : Liveness probe (Kubernetes)
- `/readyz` : Readiness probe (DB, Redis, RabbitMQ)
- `/status` : Status détaillé (DB, Redis, Chat Server, Stream Server)
## A.6 Points d'Intégration
### Contrats d'API
**Frontend React**:
- Consomme `/api/v1/*` avec JWT Bearer tokens
- Headers requis: `Authorization: Bearer <token>`
- Content-Type: `application/json`
**Chat Server (Rust)**:
- Reçoit tokens JWT depuis `/api/v1/chat/token`
- Valide tokens avec `CHAT_JWT_SECRET` (ou `JWT_SECRET` si non défini)
- WebSocket endpoint: `ws://localhost:8081/ws`
**Stream Server (Rust)**:
- Reçoit callbacks depuis `/api/v1/internal/tracks/:id/stream-ready`
- Endpoint interne (pas de auth JWT, validation par IP/secret si nécessaire)
### Auth
**JWT**:
- Algorithme: `HS256` (HMAC)
- Claims: `sub` (user_id UUID), `iss` (veza-api), `aud` (veza-app), `exp`, `iat`, `token_version`, `role`
- Validation stricte: `alg`, `iss`, `aud`, `exp` vérifiés
- Token version: Vérifiée contre DB pour révocation immédiate
**Sessions**:
- Stockées en DB (`user_sessions` table)
- Hash du token (pas token en clair)
- Validation obligatoire dans `AuthMiddleware.authenticate()`
**RBAC**:
- Rôles: `user`, `admin`, `creator`, `premium`, `artist`, `producer`, `label`
- Permissions: Tables `permissions`, `role_permissions`, `user_roles`
- Middleware: `RequireAdmin()`, `RequirePermission()`, `RequireContentCreatorRole()`
### Schéma DB / UUID
**IDs**:
- **UUID v4** : Tous les IDs utilisent `uuid.UUID` (migration depuis `int64` complétée)
- Tables: `users`, `tracks`, `playlists`, `sessions`, `rooms`, `messages`, etc.
**Conventions**:
- `id` : UUID PRIMARY KEY
- `user_id` : UUID FOREIGN KEY vers `users.id`
- `created_at`, `updated_at` : TIMESTAMP
- `deleted_at` : TIMESTAMP NULL (soft delete)
---
# PHASE B — Santé Technique
## B.1 Build Status
**✅ BUILD OK** :
- Compilation réussie : `go build ./cmd/api/main.go`
- Pas d'erreurs de compilation
- Go version : 1.23.8 (déclaré dans `go.mod`)
**⚠️ WARNINGS** :
- Aucun warning critique identifié
## B.2 Tests
**Couverture** :
- Tests unitaires : ✅ OK (tous passent)
- Tests d'intégration : ✅ OK (avec Docker/testcontainers)
- Couverture estimée : ~92% (d'après `coverage.out`)
**Résultats** :
```bash
ok veza-backend-api/internal/common 0.014s
ok veza-backend-api/internal/config 0.053s
ok veza-backend-api/internal/core/track 1.247s
ok veza-backend-api/internal/database 0.060s
ok veza-backend-api/internal/email 0.005s
ok veza-backend-api/internal/errors 0.010s
ok veza-backend-api/internal/handlers 0.064s
ok veza-backend-api/internal/jobs 0.355s
ok veza-backend-api/internal/logging 1.237s
ok veza-backend-api/internal/metrics 0.030s
ok veza-backend-api/internal/middleware 9.378s
ok veza-backend-api/internal/models 0.564s
ok veza-backend-api/internal/monitoring 0.259s
ok veza-backend-api/internal/repositories 0.238s
ok veza-backend-api/internal/services 32.491s
ok veza-backend-api/internal/testutils 57.958s
ok veza-backend-api/internal/validators 0.030s
ok veza-backend-api/internal/workers 4.024s
```
**⚠️ GAPS** :
- **P2-TEST-001** : Pas de tests pour certains handlers (voir section F)
- **P2-TEST-002** : Tests d'intégration E2E manquants (upload flow complet)
## B.3 Linters & Qualité
**golangci-lint** :
- Configuration : Présente (`.golangci.yml` probablement)
- Commandes : `make lint`
**go vet** :
- ✅ Aucune erreur critique
**⚠️ WARNINGS** :
- Aucun warning critique identifié dans l'analyse statique
## B.4 Gestion des Erreurs
**✅ BONNES PRATIQUES** :
- Error wrapping : `fmt.Errorf("...: %w", err)` utilisé
- Error types : `internal/errors` avec codes uniformes
- HTTP status : Réponses standardisées via `internal/response`
- Panic recovery : Middleware `Recovery()` présent
**⚠️ PROBLÈMES** :
- **P1-ERROR-001** : Certains handlers retournent 500 au lieu de 400 pour erreurs de validation (voir section F)
## B.5 Conventions
**✅ COHÉRENCE** :
- Naming : Cohérent (camelCase pour variables, PascalCase pour exports)
- Structure : Séparation claire (handlers, services, repositories)
- Imports : Organisés
**⚠️ INCOHÉRENCES** :
- **P2-CONV-001** : Mélange handlers legacy (`internal/handlers/`) et modern (`internal/core/*/handler.go`) (voir section F)
---
# PHASE C — Sécurité
## C.1 Secrets & Configuration
**✅ BONNES PRATIQUES** :
- Secrets masqués dans logs : `SecretsProvider` présent (`internal/config/secrets.go`)
- Validation config : `Config.Validate()` + `ValidateForEnvironment()`
- Variables requises : `getEnvRequired()` retourne erreur (pas panic)
**⚠️ RISQUES** :
- **P0-SEC-001** : `.env` peut être committé (vérifier `.gitignore`)
- **P1-SEC-001** : `JWT_SECRET` doit être ≥ 32 chars (validé, mais pas de rotation automatique)
## C.2 Authentification & Autorisation
### JWT Validation
**✅ SÉCURISÉ** :
- Algorithme : `HS256` (HMAC) — sécurisé
- Validation signature : `jwt.ParseWithClaims()` avec secret
- Validation expiration : `exp` claim vérifié
- Validation claims : `sub`, `iss`, `aud`, `exp`, `iat` vérifiés
- Validation algorithme : `alg` header vérifié (HS256 uniquement) — **FIXÉ** (`internal/services/jwt_service.go:121-127`)
- Token version : Vérifiée dans `AuthMiddleware.authenticate()` (`internal/middleware/auth.go:119-129`)
**⚠️ RISQUES** :
- **P1-SEC-002** : Pas de rotation automatique JWT secret (voir section F)
### RBAC
**✅ FONCTIONNEL** :
- `RequireAdmin()` : Utilise `PermissionService.HasRole(..., "admin")`
- `RequirePermission()` : Utilise `PermissionService.HasPermission()`
- `RequireContentCreatorRole()` : Vérifie rôles creator/premium/admin/artist/producer/label
- Tables DB : `permissions`, `role_permissions`, `user_roles` existent
**Routes Protégées** :
-`/api/v1/admin/*` : Protégé par `RequireAdmin()`
-`/api/v1/tracks` (POST) : Protégé par `RequireContentCreatorRole()`
-`/api/v1/marketplace/products` (POST) : Protégé par `RequireContentCreatorRole()`
**⚠️ RISQUES** :
- **P1-SEC-003** : Pas de vérification ownership sur certaines routes (voir section F)
- Exemple: `/api/v1/users/:id` (PUT) — vérifier ownership ou admin
- Exemple: `/api/v1/tracks/:id` (DELETE) — vérifier ownership ou admin
### Sessions
**✅ SÉCURISÉ** :
- Sessions stockées en DB avec hash du token (pas token en clair)
- Validation session obligatoire dans `AuthMiddleware.authenticate()`
- Vérification `expires_at` et `revoked_at`
- Vérification user_id match entre token et session
**⚠️ RISQUES** :
- **P2-SEC-001** : Pas de rotation automatique sessions (TTL fixe)
- **P2-SEC-002** : Pas de détection sessions suspectes (multiples IPs, etc.)
## C.3 Injection & Validation
### SQL Injection
**✅ PROTÉGÉ** :
- GORM utilisé (parametrized queries par défaut)
- Prepared statements présents (`internal/database/prepared_statements.go`)
- Pas de raw queries avec concaténation string identifiées
- Pas de `SELECT *` trouvé (bonne pratique)
**Vérification** :
- 29+ fichiers avec requêtes SQL analysés
- Toutes utilisent paramètres (`$1`, `$2`, etc.) ou GORM
**Risque** : ✅ **FAIBLE** — Bien protégé
### Input Validation
**Implémentation** :
-`go-playground/validator/v10` présent
- ✅ Validateurs: `EmailValidator`, `PasswordValidator`
**⚠️ RISQUES** :
- **P1-SEC-004** : Validation pas utilisée partout (voir section F)
- Exemples: Handlers peuvent accepter input non validé
- Impact: Données invalides en DB, risque injection indirecte
### Sanitization XSS
**⚠️ RISQUES** :
- **P2-SEC-003** : Pas de sanitization XSS systématique
- Impact: XSS possible si données affichées côté frontend sans échappement
### File Upload
**✅ VALIDÉ** :
- Validation type MIME (`UploadValidator`)
- Validation taille fichier
- Scan antivirus ClamAV mentionné (`github.com/dutchcoders/go-clamd`)
**⚠️ RISQUES** :
- **P1-SEC-005** : ClamAV peut être indisponible (uploads rejetés, mais pas de fallback)
- Fichier: `internal/services/upload_validator.go`
## C.4 CORS & Headers
**✅ CONFIGURÉ** :
- CORS middleware : `middleware.CORS()` présent
- Security headers : `middleware.SecurityHeaders()` (HSTS, CSP, etc.)
- Validation production : CORS wildcard interdit en production
**⚠️ RISQUES** :
- **P0-SEC-002** : CORS strict en production (vide = reject all) — peut bloquer frontend si mal configuré (voir section F)
## C.5 Dépendances Vulnérables
**Vérification** :
- `govulncheck` : Commandes présentes (`make security`, `make vulncheck`)
- `gosec` : Commandes présentes (`make security`)
**⚠️ ACTION REQUISE** :
- **P1-SEC-006** : Exécuter `govulncheck` régulièrement (CI/CD) (voir section F)
---
# PHASE D — Robustesse & Observabilité
## D.1 Logs
**✅ STRUCTURÉS** :
- Logger : `zap` (structured logging)
- Corrélation : `RequestID` middleware présent
- Niveaux : DEBUG, INFO, WARN, ERROR (configurable via `LOG_LEVEL`)
**⚠️ GAPS** :
- **P2-OBS-001** : Pas de `trace_id` (OpenTelemetry) — seulement `request_id` (voir section F)
## D.2 Metrics
**✅ PROMETHEUS** :
- Metrics endpoint : `/metrics` (Prometheus format)
- Metrics middleware : `middleware.Metrics()` présent
- DB pool stats : `metrics.StartDBPoolStatsCollector()` présent
**Métriques Exposées** :
- HTTP requests (count, duration)
- Error counts (par type, endpoint)
- DB pool stats (open, idle, in-use connections)
**⚠️ GAPS** :
- **P2-OBS-002** : Pas de métriques business (tracks uploaded, users registered, etc.) (voir section F)
## D.3 Health Checks
**✅ COMPLETS** :
- `/health` : Health check simple
- `/healthz` : Liveness probe
- `/readyz` : Readiness probe (DB, Redis, RabbitMQ)
- `/status` : Status détaillé (DB, Redis, Chat Server, Stream Server)
**✅ ROBUSTES** :
- Timeouts : 5s pour health checks
- Graceful degradation : Service démarre même si Redis/RabbitMQ indisponibles (mode dégradé)
## D.4 Timeouts & Retries
**✅ CONFIGURÉS** :
- Handler timeout : `middleware.Timeout()` global (30s par défaut, configurable via `HANDLER_TIMEOUT`)
- DB retries : `DBMaxRetries` (5 par défaut), `DBRetryInterval` (5s par défaut)
- RabbitMQ retries : `RabbitMQMaxRetries` (3 par défaut), `RabbitMQRetryInterval` (2s par défaut)
**⚠️ GAPS** :
- **P2-OBS-003** : Pas de circuit breakers pour services externes (Chat Server, Stream Server) (voir section F)
## D.5 Gestion de Charge
**✅ RATE LIMITING** :
- Global : `RateLimiter` (Redis) ou `SimpleRateLimiter` (in-memory)
- Par endpoint : `EndpointLimiter` (login: 5 attempts/min par défaut)
- Upload : `UploadRateLimit` middleware présent
**✅ DB POOL** :
- MaxOpenConns : 25 (configurable)
- MaxIdleConns : 10 (configurable)
- MaxLifetime : 5 minutes (configurable)
- MaxIdleTime : 1 minute (configurable)
**⚠️ GAPS** :
- **P2-OBS-004** : Pas de backpressure pour uploads (voir section F)
## D.6 Migrations
**✅ ROBUSTES** :
- Migrations SQL : Exécutées dans transactions (rollback automatique en cas d'erreur)
- Extensions : Détection `CREATE EXTENSION` (exécution hors transaction)
- Schema tracking : Table `schema_migrations` pour tracking
**⚠️ GAPS** :
- **P2-OBS-005** : Pas de rollback automatique migrations (down migrations non exécutées automatiquement) (voir section F)
---
# PHASE E — Performance & Scalabilité
## E.1 Hotspots Évidents
**✅ OPTIMISÉS** :
- Prepared statements : `PreparedStatementManager` présent
- DB pool : Configuré (25 max open, 10 max idle)
- Pas de `SELECT *` : Bonne pratique respectée
**⚠️ OPTIMISATIONS POSSIBLES** :
- **P2-PERF-001** : N+1 queries possibles dans certains services (voir section F)
- **P2-PERF-002** : Pas de pagination sur certaines listes (voir section F)
## E.2 Streaming
**✅ CONFIGURÉ** :
- Chunked upload : Support présent (`/api/v1/tracks/initiate`, `/chunk`, `/complete`)
- Redis : Utilisé pour tracking chunks (optionnel)
**⚠️ GAPS** :
- **P2-PERF-003** : Pas de buffering configuré pour streaming (voir section F)
## E.3 Go-Specific
**✅ BONNES PRATIQUES** :
- Context propagation : Utilisé (`context.Context` passé partout)
- Goroutines : Pas de leaks identifiés (timeouts présents)
- DB pool : Configuré correctement
**⚠️ GAPS** :
- **P2-PERF-004** : Pas de profiling automatique (pprof) (voir section F)
---
# PHASE F — Liste Exhaustive des Problèmes (Priorisés)
## Définition des Priorités
- **P0** : Faille sécurité exploitable / perte de données / crash prod / corruption / auth bypass / build cassé
- **P1** : Bugs fréquents / dette bloquante / erreurs de contrat inter-modules / manque de tests critiques
- **P2** : Qualité, maintenabilité, perf non critique, DX
- **P3** : Cosmétique, refactors non urgents
---
## P0 — Critique (Sécurité / Stabilité)
### MOD-P0-001 : CORS Strict en Production Peut Bloquer Frontend
**Impact** :
- Si `CORS_ALLOWED_ORIGINS` est vide en production, **TOUS** les CORS requests sont rejetés
- Frontend ne peut pas accéder à l'API → **Service inaccessible**
- Scénario: Déploiement production sans config CORS → service down
**Preuve** :
- Fichier: `internal/config/config.go:625-643`
- Code:
```go
case EnvProduction:
if len(c.CORSOrigins) == 0 {
return fmt.Errorf("CORS_ALLOWED_ORIGINS is required in production...")
}
```
- Fichier: `internal/api/router.go:75-84`
- Code:
```go
if len(r.config.CORSOrigins) == 0 {
r.logger.Warn("CORS origins not configured - strict mode enabled: ALL CORS requests will be rejected.")
}
```
**Cause Racine** :
- Validation fail-fast en production (bon), mais message d'erreur peut être ignoré si config chargée depuis fichier `.env` manquant
**Fix Minimal** :
1. Ajouter check au démarrage: si `APP_ENV=production` et `CORS_ALLOWED_ORIGINS` vide → **FATAL ERROR** avec message clair
2. Documenter dans README: `CORS_ALLOWED_ORIGINS` REQUIS en production
**Plan de Validation** :
```bash
# Test 1: Production sans CORS → doit fail
APP_ENV=production CORS_ALLOWED_ORIGINS="" go run ./cmd/api/main.go
# Attendu: FATAL ERROR avec message clair
# Test 2: Production avec CORS → doit démarrer
APP_ENV=production CORS_ALLOWED_ORIGINS="https://app.veza.com" go run ./cmd/api/main.go
# Attendu: Service démarre OK
```
**Effet de Bord** :
- Aucun (améliore la robustesse)
**Effort** : S (1h)
---
### MOD-P0-002 : Validation JWT Secret Length Manquante au Runtime
**Impact** :
- Si `JWT_SECRET` < 32 chars, tokens peuvent être crackés (brute force)
- **Auth bypass possible** si secret faible
**Preuve** :
- Fichier: `internal/config/config.go:687-690`
- Code:
```go
if err := validator.ValidateSecretLength(c.JWTSecret, 32); err != nil {
return fmt.Errorf("JWT_SECRET validation failed: %w", err)
}
```
-**DÉJÀ VALIDÉ** dans `Config.Validate()`
**Cause Racine** :
- Validation présente, mais pas de test d'intégration pour vérifier que le service refuse de démarrer avec secret < 32 chars
**Fix Minimal** :
1. Ajouter test d'intégration: Service doit refuser de démarrer si `JWT_SECRET` < 32 chars
2. Documenter dans README: `JWT_SECRET` doit être ≥ 32 chars
**Plan de Validation** :
```bash
# Test: Secret < 32 chars → doit fail
JWT_SECRET="short" go run ./cmd/api/main.go
# Attendu: FATAL ERROR "JWT_SECRET validation failed: secret must be at least 32 characters"
```
**Effet de Bord** :
- Aucun (améliore la sécurité)
**Effort** : S (30min)
---
### MOD-P0-003 : Pas de Validation Ownership sur Routes DELETE/PUT
**Impact** :
- Utilisateur peut supprimer/modifier ressources d'autres utilisateurs si ID deviné
- **Perte de données** / **Corruption données**
**Preuve** :
- Fichier: `internal/api/router.go:307` (PUT `/api/v1/users/:id`)
- Fichier: `internal/api/router.go:372` (DELETE `/api/v1/tracks/:id`)
- Code: Pas de vérification `user_id == resource.user_id || user.role == "admin"`
**Cause Racine** :
- Handlers ne vérifient pas ownership avant modification/suppression
**Fix Minimal** :
1. Ajouter middleware `RequireOwnershipOrAdmin(resourceType string)` qui vérifie:
- Si `user_id == resource.user_id` → OK
- Si `user.role == "admin"` → OK
- Sinon → 403 Forbidden
2. Appliquer sur routes:
- `PUT /api/v1/users/:id`
- `DELETE /api/v1/tracks/:id`
- `PUT /api/v1/tracks/:id`
- `DELETE /api/v1/playlists/:id`
- `PUT /api/v1/playlists/:id`
**Plan de Validation** :
```bash
# Test 1: User A essaie de modifier User B → 403
curl -X PUT /api/v1/users/{user_b_id} -H "Authorization: Bearer {user_a_token}" -d '{"username":"hacked"}'
# Attendu: 403 Forbidden
# Test 2: User A modifie ses propres données → 200
curl -X PUT /api/v1/users/{user_a_id} -H "Authorization: Bearer {user_a_token}" -d '{"username":"new_username"}'
# Attendu: 200 OK
# Test 3: Admin modifie User B → 200
curl -X PUT /api/v1/users/{user_b_id} -H "Authorization: Bearer {admin_token}" -d '{"username":"admin_updated"}'
# Attendu: 200 OK
```
**Effet de Bord** :
- Risque de régression si middleware mal appliqué (tester tous les endpoints)
**Effort** : M (4h)
---
## P1 — Important (Bugs / Dette)
### MOD-P1-001 : Validation Input Non Systématique
**Impact** :
- Handlers peuvent accepter données invalides → corruption DB, injection indirecte
**Preuve** :
- Fichier: `internal/handlers/*.go` (plusieurs handlers)
- Code: Pas de validation struct tags (`validate:"required,email"`) sur tous les DTOs
**Cause Racine** :
- Validators présents (`EmailValidator`, `PasswordValidator`), mais pas utilisés partout
**Fix Minimal** :
1. Ajouter struct tags `validate` sur tous les DTOs (`internal/dto/*.go`)
2. Ajouter middleware `ValidateRequest()` qui valide automatiquement les DTOs
3. Appliquer sur tous les handlers POST/PUT
**Plan de Validation** :
```bash
# Test: Envoyer données invalides → 400
curl -X POST /api/v1/auth/register -d '{"email":"invalid","password":"123"}'
# Attendu: 400 Bad Request avec détails validation
```
**Effet de Bord** :
- Risque de casser endpoints existants si validation trop stricte (tester tous les endpoints)
**Effort** : M (6h)
---
### MOD-P1-002 : ClamAV Indisponible → Uploads Rejetés (Pas de Fallback)
**Impact** :
- Si ClamAV down, **TOUS** les uploads sont rejetés
- Service devient inutilisable pour uploads
**Preuve** :
- Fichier: `internal/services/upload_validator.go`
- Code: Si ClamAV indisponible, `NewUploadValidator()` retourne erreur → uploads rejetés
**Cause Racine** :
- Pas de mode dégradé: ClamAV requis pour uploads
**Fix Minimal** :
1. Ajouter config `CLAMAV_REQUIRED=false` (défaut: `true`)
2. Si `CLAMAV_REQUIRED=false` et ClamAV indisponible → logger warning mais accepter uploads
3. Documenter: En production, ClamAV doit être disponible
**Plan de Validation** :
```bash
# Test 1: ClamAV down, CLAMAV_REQUIRED=true → uploads rejetés
# Test 2: ClamAV down, CLAMAV_REQUIRED=false → uploads acceptés (avec warning)
```
**Effet de Bord** :
- Risque sécurité si ClamAV désactivé (documenter clairement)
**Effort** : S (2h)
---
### MOD-P1-003 : Pas de Tests d'Intégration E2E (Upload Flow)
**Impact** :
- Bugs dans flow upload complet non détectés avant production
**Preuve** :
- Fichier: `tests/integration/upload_flow_test.go` (existe mais peut être incomplet)
- Code: Vérifier que flow complet (initiate → chunk → complete) fonctionne
**Cause Racine** :
- Tests unitaires présents, mais tests E2E manquants
**Fix Minimal** :
1. Ajouter test E2E: Upload flow complet (initiate → chunk → complete → download)
2. Ajouter test E2E: Upload avec ClamAV scan
3. Ajouter test E2E: Upload avec erreur (chunk manquant, etc.)
**Plan de Validation** :
```bash
make test-integration
# Attendu: Tests E2E upload passent
```
**Effet de Bord** :
- Aucun (améliore la qualité)
**Effort** : M (4h)
---
### MOD-P1-004 : Handlers Retournent 500 au Lieu de 400 pour Erreurs Validation
**Impact** :
- Erreurs client (400) retournées comme erreurs serveur (500) → confusion, métriques incorrectes
**Preuve** :
- Fichier: `internal/handlers/*.go` (plusieurs handlers)
- Code: `response.InternalServerError(c, ...)` au lieu de `response.BadRequest(c, ...)`
**Cause Racine** :
- Pas de distinction claire entre erreurs client (400) et serveur (500)
**Fix Minimal** :
1. Auditer tous les handlers: Remplacer `InternalServerError` par `BadRequest` pour erreurs validation
2. Utiliser `InternalServerError` uniquement pour erreurs DB/IO inattendues
**Plan de Validation** :
```bash
# Test: Envoyer données invalides → 400 (pas 500)
curl -X POST /api/v1/auth/register -d '{"email":"invalid"}'
# Attendu: 400 Bad Request
```
**Effet de Bord** :
- Risque de casser clients existants si changement de status code (vérifier clients)
**Effort** : S (2h)
---
### MOD-P1-005 : Pas de Rotation Automatique JWT Secret
**Impact** :
- Si secret compromis, tous les tokens restent valides jusqu'à expiration
- **Auth bypass** possible même après changement secret
**Preuve** :
- Fichier: `internal/services/jwt_service.go`
- Code: Pas de mécanisme de rotation automatique
**Cause Racine** :
- Secret fixe, pas de versioning
**Fix Minimal** :
1. Ajouter `JWT_SECRET_VERSION` (entier, défaut: 1)
2. Inclure `secret_version` dans JWT claims
3. Valider `secret_version` dans `ValidateToken()`
4. Documenter: Rotation manuelle (changer secret + incrémenter version)
**Plan de Validation** :
```bash
# Test: Token avec ancien secret_version → rejeté
```
**Effet de Bord** :
- Tous les tokens existants invalidés après rotation (documenter migration)
**Effort** : M (4h)
---
### MOD-P1-006 : Pas de Circuit Breakers pour Services Externes
**Impact** :
- Si Chat Server ou Stream Server down, API peut être ralentie (timeouts)
- **Cascade failures** possibles
**Preuve** :
- Fichier: `internal/services/stream_service.go`
- Code: Pas de circuit breaker (gobreaker présent dans `go.mod` mais non utilisé)
**Cause Racine** :
- Appels HTTP directs sans protection
**Fix Minimal** :
1. Ajouter circuit breaker (gobreaker) pour Chat Server et Stream Server
2. Config: `CIRCUIT_BREAKER_MAX_REQUESTS=5`, `CIRCUIT_BREAKER_INTERVAL=60s`, `CIRCUIT_BREAKER_TIMEOUT=30s`
3. En cas d'ouverture circuit: Retourner 503 Service Unavailable avec message clair
**Plan de Validation** :
```bash
# Test: Stream Server down → circuit ouvre après 5 échecs → 503
```
**Effet de Bord** :
- Risque de faux positifs (circuit ouvre trop vite) → ajuster config
**Effort** : M (4h)
---
## P2 — Qualité / Maintenabilité
### MOD-P2-001 : Mélange Handlers Legacy et Modern
**Impact** :
- Confusion pour développeurs (deux patterns différents)
- Maintenance difficile
**Preuve** :
- Fichiers: `internal/handlers/*.go` (legacy) vs `internal/core/*/handler.go` (modern)
- Code: Deux patterns différents
**Cause Racine** :
- Migration progressive non complétée
**Fix Minimal** :
1. Documenter: Pattern moderne (`internal/core/*/handler.go`) est la référence
2. Migrer progressivement handlers legacy vers pattern moderne
3. Marquer handlers legacy comme `@deprecated`
**Plan de Validation** :
- Aucun (refactor progressif)
**Effet de Bord** :
- Risque de régression si migration mal faite (tester chaque handler migré)
**Effort** : L (2 jours)
---
### MOD-P2-002 : Pas de Trace ID (OpenTelemetry)
**Impact** :
- Debugging difficile (pas de corrélation entre services)
**Preuve** :
- Fichier: `internal/middleware/request_id.go`
- Code: Seulement `request_id` (local), pas de `trace_id` (distributed)
**Cause Racine** :
- OpenTelemetry non intégré
**Fix Minimal** :
1. Ajouter OpenTelemetry SDK
2. Générer `trace_id` dans middleware
3. Logger `trace_id` dans tous les logs
**Plan de Validation** :
```bash
# Test: Vérifier trace_id dans logs
```
**Effet de Bord** :
- Aucun (améliore l'observabilité)
**Effort** : M (4h)
---
### MOD-P2-003 : Pas de Métriques Business
**Impact** :
- Pas de visibilité sur métriques business (tracks uploaded, users registered, etc.)
**Preuve** :
- Fichier: `internal/metrics/*.go`
- Code: Seulement métriques techniques (HTTP, DB, errors)
**Cause Racine** :
- Métriques business non implémentées
**Fix Minimal** :
1. Ajouter métriques Prometheus:
- `veza_tracks_uploaded_total`
- `veza_users_registered_total`
- `veza_playlists_created_total`
- `veza_uploads_failed_total` (par raison: ClamAV, validation, etc.)
2. Exposer via `/metrics`
**Plan de Validation** :
```bash
# Test: Upload track → métrique incrémentée
curl http://localhost:8080/metrics | grep veza_tracks_uploaded_total
```
**Effet de Bord** :
- Aucun (améliore l'observabilité)
**Effort** : S (2h)
---
### MOD-P2-004 : Pas de Pagination sur Certaines Listes
**Impact** :
- Performance dégradée sur grandes listes (tracks, playlists, etc.)
**Preuve** :
- Fichier: `internal/handlers/*.go` (plusieurs handlers de liste)
- Code: Pas de pagination (ou pagination optionnelle)
**Cause Racine** :
- Pagination non systématique
**Fix Minimal** :
1. Ajouter pagination obligatoire sur toutes les listes:
- `GET /api/v1/tracks?page=1&limit=20`
- `GET /api/v1/playlists?page=1&limit=20`
2. Limite max: 100 items par page
3. Retourner `total`, `page`, `limit` dans réponse
**Plan de Validation** :
```bash
# Test: Liste sans pagination → 400
curl /api/v1/tracks
# Attendu: 400 Bad Request "pagination required"
# Test: Liste avec pagination → 200
curl /api/v1/tracks?page=1&limit=20
# Attendu: 200 OK avec pagination metadata
```
**Effet de Bord** :
- Risque de casser clients existants (ajouter pagination optionnelle d'abord, puis obligatoire)
**Effort** : M (4h)
---
### MOD-P2-005 : Pas de Backpressure pour Uploads
**Impact** :
- Uploads simultanés peuvent saturer serveur (mémoire, CPU)
**Preuve** :
- Fichier: `internal/handlers/upload.go`
- Code: Pas de limite uploads simultanés
**Cause Racine** :
- Rate limiting présent, mais pas de backpressure
**Fix Minimal** :
1. Ajouter semaphore (limite uploads simultanés: 10 par défaut)
2. Si limite atteinte: Retourner 503 Service Unavailable avec `Retry-After` header
3. Config: `MAX_CONCURRENT_UPLOADS=10`
**Plan de Validation** :
```bash
# Test: 11 uploads simultanés → 11ème reçoit 503
```
**Effet de Bord** :
- Risque de rejets légitimes si limite trop basse (ajuster config)
**Effort** : S (2h)
---
### MOD-P2-006 : Pas de Profiling Automatique (pprof)
**Impact** :
- Debugging performance difficile
**Preuve** :
- Fichier: `cmd/api/main.go`
- Code: Pas d'endpoint `/debug/pprof`
**Cause Racine** :
- pprof non activé
**Fix Minimal** :
1. Ajouter import `_ "net/http/pprof"`
2. Exposer endpoint `/debug/pprof` (protégé par auth admin en production)
3. Documenter: Utilisation pprof pour debugging
**Plan de Validation** :
```bash
# Test: Accéder /debug/pprof → 200 (ou 401 si non admin)
```
**Effet de Bord** :
- Risque sécurité si endpoint exposé publiquement (protéger par auth admin)
**Effort** : S (1h)
---
## P3 — Cosmétique / Refactors
### MOD-P3-001 : README.md Est Celui de golang-migrate
**Impact** :
- Confusion pour nouveaux développeurs
**Preuve** :
- Fichier: `README.md`
- Code: Contenu de golang-migrate, pas de Veza
**Cause Racine** :
- README non mis à jour
**Fix Minimal** :
1. Remplacer README.md par documentation Veza:
- Description projet
- Installation
- Configuration
- API endpoints
- Tests
- Déploiement
**Plan de Validation** :
- Aucun (documentation)
**Effet de Bord** :
- Aucun
**Effort** : S (1h)
---
### MOD-P3-002 : Pas de Documentation OpenAPI/Swagger Complète
**Impact** :
- Développeurs frontend doivent deviner contrats API
**Preuve** :
- Fichier: `docs/swagger.json` (peut être incomplet)
- Code: Swagger présent (`/swagger/*any`), mais peut manquer endpoints
**Cause Racine** :
- Documentation Swagger non maintenue
**Fix Minimal** :
1. Ajouter annotations Swagger sur tous les handlers
2. Générer `docs/swagger.json` avec `swag init`
3. Vérifier que tous les endpoints sont documentés
**Plan de Validation** :
```bash
# Test: Accéder /swagger/index.html → tous endpoints visibles
```
**Effet de Bord** :
- Aucun (améliore la DX)
**Effort** : M (4h)
---
# PHASE G — Plan d'Exécution
## Checklist P0 (Ordre Strict)
1. **MOD-P0-001** : CORS Strict en Production (1h)
- Ajouter check fail-fast au démarrage
- Documenter dans README
2. **MOD-P0-002** : Validation JWT Secret Length (30min)
- Ajouter test d'intégration
- Documenter dans README
3. **MOD-P0-003** : Validation Ownership Routes (4h)
- Créer middleware `RequireOwnershipOrAdmin()`
- Appliquer sur routes DELETE/PUT
- Tests d'intégration
## Checklist P1 (Par Lots Cohérents)
### Lot 1 : Validation & Erreurs (8h)
- **MOD-P1-001** : Validation Input Systématique (6h)
- **MOD-P1-004** : Handlers 500 → 400 (2h)
### Lot 2 : Uploads & ClamAV (6h)
- **MOD-P1-002** : ClamAV Fallback (2h)
- **MOD-P1-003** : Tests E2E Upload (4h)
### Lot 3 : Sécurité & Observabilité (8h)
- **MOD-P1-005** : Rotation JWT Secret (4h)
- **MOD-P1-006** : Circuit Breakers (4h)
## Quick Wins (≤ 1h chacun)
1. **MOD-P3-001** : README.md (1h)
2. **MOD-P2-006** : pprof (1h)
3. **MOD-P2-003** : Métriques Business (2h)
## Tests à Ajouter en Priorité
1. **Tests d'intégration E2E Upload Flow** (MOD-P1-003)
2. **Tests ownership validation** (MOD-P0-003)
3. **Tests CORS fail-fast** (MOD-P0-001)
4. **Tests ClamAV fallback** (MOD-P1-002)
## PR Plan
### PR 1 : P0 Security Fixes (1 jour)
- **Titre**: `fix(security): CORS fail-fast + JWT secret validation + ownership checks`
- **Issues**: MOD-P0-001, MOD-P0-002, MOD-P0-003
- **Tests**: Tests d'intégration pour chaque fix
- **Review**: Security review requis
### PR 2 : P1 Validation & Errors (1 jour)
- **Titre**: `feat(validation): Input validation systématique + correct HTTP status codes`
- **Issues**: MOD-P1-001, MOD-P1-004
- **Tests**: Tests unitaires + intégration
- **Review**: Code review standard
### PR 3 : P1 Uploads & ClamAV (1 jour)
- **Titre**: `feat(uploads): ClamAV fallback + E2E tests`
- **Issues**: MOD-P1-002, MOD-P1-003
- **Tests**: Tests E2E upload flow
- **Review**: Code review standard
### PR 4 : P1 Security & Observability (1 jour)
- **Titre**: `feat(security): JWT secret rotation + circuit breakers`
- **Issues**: MOD-P1-005, MOD-P1-006
- **Tests**: Tests unitaires
- **Review**: Code review standard
### PR 5 : P2 Quick Wins (0.5 jour)
- **Titre**: `docs: README + pprof + business metrics`
- **Issues**: MOD-P3-001, MOD-P2-006, MOD-P2-003
- **Tests**: Aucun (documentation + observabilité)
- **Review**: Code review standard
### PR 6 : P2 Quality Improvements (2 jours)
- **Titre**: `feat(quality): Trace ID + pagination + backpressure`
- **Issues**: MOD-P2-002, MOD-P2-004, MOD-P2-005
- **Tests**: Tests unitaires + intégration
- **Review**: Code review standard
### PR 7 : P2 Refactor Handlers (2 jours)
- **Titre**: `refactor(handlers): Migrate legacy handlers to modern pattern`
- **Issues**: MOD-P2-001
- **Tests**: Tests unitaires (vérifier régression)
- **Review**: Code review standard
### PR 8 : P3 Documentation (0.5 jour)
- **Titre**: `docs: Complete OpenAPI/Swagger documentation`
- **Issues**: MOD-P3-002
- **Tests**: Aucun (documentation)
- **Review**: Code review standard
---
## Résumé Exécutif
**Total Issues** : 18
- **P0** : 3 (Sécurité critique)
- **P1** : 6 (Bugs / Dette importante)
- **P2** : 6 (Qualité / Maintenabilité)
- **P3** : 3 (Cosmétique / Documentation)
**Effort Total Estimé** :
- P0 : 5.5h
- P1 : 22h
- P2 : 19h
- P3 : 6h
- **Total** : ~52.5h (~1.5 semaines)
**Priorité Immédiate** :
1. **P0 Security Fixes** (PR 1) — 1 jour
2. **P1 Validation & Errors** (PR 2) — 1 jour
3. **P1 Uploads & ClamAV** (PR 3) — 1 jour
**Risques Identifiés** :
- CORS strict peut bloquer frontend (P0)
- Pas de validation ownership (P0)
- ClamAV indisponible → service down (P1)
- Pas de circuit breakers → cascade failures (P1)
**Recommandations** :
- Exécuter P0 immédiatement (sécurité)
- Exécuter P1 dans les 2 semaines (stabilité)
- Exécuter P2 dans le mois (qualité)
- Exécuter P3 selon disponibilité (documentation)
---
**Fin du Rapport**