41 KiB
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
- PHASE A — Cartographie
- PHASE B — Santé Technique
- PHASE C — Sécurité
- PHASE D — Robustesse & Observabilité
- PHASE E — Performance & Scalabilité
- PHASE F — Liste Exhaustive des Problèmes (Priorisés)
- PHASE G — Plan d'Exé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:
{
"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:
{
"id": "uuid-v4",
"user_id": "uuid-v4",
"title": "Track Title",
"artist": "Artist Name",
"duration": 180.5,
"file_path": "/uploads/tracks/...",
"status": "ready"
}
JWT Claims:
{
"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 uniformeinternal/response: Réponses HTTP standardiséesinternal/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:
make build # Compile pour OS courant
make build-linux # Compile pour Linux
Run:
make run # Build + run
make dev # Mode développement (go run)
Tests:
make test # Tests unitaires (sans integration)
make test-coverage # Tests avec couverture
make test-integration # Tests d'intégration (requiert Docker)
Qualité:
make lint # golangci-lint
make vet # go vet
make security # gosec + govulncheck
Configuration
Variables d'Environnement Requises:
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é viagodotenv).env.{APP_ENV}: Variables spécifiques à l'environnementmigrations/*.sql: Migrations SQL (exécutées au démarrage)
Docker:
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(ouJWT_SECRETsi 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,expvérifiés - Token version: Vérifiée contre DB pour révocation immédiate
Sessions:
- Stockées en DB (
user_sessionstable) - 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 depuisint64complétée) - Tables:
users,tracks,playlists,sessions,rooms,messages, etc.
Conventions:
id: UUID PRIMARY KEYuser_id: UUID FOREIGN KEY versusers.idcreated_at,updated_at: TIMESTAMPdeleted_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 :
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.ymlprobablement) - 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/errorsavec 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 :
SecretsProviderprésent (internal/config/secrets.go) - Validation config :
Config.Validate()+ValidateForEnvironment() - Variables requises :
getEnvRequired()retourne erreur (pas panic)
⚠️ RISQUES :
- P0-SEC-001 :
.envpeut être committé (vérifier.gitignore) - P1-SEC-001 :
JWT_SECRETdoit ê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 :
expclaim vérifié - Validation claims :
sub,iss,aud,exp,iatvérifiés - Validation algorithme :
algheader 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(): UtilisePermissionService.HasRole(..., "admin")RequirePermission(): UtilisePermissionService.HasPermission()RequireContentCreatorRole(): Vérifie rôles creator/premium/admin/artist/producer/label- Tables DB :
permissions,role_permissions,user_rolesexistent
Routes Protégées :
- ✅
/api/v1/admin/*: Protégé parRequireAdmin() - ✅
/api/v1/tracks(POST) : Protégé parRequireContentCreatorRole() - ✅
/api/v1/marketplace/products(POST) : Protégé parRequireContentCreatorRole()
⚠️ 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
- Exemple:
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_atetrevoked_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/v10pré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
- Fichier:
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
govulncheckrégulièrement (CI/CD) (voir section F)
PHASE D — Robustesse & Observabilité
D.1 Logs
✅ STRUCTURÉS :
- Logger :
zap(structured logging) - Corrélation :
RequestIDmiddleware présent - Niveaux : DEBUG, INFO, WARN, ERROR (configurable via
LOG_LEVEL)
⚠️ GAPS :
- P2-OBS-001 : Pas de
trace_id(OpenTelemetry) — seulementrequest_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 viaHANDLER_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) ouSimpleRateLimiter(in-memory) - Par endpoint :
EndpointLimiter(login: 5 attempts/min par défaut) - Upload :
UploadRateLimitmiddleware 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_migrationspour 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 :
PreparedStatementManagerpré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.Contextpassé 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_ORIGINSest 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:
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:
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
.envmanquant
Fix Minimal :
- Ajouter check au démarrage: si
APP_ENV=productionetCORS_ALLOWED_ORIGINSvide → FATAL ERROR avec message clair - Documenter dans README:
CORS_ALLOWED_ORIGINSREQUIS en production
Plan de Validation :
# 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:
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 :
- Ajouter test d'intégration: Service doit refuser de démarrer si
JWT_SECRET< 32 chars - Documenter dans README:
JWT_SECRETdoit être ≥ 32 chars
Plan de Validation :
# 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 :
- Ajouter middleware
RequireOwnershipOrAdmin(resourceType string)qui vérifie:- Si
user_id == resource.user_id→ OK - Si
user.role == "admin"→ OK - Sinon → 403 Forbidden
- Si
- Appliquer sur routes:
PUT /api/v1/users/:idDELETE /api/v1/tracks/:idPUT /api/v1/tracks/:idDELETE /api/v1/playlists/:idPUT /api/v1/playlists/:id
Plan de Validation :
# 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 :
- Ajouter struct tags
validatesur tous les DTOs (internal/dto/*.go) - Ajouter middleware
ValidateRequest()qui valide automatiquement les DTOs - Appliquer sur tous les handlers POST/PUT
Plan de Validation :
# 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 :
- Ajouter config
CLAMAV_REQUIRED=false(défaut:true) - Si
CLAMAV_REQUIRED=falseet ClamAV indisponible → logger warning mais accepter uploads - Documenter: En production, ClamAV doit être disponible
Plan de Validation :
# 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 :
- Ajouter test E2E: Upload flow complet (initiate → chunk → complete → download)
- Ajouter test E2E: Upload avec ClamAV scan
- Ajouter test E2E: Upload avec erreur (chunk manquant, etc.)
Plan de Validation :
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 deresponse.BadRequest(c, ...)
Cause Racine :
- Pas de distinction claire entre erreurs client (400) et serveur (500)
Fix Minimal :
- Auditer tous les handlers: Remplacer
InternalServerErrorparBadRequestpour erreurs validation - Utiliser
InternalServerErroruniquement pour erreurs DB/IO inattendues
Plan de Validation :
# 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 :
- Ajouter
JWT_SECRET_VERSION(entier, défaut: 1) - Inclure
secret_versiondans JWT claims - Valider
secret_versiondansValidateToken() - Documenter: Rotation manuelle (changer secret + incrémenter version)
Plan de Validation :
# 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.modmais non utilisé)
Cause Racine :
- Appels HTTP directs sans protection
Fix Minimal :
- Ajouter circuit breaker (gobreaker) pour Chat Server et Stream Server
- Config:
CIRCUIT_BREAKER_MAX_REQUESTS=5,CIRCUIT_BREAKER_INTERVAL=60s,CIRCUIT_BREAKER_TIMEOUT=30s - En cas d'ouverture circuit: Retourner 503 Service Unavailable avec message clair
Plan de Validation :
# 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) vsinternal/core/*/handler.go(modern) - Code: Deux patterns différents
Cause Racine :
- Migration progressive non complétée
Fix Minimal :
- Documenter: Pattern moderne (
internal/core/*/handler.go) est la référence - Migrer progressivement handlers legacy vers pattern moderne
- 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 detrace_id(distributed)
Cause Racine :
- OpenTelemetry non intégré
Fix Minimal :
- Ajouter OpenTelemetry SDK
- Générer
trace_iddans middleware - Logger
trace_iddans tous les logs
Plan de Validation :
# 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 :
- Ajouter métriques Prometheus:
veza_tracks_uploaded_totalveza_users_registered_totalveza_playlists_created_totalveza_uploads_failed_total(par raison: ClamAV, validation, etc.)
- Exposer via
/metrics
Plan de Validation :
# 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 :
- Ajouter pagination obligatoire sur toutes les listes:
GET /api/v1/tracks?page=1&limit=20GET /api/v1/playlists?page=1&limit=20
- Limite max: 100 items par page
- Retourner
total,page,limitdans réponse
Plan de Validation :
# 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 :
- Ajouter semaphore (limite uploads simultanés: 10 par défaut)
- Si limite atteinte: Retourner 503 Service Unavailable avec
Retry-Afterheader - Config:
MAX_CONCURRENT_UPLOADS=10
Plan de Validation :
# 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 :
- Ajouter import
_ "net/http/pprof" - Exposer endpoint
/debug/pprof(protégé par auth admin en production) - Documenter: Utilisation pprof pour debugging
Plan de Validation :
# 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 :
- 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 :
- Ajouter annotations Swagger sur tous les handlers
- Générer
docs/swagger.jsonavecswag init - Vérifier que tous les endpoints sont documentés
Plan de Validation :
# 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)
-
MOD-P0-001 : CORS Strict en Production (1h)
- Ajouter check fail-fast au démarrage
- Documenter dans README
-
MOD-P0-002 : Validation JWT Secret Length (30min)
- Ajouter test d'intégration
- Documenter dans README
-
MOD-P0-003 : Validation Ownership Routes (4h)
- Créer middleware
RequireOwnershipOrAdmin() - Appliquer sur routes DELETE/PUT
- Tests d'intégration
- Créer middleware
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)
- MOD-P3-001 : README.md (1h)
- MOD-P2-006 : pprof (1h)
- MOD-P2-003 : Métriques Business (2h)
Tests à Ajouter en Priorité
- Tests d'intégration E2E Upload Flow (MOD-P1-003)
- Tests ownership validation (MOD-P0-003)
- Tests CORS fail-fast (MOD-P0-001)
- 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 :
- P0 Security Fixes (PR 1) — 1 jour
- P1 Validation & Errors (PR 2) — 1 jour
- 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