# 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 `) - **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 ` - 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**