1141 lines
41 KiB
Markdown
1141 lines
41 KiB
Markdown
|
|
# AUDIT EXHAUSTIF - MODULE VEZA BACKEND API
|
||
|
|
**Date**: 2025-01-27
|
||
|
|
**Auditeur**: Auto (Cursor AI)
|
||
|
|
**Module**: `veza-backend-api` (Backend Go - API REST)
|
||
|
|
**Version**: 1.2.0
|
||
|
|
**Go Version**: 1.23.8
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
# EXECUTIVE SUMMARY
|
||
|
|
|
||
|
|
## État Général
|
||
|
|
- ✅ **Build**: Compile sans erreurs
|
||
|
|
- ⚠️ **Tests**: 229 fichiers de tests, certains échecs liés à testcontainers (PostgreSQL)
|
||
|
|
- ✅ **Sécurité**: JWT validation stricte, CORS configuré, ClamAV intégré
|
||
|
|
- ⚠️ **Robustesse**: Timeouts partiels, retries présents, circuit breakers manquants
|
||
|
|
- ⚠️ **Performance**: Risques N+1 queries, cache limité, pas de métriques DB pool
|
||
|
|
- ✅ **Observabilité**: Logging structuré (zap), Prometheus metrics, Sentry intégré
|
||
|
|
|
||
|
|
## Métriques Clés
|
||
|
|
- **Fichiers Go**: 671
|
||
|
|
- **Fichiers Tests**: 229 (34% ratio)
|
||
|
|
- **TODOs/FIXMEs**: 25+ identifiés
|
||
|
|
- **Points d'entrée**: 2 (`cmd/api/main.go`, `cmd/modern-server/main.go`)
|
||
|
|
|
||
|
|
## Risques Critiques (Top 5)
|
||
|
|
1. **P0-SECURITY**: CORS strict mode en production si `CORS_ALLOWED_ORIGINS` vide (rejette tout)
|
||
|
|
2. **P0-SECURITY**: Secrets dans logs si `LOG_LEVEL=DEBUG` en production
|
||
|
|
3. **P1-ROBUSTNESS**: Tests d'intégration échouent (testcontainers PostgreSQL)
|
||
|
|
4. **P1-ROBUSTNESS**: Pas de rollback automatique migrations si échec
|
||
|
|
5. **P1-PERFORMANCE**: Risque N+1 queries dans certains handlers
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
# PHASE A — CARTOGRAPHIE
|
||
|
|
|
||
|
|
## A.1 But du Module
|
||
|
|
|
||
|
|
**Rôle**: API REST backend pour la plateforme Veza (audio collaborative)
|
||
|
|
|
||
|
|
**Fonctionnalités principales**:
|
||
|
|
- Authentification (JWT, sessions, 2FA, OAuth)
|
||
|
|
- Gestion utilisateurs et profils (RBAC)
|
||
|
|
- Upload et gestion de tracks audio (ClamAV scanning)
|
||
|
|
- Playlists et collaboration
|
||
|
|
- Chat rooms et messages
|
||
|
|
- Marketplace (produits, commandes)
|
||
|
|
- Webhooks et jobs asynchrones
|
||
|
|
- Audit logging
|
||
|
|
|
||
|
|
## A.2 Entrées / Sorties
|
||
|
|
|
||
|
|
### APIs Exposées
|
||
|
|
|
||
|
|
**HTTP REST** (Gin Framework):
|
||
|
|
- Base path: `/api/v1`
|
||
|
|
- Port: 8080 (configurable via `APP_PORT`)
|
||
|
|
- Format: JSON (Content-Type: `application/json`)
|
||
|
|
|
||
|
|
**Routes principales**:
|
||
|
|
```
|
||
|
|
GET /api/v1/health - Health check global
|
||
|
|
GET /api/v1/healthz - Liveness probe
|
||
|
|
GET /api/v1/readyz - Readiness probe
|
||
|
|
GET /api/v1/status - Status détaillé
|
||
|
|
GET /api/v1/metrics - Prometheus metrics
|
||
|
|
|
||
|
|
POST /api/v1/auth/register - Inscription
|
||
|
|
POST /api/v1/auth/login - Connexion (rate limited)
|
||
|
|
POST /api/v1/auth/refresh - Refresh token
|
||
|
|
POST /api/v1/auth/logout - Déconnexion
|
||
|
|
POST /api/v1/auth/verify-email - Vérification email
|
||
|
|
POST /api/v1/auth/password/reset-request - Reset password
|
||
|
|
|
||
|
|
GET /api/v1/users/:id - Profil utilisateur
|
||
|
|
PUT /api/v1/users/:id - Mise à jour profil
|
||
|
|
|
||
|
|
GET /api/v1/tracks - Liste tracks
|
||
|
|
POST /api/v1/tracks - Upload track (creator role)
|
||
|
|
GET /api/v1/tracks/:id - Détails track
|
||
|
|
PUT /api/v1/tracks/:id - Mise à jour track
|
||
|
|
DELETE /api/v1/tracks/:id - Suppression track
|
||
|
|
|
||
|
|
GET /api/v1/playlists - Liste playlists
|
||
|
|
POST /api/v1/playlists - Créer playlist
|
||
|
|
GET /api/v1/playlists/:id - Détails playlist
|
||
|
|
|
||
|
|
GET /api/v1/marketplace/products - Liste produits
|
||
|
|
POST /api/v1/marketplace/products - Créer produit (creator role)
|
||
|
|
|
||
|
|
GET /api/v1/admin/* - Routes admin (admin role)
|
||
|
|
```
|
||
|
|
|
||
|
|
**WebSocket**: Délégué au Chat Server Rust (port 8081)
|
||
|
|
|
||
|
|
**gRPC**: Configuré mais non utilisé actuellement
|
||
|
|
|
||
|
|
**GraphQL**: Configuré mais non utilisé actuellement
|
||
|
|
|
||
|
|
### Formats de Données
|
||
|
|
|
||
|
|
**Request/Response JSON**:
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"id": "uuid-v4",
|
||
|
|
"email": "user@example.com",
|
||
|
|
"username": "username",
|
||
|
|
"created_at": "2025-01-27T10:00:00Z"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**JWT Token** (Bearer):
|
||
|
|
```
|
||
|
|
Authorization: Bearer <token>
|
||
|
|
```
|
||
|
|
|
||
|
|
**Claims JWT**:
|
||
|
|
- `sub`: UUID utilisateur
|
||
|
|
- `iss`: "veza-api" (vérifié)
|
||
|
|
- `aud`: "veza-app" (vérifié)
|
||
|
|
- `exp`: Expiration timestamp
|
||
|
|
- `iat`: Issued at timestamp
|
||
|
|
- `token_version`: Version pour révocation
|
||
|
|
|
||
|
|
## A.3 Dépendances Internes
|
||
|
|
|
||
|
|
**Structure**:
|
||
|
|
```
|
||
|
|
internal/
|
||
|
|
├── api/ # Routes et handlers HTTP
|
||
|
|
├── config/ # Configuration (env, secrets, validation)
|
||
|
|
├── core/ # Services core (auth, track, marketplace)
|
||
|
|
├── database/ # Gestion DB (migrations, pool, retry)
|
||
|
|
├── handlers/ # Handlers HTTP (auth, tracks, playlists, etc.)
|
||
|
|
├── middleware/ # Middlewares (auth, CORS, rate limit, timeout, etc.)
|
||
|
|
├── models/ # Modèles GORM
|
||
|
|
├── repositories/ # Repositories (data access)
|
||
|
|
├── services/ # Services métier
|
||
|
|
├── workers/ # Workers asynchrones (jobs, webhooks, etc.)
|
||
|
|
├── errors/ # Gestion erreurs standardisée
|
||
|
|
├── logging/ # Logging structuré (zap)
|
||
|
|
├── metrics/ # Prometheus metrics
|
||
|
|
└── validators/ # Validateurs (email, password, etc.)
|
||
|
|
```
|
||
|
|
|
||
|
|
**Packages partagés**:
|
||
|
|
- `internal/errors`: Codes d'erreur standardisés (1000-9999)
|
||
|
|
- `internal/common`: Types et validation communs
|
||
|
|
- `internal/response`: Format réponse standardisé
|
||
|
|
|
||
|
|
## A.4 Dépendances Externes
|
||
|
|
|
||
|
|
### Base de Données
|
||
|
|
- **PostgreSQL**: Base principale (via `lib/pq` + GORM)
|
||
|
|
- **Migrations**: SQL files dans `migrations/` (exécutées au démarrage)
|
||
|
|
- **Pool**: MaxOpenConns=25, MaxIdleConns=10, MaxLifetime=5min
|
||
|
|
|
||
|
|
### Cache & Sessions
|
||
|
|
- **Redis**: Cache et sessions (optionnel via `REDIS_ENABLE`)
|
||
|
|
- **Client**: `redis/go-redis/v9`
|
||
|
|
|
||
|
|
### Message Queue
|
||
|
|
- **RabbitMQ**: Event bus pour jobs asynchrones (optionnel via `RABBITMQ_ENABLE`)
|
||
|
|
- **Client**: `rabbitmq/amqp091-go`
|
||
|
|
|
||
|
|
### Services Externes
|
||
|
|
- **Chat Server**: `http://localhost:8081` (WebSocket, Rust)
|
||
|
|
- **Stream Server**: `http://localhost:8082` (WebRTC streaming, Rust)
|
||
|
|
- **ClamAV**: Virus scanning (localhost:3310, optionnel)
|
||
|
|
|
||
|
|
### Monitoring & Observabilité
|
||
|
|
- **Sentry**: Error tracking (optionnel via `SENTRY_DSN`)
|
||
|
|
- **Prometheus**: Metrics exposées sur `/api/v1/metrics`
|
||
|
|
|
||
|
|
### Email
|
||
|
|
- **SMTP**: Envoi emails (verification, password reset, etc.)
|
||
|
|
|
||
|
|
## A.5 Exécution
|
||
|
|
|
||
|
|
### Commandes Build/Run
|
||
|
|
|
||
|
|
**Build**:
|
||
|
|
```bash
|
||
|
|
make build # Compile binaire
|
||
|
|
make build-linux # Compile pour Linux
|
||
|
|
make docker-build # Build image Docker
|
||
|
|
```
|
||
|
|
|
||
|
|
**Run**:
|
||
|
|
```bash
|
||
|
|
make run # Build + run
|
||
|
|
make dev # Run en mode dev (go run)
|
||
|
|
make run-lab # Run en mode lab (sans Redis/RabbitMQ)
|
||
|
|
```
|
||
|
|
|
||
|
|
**Tests**:
|
||
|
|
```bash
|
||
|
|
make test # Tests unitaires
|
||
|
|
make test-coverage # Tests avec couverture
|
||
|
|
make test-race # Tests avec détection race conditions
|
||
|
|
make test-integration # Tests d'intégration
|
||
|
|
```
|
||
|
|
|
||
|
|
**Qualité**:
|
||
|
|
```bash
|
||
|
|
make lint # golangci-lint
|
||
|
|
make vet # go vet
|
||
|
|
make security # gosec + govulncheck
|
||
|
|
```
|
||
|
|
|
||
|
|
### Configuration
|
||
|
|
|
||
|
|
**Variables d'environnement requises**:
|
||
|
|
```bash
|
||
|
|
DATABASE_URL=postgresql://user:pass@host:5432/dbname
|
||
|
|
JWT_SECRET=<secret-32-chars-min>
|
||
|
|
```
|
||
|
|
|
||
|
|
**Variables optionnelles**:
|
||
|
|
```bash
|
||
|
|
APP_ENV=production # development, test, production
|
||
|
|
APP_PORT=8080
|
||
|
|
REDIS_URL=redis://localhost:6379
|
||
|
|
REDIS_ENABLE=true
|
||
|
|
RABBITMQ_URL=amqp://guest:guest@localhost:5672/
|
||
|
|
RABBITMQ_ENABLE=true
|
||
|
|
CORS_ALLOWED_ORIGINS=https://app.veza.com,https://www.veza.com
|
||
|
|
SENTRY_DSN=https://...
|
||
|
|
LOG_LEVEL=INFO # DEBUG, INFO, WARN, ERROR
|
||
|
|
HANDLER_TIMEOUT=30s
|
||
|
|
```
|
||
|
|
|
||
|
|
**Fichiers de config**:
|
||
|
|
- `.env` (chargé automatiquement)
|
||
|
|
- `.env.{APP_ENV}` (chargé selon environnement)
|
||
|
|
|
||
|
|
### Docker
|
||
|
|
|
||
|
|
**Build**:
|
||
|
|
```bash
|
||
|
|
docker build -t veza-backend-api .
|
||
|
|
```
|
||
|
|
|
||
|
|
**Run**:
|
||
|
|
```bash
|
||
|
|
docker run -p 8080:8080 \
|
||
|
|
-e DATABASE_URL=... \
|
||
|
|
-e JWT_SECRET=... \
|
||
|
|
veza-backend-api
|
||
|
|
```
|
||
|
|
|
||
|
|
**Production Dockerfile**: `Dockerfile.production` (multi-stage, non-root user, healthcheck)
|
||
|
|
|
||
|
|
## A.6 Points d'Intégration
|
||
|
|
|
||
|
|
### Contrats d'API
|
||
|
|
|
||
|
|
**Frontend React**:
|
||
|
|
- Base URL: `/api/v1`
|
||
|
|
- Auth: JWT Bearer token
|
||
|
|
- CORS: Configuré via `CORS_ALLOWED_ORIGINS`
|
||
|
|
|
||
|
|
**Chat Server Rust**:
|
||
|
|
- Endpoint: `POST /api/v1/chat/token` (génère JWT pour Chat Server)
|
||
|
|
- Format: JWT avec claims `sub`, `iss`, `aud`
|
||
|
|
|
||
|
|
**Stream Server Rust**:
|
||
|
|
- Callback: `POST /api/v1/internal/tracks/:id/stream-ready` (callback après transcoding)
|
||
|
|
- Format: JSON avec `track_id`, `status`, `hls_url`
|
||
|
|
|
||
|
|
### Auth
|
||
|
|
|
||
|
|
**JWT Validation**:
|
||
|
|
- Algorithme: HS256 (strict, `none`/`RS256` rejetés)
|
||
|
|
- Claims vérifiés: `iss`, `aud`, `exp`, `token_version`
|
||
|
|
- Session DB: Vérifiée via `SessionService.ValidateSession()`
|
||
|
|
|
||
|
|
**RBAC**:
|
||
|
|
- Rôles: `user`, `admin`, `creator`, `premium`, `artist`, `producer`, `label`
|
||
|
|
- Permissions: Tables `permissions`, `role_permissions`, `user_roles`
|
||
|
|
- Middleware: `RequireAuth()`, `RequireAdmin()`, `RequireContentCreatorRole()`
|
||
|
|
|
||
|
|
### Schéma DB
|
||
|
|
|
||
|
|
**Conventions**:
|
||
|
|
- IDs: UUID v4 (migration depuis int64 complétée)
|
||
|
|
- Timestamps: `created_at`, `updated_at` (timestamptz)
|
||
|
|
- Soft delete: `deleted_at` (timestamptz nullable)
|
||
|
|
- Foreign keys: ON DELETE CASCADE/RESTRICT explicite
|
||
|
|
- Indexes: Sur toutes foreign keys
|
||
|
|
|
||
|
|
**Tables principales**:
|
||
|
|
- `users` (id UUID, email, username, password_hash, token_version, ...)
|
||
|
|
- `sessions` (id UUID, user_id UUID, token_hash, expires_at, ...)
|
||
|
|
- `tracks` (id UUID, user_id UUID, title, file_path, status, ...)
|
||
|
|
- `playlists` (id UUID, user_id UUID, title, ...)
|
||
|
|
- `permissions`, `role_permissions`, `user_roles` (RBAC)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
# PHASE B — SANTÉ TECHNIQUE
|
||
|
|
|
||
|
|
## B.1 Build & Compilation
|
||
|
|
|
||
|
|
**État**: ✅ **PASS**
|
||
|
|
|
||
|
|
**Compilation**:
|
||
|
|
```bash
|
||
|
|
go build ./... # ✅ Compile sans erreurs
|
||
|
|
```
|
||
|
|
|
||
|
|
**Points d'entrée**:
|
||
|
|
- `cmd/api/main.go`: Point d'entrée principal (Sentry, RabbitMQ, Job Worker)
|
||
|
|
- `cmd/modern-server/main.go`: Point d'entrée alternatif (moins de fonctionnalités)
|
||
|
|
|
||
|
|
**Problèmes**:
|
||
|
|
- ⚠️ **P2-STRUCTURE**: 2 points d'entrée créent confusion
|
||
|
|
- Fichier: `cmd/api/main.go`, `cmd/modern-server/main.go`
|
||
|
|
- Impact: Développeurs peuvent utiliser le mauvais point d'entrée
|
||
|
|
- Fix: Documenter ou supprimer `cmd/modern-server/main.go`
|
||
|
|
|
||
|
|
**Dockerfile**:
|
||
|
|
- ✅ Multi-stage build (optimisé)
|
||
|
|
- ✅ Non-root user (sécurité)
|
||
|
|
- ✅ Healthcheck configuré
|
||
|
|
- ⚠️ **P2-DOCKER**: `Dockerfile.production` référence `./main.go` (ligne 30) mais devrait être `./cmd/api/main.go`
|
||
|
|
- Fichier: `Dockerfile.production:30`
|
||
|
|
- Impact: Build échoue si utilisé
|
||
|
|
- Fix: Corriger chemin vers `./cmd/api/main.go`
|
||
|
|
|
||
|
|
## B.2 Tests
|
||
|
|
|
||
|
|
**État**: ⚠️ **PARTIAL** (tests unitaires OK, tests d'intégration échouent)
|
||
|
|
|
||
|
|
**Métriques**:
|
||
|
|
- Fichiers tests: 229
|
||
|
|
- Ratio: 34% (229/671)
|
||
|
|
- Tests unitaires: ✅ Passent (sauf dépendances externes)
|
||
|
|
- Tests d'intégration: ❌ Échouent (testcontainers PostgreSQL)
|
||
|
|
|
||
|
|
**Problèmes identifiés**:
|
||
|
|
|
||
|
|
#### MOD-P1-011: Tests d'Intégration Échouent (testcontainers)
|
||
|
|
- **Titre**: Tests d'intégration échouent avec erreur "container exited with code 3"
|
||
|
|
- **Impact**: Tests d'intégration non fiables, CI/CD peut échouer
|
||
|
|
- **Preuve**: `tests/transactions/social_transaction_test.go:23` - erreur testcontainers
|
||
|
|
- **Cause**: Testcontainers PostgreSQL ne démarre pas correctement
|
||
|
|
- **Fix Minimal**:
|
||
|
|
1. Vérifier configuration testcontainers
|
||
|
|
2. Ajouter retry/backoff pour démarrage container
|
||
|
|
3. Ou utiliser DB de test locale si testcontainers instable
|
||
|
|
- **Plan Validation**:
|
||
|
|
- Test: `go test ./tests/transactions -v` → doit passer
|
||
|
|
- Commande: Vérifier logs testcontainers pour cause échec
|
||
|
|
- **Effet de Bord**: Tests peuvent être plus lents
|
||
|
|
- **Effort**: M (4h)
|
||
|
|
|
||
|
|
**Couverture**:
|
||
|
|
- ⚠️ Pas de métrique de couverture automatique
|
||
|
|
- ⚠️ **P2-TEST**: Couverture non mesurée systématiquement
|
||
|
|
- Fix: Ajouter `make test-coverage` dans CI/CD
|
||
|
|
|
||
|
|
**Tests manquants**:
|
||
|
|
- ⚠️ **P2-TEST**: Pas de tests E2E complets
|
||
|
|
- ⚠️ **P2-TEST**: Tests de charge manquants (k6 script présent mais non exécuté)
|
||
|
|
|
||
|
|
## B.3 Gestion des Erreurs
|
||
|
|
|
||
|
|
**État**: ✅ **BON** (structure standardisée)
|
||
|
|
|
||
|
|
**Implémentation**:
|
||
|
|
- ✅ Package `internal/errors`: Codes d'erreur standardisés (1000-9999)
|
||
|
|
- ✅ `AppError` struct: Code, Message, Details, Context
|
||
|
|
- ✅ Middleware `ErrorHandler`: Mapping code → HTTP status
|
||
|
|
- ✅ Wrapping: `errors.Wrap()` pour chaînage erreurs
|
||
|
|
|
||
|
|
**Codes d'erreur**:
|
||
|
|
```go
|
||
|
|
// Auth (1000-1999)
|
||
|
|
ErrCodeInvalidCredentials = 1000
|
||
|
|
ErrCodeTokenExpired = 1001
|
||
|
|
ErrCodeTokenInvalid = 1002
|
||
|
|
ErrCodeForbidden = 1003
|
||
|
|
ErrCodeUnauthorized = 1004
|
||
|
|
|
||
|
|
// Validation (2000-2999)
|
||
|
|
ErrCodeValidation = 2000
|
||
|
|
ErrCodeRequiredField = 2001
|
||
|
|
|
||
|
|
// Resource (3000-3999)
|
||
|
|
ErrCodeNotFound = 3000
|
||
|
|
ErrCodeAlreadyExists = 3001
|
||
|
|
|
||
|
|
// Business Logic (4000-4999)
|
||
|
|
ErrCodeOperationNotAllowed = 4000
|
||
|
|
ErrCodeQuotaExceeded = 4005
|
||
|
|
|
||
|
|
// Rate Limiting (5000-5099)
|
||
|
|
ErrCodeRateLimitExceeded = 5000
|
||
|
|
|
||
|
|
// Internal (9000-9999)
|
||
|
|
ErrCodeInternal = 9000
|
||
|
|
ErrCodeDatabase = 9001
|
||
|
|
```
|
||
|
|
|
||
|
|
**Problèmes**:
|
||
|
|
- ⚠️ **P2-ERROR**: Certains handlers retournent encore `gin.H{"error": "..."}` au lieu de `AppError`
|
||
|
|
- Fichiers: À auditer tous handlers
|
||
|
|
- Impact: Incohérence format erreur
|
||
|
|
- Fix: Refactoriser tous handlers pour utiliser `AppError`
|
||
|
|
|
||
|
|
## B.4 Conventions & Structure
|
||
|
|
|
||
|
|
**État**: ✅ **BON** (structure claire)
|
||
|
|
|
||
|
|
**Naming**:
|
||
|
|
- ✅ Packages: snake_case (`internal/api/user`)
|
||
|
|
- ✅ Fichiers: snake_case (`handler.go`, `service.go`)
|
||
|
|
- ✅ Types: PascalCase (`AuthService`, `UserHandler`)
|
||
|
|
- ✅ Variables: camelCase (`userID`, `authService`)
|
||
|
|
|
||
|
|
**Structure**:
|
||
|
|
- ✅ Séparation claire: handlers → services → repositories
|
||
|
|
- ✅ Middlewares centralisés
|
||
|
|
- ✅ Config centralisée
|
||
|
|
|
||
|
|
**Problèmes**:
|
||
|
|
- ⚠️ **P2-STRUCTURE**: 25+ TODOs/FIXMEs dans code
|
||
|
|
- Fichiers: `internal/core/track/handler.go:282`, `internal/services/track_history_service.go:74`, etc.
|
||
|
|
- Impact: Dette technique, code incomplet
|
||
|
|
- Fix: Auditer tous TODOs, prioriser, résoudre ou créer tickets
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
# PHASE C — SÉCURITÉ
|
||
|
|
|
||
|
|
## C.1 Secrets & Configuration
|
||
|
|
|
||
|
|
**État**: ✅ **BON** (secrets masqués, validation stricte)
|
||
|
|
|
||
|
|
**Implémentation**:
|
||
|
|
- ✅ `SecretsProvider`: Masque secrets dans logs (`internal/config/secrets.go`)
|
||
|
|
- ✅ `getEnvRequired()`: Variables requises retournent erreur (pas panic)
|
||
|
|
- ✅ Validation environnement: `ValidateForEnvironment()` (stricte en production)
|
||
|
|
- ✅ CORS: Wildcard `*` interdit en production
|
||
|
|
|
||
|
|
**Problèmes**:
|
||
|
|
|
||
|
|
#### MOD-P0-001: CORS Strict Mode en Production
|
||
|
|
- **Titre**: Si `CORS_ALLOWED_ORIGINS` vide en production, TOUTES les requêtes CORS sont rejetées
|
||
|
|
- **Impact**: Service inaccessible depuis frontend si config manquante
|
||
|
|
- **Preuve**: `internal/api/router.go:72-74` - Warning loggé mais service démarre
|
||
|
|
- **Cause**: CORS middleware appliqué avec liste vide (strict mode)
|
||
|
|
- **Fix Minimal**:
|
||
|
|
1. Fail-fast au démarrage si `CORS_ALLOWED_ORIGINS` vide en production
|
||
|
|
2. Ou documenter que strict mode est intentionnel
|
||
|
|
- **Plan Validation**:
|
||
|
|
- Test: Démarrer avec `APP_ENV=production CORS_ALLOWED_ORIGINS=""` → doit échouer ou documenter
|
||
|
|
- Commande: Vérifier logs au démarrage
|
||
|
|
- **Effet de Bord**: Service ne démarre pas si config manquante (acceptable pour sécurité)
|
||
|
|
- **Effort**: S (1h)
|
||
|
|
|
||
|
|
#### MOD-P0-002: Secrets dans Logs si DEBUG
|
||
|
|
- **Titre**: `LOG_LEVEL=DEBUG` en production peut exposer secrets dans logs
|
||
|
|
- **Impact**: Fuite de données sensibles (JWT secrets, DB passwords)
|
||
|
|
- **Preuve**: `internal/config/config.go:651` - Validation interdit DEBUG en prod, mais si contourné
|
||
|
|
- **Cause**: Logs DEBUG peuvent contenir config complète
|
||
|
|
- **Fix Minimal**:
|
||
|
|
1. Validation déjà présente (interdit DEBUG en prod)
|
||
|
|
2. Ajouter redaction automatique secrets dans logs DEBUG
|
||
|
|
- **Plan Validation**:
|
||
|
|
- Test: Démarrer avec `LOG_LEVEL=DEBUG`, vérifier logs → secrets masqués
|
||
|
|
- Commande: `grep -i "jwt_secret\|password" logs/*.log` → doit être vide
|
||
|
|
- **Effet de Bord**: Debugging plus difficile (acceptable)
|
||
|
|
- **Effort**: S (2h)
|
||
|
|
|
||
|
|
## C.2 Authentification & Autorisation
|
||
|
|
|
||
|
|
**État**: ✅ **EXCELLENT** (JWT validation stricte, RBAC fonctionnel)
|
||
|
|
|
||
|
|
**JWT Validation**:
|
||
|
|
- ✅ Algorithme: HS256 (strict, `none`/`RS256` rejetés)
|
||
|
|
- ✅ Signature: Validée avec secret
|
||
|
|
- ✅ Expiration: `exp` claim vérifié
|
||
|
|
- ✅ Issuer: `iss` vérifié (doit être `JWT_ISSUER` ou "veza-api")
|
||
|
|
- ✅ Audience: `aud` vérifié (doit être `JWT_AUDIENCE` ou "veza-app")
|
||
|
|
- ✅ Token Version: Vérifié contre DB (`user.token_version`)
|
||
|
|
- ✅ Session DB: `SessionService.ValidateSession()` appelé
|
||
|
|
|
||
|
|
**RBAC**:
|
||
|
|
- ✅ `RequireAdmin()`: Utilise `PermissionService.HasRole(..., "admin")`
|
||
|
|
- ✅ `RequirePermission()`: Utilise `PermissionService.HasPermission()`
|
||
|
|
- ✅ `RequireContentCreatorRole()`: Vérifie 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()`
|
||
|
|
|
||
|
|
**Problèmes**:
|
||
|
|
- ✅ **RÉSOLU**: Validation `aud`/`iss` JWT stricte (via `jwt.WithIssuer()`, `jwt.WithAudience()`)
|
||
|
|
- ✅ **RÉSOLU**: Token version vérifiée dans `authenticate()`
|
||
|
|
|
||
|
|
## C.3 Injection & File Upload
|
||
|
|
|
||
|
|
**État**: ✅ **BON** (ClamAV intégré, validation stricte)
|
||
|
|
|
||
|
|
**File Upload**:
|
||
|
|
- ✅ ClamAV scanning: Intégré (`internal/services/upload_validator.go`)
|
||
|
|
- ✅ Validation type MIME: Magic number + extension
|
||
|
|
- ✅ Validation taille: Limites par type (audio, image, video)
|
||
|
|
- ✅ Fail-secure: Rejette upload si ClamAV requis mais indisponible
|
||
|
|
- ✅ Quarantine: Fichiers infectés mis en quarantaine
|
||
|
|
|
||
|
|
**SQL Injection**:
|
||
|
|
- ✅ GORM: Utilisé partout (paramétrisé)
|
||
|
|
- ✅ Raw SQL: Utilisé avec `$1, $2, ...` (paramétrisé)
|
||
|
|
- ⚠️ **P1-SECURITY**: Quelques requêtes raw SQL à auditer
|
||
|
|
- Fichiers: `internal/services/email_verification_service.go:73`, `internal/services/session_service.go:82`
|
||
|
|
- Impact: Risque SQL injection si mal formaté
|
||
|
|
- Fix: Vérifier toutes requêtes raw SQL utilisent paramètres
|
||
|
|
|
||
|
|
**Command Injection**:
|
||
|
|
- ✅ Pas d'exécution commande shell identifiée
|
||
|
|
- ✅ ClamAV: Communication via socket (pas commande shell)
|
||
|
|
|
||
|
|
**Path Traversal**:
|
||
|
|
- ✅ Uploads: Chemins sanitizés (`filepath.Join`, `filepath.Base`)
|
||
|
|
- ⚠️ **P2-SECURITY**: Audit nécessaire pour tous accès fichiers
|
||
|
|
|
||
|
|
## C.4 CORS, Cookies, Headers
|
||
|
|
|
||
|
|
**État**: ✅ **BON** (CORS configuré, pas de cookies)
|
||
|
|
|
||
|
|
**CORS**:
|
||
|
|
- ✅ Middleware: `middleware.CORS()` appliqué
|
||
|
|
- ✅ Origins: Configuré via `CORS_ALLOWED_ORIGINS`
|
||
|
|
- ✅ Production: Wildcard `*` interdit
|
||
|
|
- ⚠️ **P0-SECURITY**: Si `CORS_ALLOWED_ORIGINS` vide, strict mode (rejette tout) - voir MOD-P0-001
|
||
|
|
|
||
|
|
**Cookies**:
|
||
|
|
- ✅ Pas de cookies utilisés (JWT dans header Authorization)
|
||
|
|
|
||
|
|
**Headers Sécurité**:
|
||
|
|
- ⚠️ **P2-SECURITY**: Headers sécurité manquants (HSTS, CSP, X-Frame-Options, etc.)
|
||
|
|
- Fix: Ajouter middleware sécurité avec headers recommandés
|
||
|
|
|
||
|
|
## C.5 Dépendances Vulnérables
|
||
|
|
|
||
|
|
**État**: ✅ **BON** (scan automatique dans CI/CD)
|
||
|
|
|
||
|
|
**Scan Automatique**:
|
||
|
|
- ✅ GitHub Actions: `govulncheck` dans workflow (`vulnerability-scan.yml`)
|
||
|
|
- ✅ Makefile: `make security` avec `gosec` + `govulncheck`
|
||
|
|
- ✅ Docker: Trivy scan dans CI/CD
|
||
|
|
|
||
|
|
**Problèmes**:
|
||
|
|
- ⚠️ **P2-SECURITY**: Scan non exécuté localement par défaut
|
||
|
|
- Fix: Ajouter `make security` dans `make ci`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
# PHASE D — ROBUSTESSE & OBSERVABILITÉ
|
||
|
|
|
||
|
|
## D.1 Logging
|
||
|
|
|
||
|
|
**État**: ✅ **EXCELLENT** (structured logging, corrélation)
|
||
|
|
|
||
|
|
**Implémentation**:
|
||
|
|
- ✅ Zap: Structured logging (`go.uber.org/zap`)
|
||
|
|
- ✅ Request ID: Généré et propagé (`middleware.RequestID()`)
|
||
|
|
- ✅ Trace ID: W3C Trace Context compatible (`middleware.Tracing()`)
|
||
|
|
- ✅ Context: `request_id`, `user_id`, `trace_id`, `span_id` dans logs
|
||
|
|
- ✅ Niveaux: DEBUG, INFO, WARN, ERROR (configurable via `LOG_LEVEL`)
|
||
|
|
|
||
|
|
**Problèmes**:
|
||
|
|
- ⚠️ **P1-OBSERVABILITY**: Stack traces dans logs peuvent exposer info sensible
|
||
|
|
- Fichier: `internal/middleware/error_handler.go:145` - `zap.ByteString("stack_trace", debug.Stack())`
|
||
|
|
- Impact: Chemins fichiers, code dans logs prod
|
||
|
|
- Fix: Logger stack traces seulement si `LOG_LEVEL=DEBUG` ou `APP_ENV=development`
|
||
|
|
- Effort: S (1h)
|
||
|
|
|
||
|
|
## D.2 Metrics
|
||
|
|
|
||
|
|
**État**: ✅ **BON** (Prometheus intégré)
|
||
|
|
|
||
|
|
**Implémentation**:
|
||
|
|
- ✅ Prometheus: Metrics exposées sur `/api/v1/metrics`
|
||
|
|
- ✅ Middleware: `middleware.Metrics()` enregistre requêtes HTTP
|
||
|
|
- ✅ Error Metrics: `ErrorMetrics` enregistre erreurs par code
|
||
|
|
- ✅ System Metrics: CPU, mémoire, goroutines (`/api/v1/system/metrics`)
|
||
|
|
|
||
|
|
**Problèmes**:
|
||
|
|
- ⚠️ **P2-OBSERVABILITY**: Métriques DB pool manquantes (connections, wait time)
|
||
|
|
- Fix: Exposer métriques `database/sql` stats
|
||
|
|
- Effort: M (2h)
|
||
|
|
|
||
|
|
## D.3 Healthchecks
|
||
|
|
|
||
|
|
**État**: ✅ **BON** (healthchecks complets)
|
||
|
|
|
||
|
|
**Endpoints**:
|
||
|
|
- ✅ `/api/v1/health`: Health check global
|
||
|
|
- ✅ `/api/v1/healthz`: Liveness probe (Kubernetes)
|
||
|
|
- ✅ `/api/v1/readyz`: Readiness probe (DB, Redis, RabbitMQ)
|
||
|
|
- ✅ `/api/v1/status`: Status détaillé (version, git commit, build time)
|
||
|
|
|
||
|
|
**Problèmes**:
|
||
|
|
- ⚠️ **P1-ROBUSTNESS**: `/readyz` peut échouer si Redis/RabbitMQ down (même en dev)
|
||
|
|
- Fichier: `internal/handlers/health.go:143-159`
|
||
|
|
- Impact: Service marqué "not ready" même si DB OK
|
||
|
|
- Fix: Déjà partiel (tolérance en non-prod), mais peut être amélioré
|
||
|
|
- Effort: S (1h)
|
||
|
|
|
||
|
|
## D.4 Timeouts & Retries
|
||
|
|
|
||
|
|
**État**: ⚠️ **PARTIAL** (timeouts partiels, retries présents)
|
||
|
|
|
||
|
|
**Timeouts**:
|
||
|
|
- ✅ HTTP server: `ReadTimeout: 30s`, `WriteTimeout: 30s`
|
||
|
|
- ✅ Global handler: `HANDLER_TIMEOUT=30s` (middleware `Timeout()`)
|
||
|
|
- ✅ DB: Timeout 5s dans health checks
|
||
|
|
- ✅ Redis: Timeout 5s dans health checks
|
||
|
|
- ⚠️ **P1-ROBUSTNESS**: Pas de timeout context dans tous les handlers
|
||
|
|
- Impact: Handlers peuvent bloquer indéfiniment
|
||
|
|
- Fix: Ajouter `context.WithTimeout()` dans tous handlers
|
||
|
|
- Effort: M (4h)
|
||
|
|
|
||
|
|
**Retries**:
|
||
|
|
- ✅ DB: Retry avec `DBMaxRetries` (défaut: 5) et `DBRetryInterval` (défaut: 5s)
|
||
|
|
- ✅ RabbitMQ: Retry avec `RabbitMQMaxRetries` (défaut: 3) et `RabbitMQRetryInterval` (défaut: 2s)
|
||
|
|
- ⚠️ **P2-ROBUSTNESS**: Pas de retry sur requêtes HTTP externes (Chat Server, Stream Server)
|
||
|
|
- Fix: Ajouter retry avec backoff exponentiel
|
||
|
|
- Effort: M (3h)
|
||
|
|
|
||
|
|
**Circuit Breakers**:
|
||
|
|
- ⚠️ **P2-ROBUSTNESS**: Pas de circuit breakers implémentés
|
||
|
|
- Impact: Service peut être surchargé si dépendances lentes
|
||
|
|
- Fix: Intégrer `sony/gobreaker` ou similaire
|
||
|
|
- Effort: M (4h)
|
||
|
|
|
||
|
|
## D.5 Gestion de Charge
|
||
|
|
|
||
|
|
**DB Pool**:
|
||
|
|
- ✅ Configuré: `MaxOpenConns: 25`, `MaxIdleConns: 10`
|
||
|
|
- ✅ `ConnMaxLifetime: 5min`, `ConnMaxIdleTime: 1min`
|
||
|
|
- ⚠️ **P2-PERFORMANCE**: Pool stats pas exposés dans métriques
|
||
|
|
- Fix: Exposer métriques pool
|
||
|
|
- Effort: S (1h)
|
||
|
|
|
||
|
|
**WebSocket**:
|
||
|
|
- ⚠️ **P2-ROBUSTNESS**: Pas de limite connexions WebSocket (géré par Chat Server Rust)
|
||
|
|
|
||
|
|
**Streaming**:
|
||
|
|
- ⚠️ **P2-ROBUSTNESS**: Pas de backpressure sur uploads (géré par rate limiting uploads)
|
||
|
|
|
||
|
|
## D.6 Migrations & Compatibilité
|
||
|
|
|
||
|
|
**Migrations**:
|
||
|
|
- ✅ Migrations SQL (`migrations/*.sql`)
|
||
|
|
- ✅ Table tracking: `schema_migrations`
|
||
|
|
- ✅ Exécution au démarrage: `Database.Initialize()`
|
||
|
|
- ⚠️ **P1-ROBUSTNESS**: Pas de rollback automatique si migration échoue
|
||
|
|
- Fichier: `internal/database/database.go:219` - Migration exécutée sans rollback si erreur
|
||
|
|
- Impact: DB peut être dans état incohérent
|
||
|
|
- Fix: Exécuter migrations dans transaction, rollback si erreur
|
||
|
|
- Effort: M (4h)
|
||
|
|
|
||
|
|
**UUID Migration**:
|
||
|
|
- ✅ Migration depuis int64 vers UUID complétée
|
||
|
|
- ✅ Fichiers backup présents (`.backup-pre-uuid-migration/`) - à nettoyer
|
||
|
|
|
||
|
|
**Compatibilité**:
|
||
|
|
- ⚠️ **P2-ROBUSTNESS**: Pas de versioning API (toutes routes `/api/v1/*`)
|
||
|
|
- Impact: Breaking changes difficiles
|
||
|
|
- Fix: Prévoir versioning pour futures versions
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
# PHASE E — PERFORMANCE & SCALABILITÉ
|
||
|
|
|
||
|
|
## E.1 Hotspots
|
||
|
|
|
||
|
|
**Allocations**:
|
||
|
|
- ⚠️ **P2-PERFORMANCE**: Copies de slices/strings dans certains handlers (audit nécessaire)
|
||
|
|
- ⚠️ **P2-PERFORMANCE**: JSON marshalling peut être optimisé (streaming pour grandes réponses)
|
||
|
|
|
||
|
|
**N+1 Queries**:
|
||
|
|
- ⚠️ **P1-PERFORMANCE**: Risque N+1 dans `ListTracks()` si relations chargées
|
||
|
|
- Fichier: `internal/core/track/service.go` - À auditer
|
||
|
|
- Impact: Performance dégradée, charge DB excessive
|
||
|
|
- Fix: Ajouter `Preload("User")` ou joins SQL
|
||
|
|
- Effort: M (6h)
|
||
|
|
|
||
|
|
**Locks**:
|
||
|
|
- ⚠️ **P2-PERFORMANCE**: Pas de locks identifiés (audit nécessaire pour concurrence)
|
||
|
|
|
||
|
|
## E.2 Streaming
|
||
|
|
|
||
|
|
**Buffering**:
|
||
|
|
- ✅ Chunked Upload: Implémenté (`TrackChunkService`)
|
||
|
|
- ✅ Redis Cache: Utilisé pour chunks (si Redis enabled)
|
||
|
|
|
||
|
|
**ffmpeg Pipeline**:
|
||
|
|
- ⚠️ **P2-PERFORMANCE**: Pas d'implémentation ffmpeg dans backend (délégué à Stream Server)
|
||
|
|
|
||
|
|
**IO**:
|
||
|
|
- ⚠️ **P2-PERFORMANCE**: File I/O synchrone (peut bloquer goroutines)
|
||
|
|
- Fix: File I/O asynchrone (goroutines pour uploads)
|
||
|
|
- Effort: M (4h)
|
||
|
|
|
||
|
|
## E.3 Go-Specific Issues
|
||
|
|
|
||
|
|
**Goroutine Leaks**:
|
||
|
|
- ✅ **RÉSOLU**: Timeout middleware fixé (MOD-P1-007)
|
||
|
|
- Fichier: `internal/middleware/timeout.go:24-27` - Context cancellation + cleanup
|
||
|
|
|
||
|
|
**Context Propagation**:
|
||
|
|
- ✅ Context: Propagé dans handlers → services → repositories
|
||
|
|
- ⚠️ **P2-PERFORMANCE**: Pas toujours utilisé pour timeouts DB
|
||
|
|
|
||
|
|
**DB Pool Misuse**:
|
||
|
|
- ✅ Pool Configuré: MaxOpenConns, MaxIdleConns configurés
|
||
|
|
- ⚠️ **P2-PERFORMANCE**: Pas de métriques pool pour monitoring
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
# 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é / Crash / Corruption)
|
||
|
|
|
||
|
|
### MOD-P0-001: CORS Strict Mode en Production
|
||
|
|
- **ID**: `MOD-P0-001`
|
||
|
|
- **Titre**: CORS strict mode si `CORS_ALLOWED_ORIGINS` vide en production
|
||
|
|
- **Impact**: Service inaccessible depuis frontend si config manquante
|
||
|
|
- **Preuve**: `internal/api/router.go:72-74` - Warning loggé mais service démarre
|
||
|
|
- **Cause**: CORS middleware appliqué avec liste vide (strict mode)
|
||
|
|
- **Fix Minimal**: Fail-fast au démarrage si `CORS_ALLOWED_ORIGINS` vide en production
|
||
|
|
- **Plan Validation**: Démarrer avec `APP_ENV=production CORS_ALLOWED_ORIGINS=""` → doit échouer
|
||
|
|
- **Effet de Bord**: Service ne démarre pas si config manquante (acceptable)
|
||
|
|
- **Effort**: S (1h)
|
||
|
|
|
||
|
|
### MOD-P0-002: Secrets dans Logs si DEBUG
|
||
|
|
- **ID**: `MOD-P0-002`
|
||
|
|
- **Titre**: `LOG_LEVEL=DEBUG` en production peut exposer secrets
|
||
|
|
- **Impact**: Fuite de données sensibles
|
||
|
|
- **Preuve**: `internal/config/config.go:651` - Validation interdit DEBUG en prod, mais si contourné
|
||
|
|
- **Cause**: Logs DEBUG peuvent contenir config complète
|
||
|
|
- **Fix Minimal**: Ajouter redaction automatique secrets dans logs DEBUG
|
||
|
|
- **Plan Validation**: Démarrer avec `LOG_LEVEL=DEBUG`, vérifier logs → secrets masqués
|
||
|
|
- **Effet de Bord**: Debugging plus difficile (acceptable)
|
||
|
|
- **Effort**: S (2h)
|
||
|
|
|
||
|
|
### MOD-P0-003: Dockerfile Production Chemin Incorrect
|
||
|
|
- **ID**: `MOD-P0-003`
|
||
|
|
- **Titre**: `Dockerfile.production` référence `./main.go` au lieu de `./cmd/api/main.go`
|
||
|
|
- **Impact**: Build échoue si utilisé
|
||
|
|
- **Preuve**: `Dockerfile.production:30` - `./main.go` n'existe pas
|
||
|
|
- **Cause**: Chemin incorrect
|
||
|
|
- **Fix Minimal**: Corriger chemin vers `./cmd/api/main.go`
|
||
|
|
- **Plan Validation**: `docker build -f Dockerfile.production .` → doit build
|
||
|
|
- **Effet de Bord**: Aucun
|
||
|
|
- **Effort**: S (5min)
|
||
|
|
|
||
|
|
## P1 — MAJEUR (Bugs / Dette / Tests)
|
||
|
|
|
||
|
|
### MOD-P1-001: Tests d'Intégration Échouent
|
||
|
|
- **ID**: `MOD-P1-001`
|
||
|
|
- **Titre**: Tests d'intégration échouent avec testcontainers PostgreSQL
|
||
|
|
- **Impact**: Tests d'intégration non fiables
|
||
|
|
- **Preuve**: `tests/transactions/social_transaction_test.go:23` - erreur testcontainers
|
||
|
|
- **Cause**: Testcontainers PostgreSQL ne démarre pas correctement
|
||
|
|
- **Fix Minimal**: Vérifier configuration testcontainers, ajouter retry/backoff
|
||
|
|
- **Plan Validation**: `go test ./tests/transactions -v` → doit passer
|
||
|
|
- **Effet de Bord**: Tests peuvent être plus lents
|
||
|
|
- **Effort**: M (4h)
|
||
|
|
|
||
|
|
### MOD-P1-002: Pas de Rollback Automatique Migrations
|
||
|
|
- **ID**: `MOD-P1-002`
|
||
|
|
- **Titre**: Pas de rollback automatique si migration échoue
|
||
|
|
- **Impact**: DB peut être dans état incohérent
|
||
|
|
- **Preuve**: `internal/database/database.go:219` - Migration exécutée sans rollback
|
||
|
|
- **Cause**: Migrations SQL exécutées directement sans transaction
|
||
|
|
- **Fix Minimal**: Exécuter migrations dans transaction, rollback si erreur
|
||
|
|
- **Plan Validation**: Créer migration invalide, démarrer → doit rollback
|
||
|
|
- **Effet de Bord**: Aucun (sécurité)
|
||
|
|
- **Effort**: M (4h)
|
||
|
|
|
||
|
|
### MOD-P1-003: Risque N+1 Queries
|
||
|
|
- **ID**: `MOD-P1-003`
|
||
|
|
- **Titre**: Risque N+1 queries dans certains handlers
|
||
|
|
- **Impact**: Performance dégradée, charge DB excessive
|
||
|
|
- **Preuve**: Audit nécessaire, exemples probables: `/api/v1/tracks` charge user pour chaque track
|
||
|
|
- **Cause**: Pas de `Preload()` GORM ou joins dans certains handlers
|
||
|
|
- **Fix Minimal**: Auditer handlers, ajouter `Preload("User")` ou joins SQL
|
||
|
|
- **Plan Validation**: Requête `/api/v1/tracks` avec 100 tracks → doit faire < 5 queries DB
|
||
|
|
- **Effet de Bord**: Aucun (optimisation)
|
||
|
|
- **Effort**: M (6h)
|
||
|
|
|
||
|
|
### MOD-P1-004: Pas de Timeout Context dans Tous Handlers
|
||
|
|
- **ID**: `MOD-P1-004`
|
||
|
|
- **Titre**: Pas de timeout context dans tous les handlers
|
||
|
|
- **Impact**: Handlers peuvent bloquer indéfiniment
|
||
|
|
- **Preuve**: Audit nécessaire, certains handlers peuvent ne pas avoir timeout
|
||
|
|
- **Cause**: Pas de timeout context systématique
|
||
|
|
- **Fix Minimal**: Ajouter `context.WithTimeout()` dans tous handlers (30s)
|
||
|
|
- **Plan Validation**: Handler avec DB lente → doit timeout après 30s
|
||
|
|
- **Effet de Bord**: Requêtes lentes seront annulées (comportement attendu)
|
||
|
|
- **Effort**: M (4h)
|
||
|
|
|
||
|
|
### MOD-P1-005: Stack Traces dans Logs Prod
|
||
|
|
- **ID**: `MOD-P1-005`
|
||
|
|
- **Titre**: Stack traces dans logs peuvent exposer info sensible
|
||
|
|
- **Impact**: Info sensible dans logs prod
|
||
|
|
- **Preuve**: `internal/middleware/error_handler.go:145` - `zap.ByteString("stack_trace", debug.Stack())`
|
||
|
|
- **Cause**: Stack traces toujours loggés même en prod
|
||
|
|
- **Fix Minimal**: Logger stack traces seulement si `LOG_LEVEL=DEBUG` ou `APP_ENV=development`
|
||
|
|
- **Plan Validation**: Démarrer en prod, déclencher erreur → logs ne doivent pas contenir stack trace
|
||
|
|
- **Effet de Bord**: Debugging plus difficile en prod (utiliser Sentry)
|
||
|
|
- **Effort**: S (1h)
|
||
|
|
|
||
|
|
### MOD-P1-006: /readyz Échoue si Redis/RabbitMQ Down
|
||
|
|
- **ID**: `MOD-P1-006`
|
||
|
|
- **Titre**: `/readyz` peut échouer si Redis/RabbitMQ down (même en dev)
|
||
|
|
- **Impact**: Service marqué "not ready" même si DB OK
|
||
|
|
- **Preuve**: `internal/handlers/health.go:143-159`
|
||
|
|
- **Cause**: Health check strict pour tous services
|
||
|
|
- **Fix Minimal**: Tolérance en non-prod, ou marquer service comme "degraded" au lieu de "not ready"
|
||
|
|
- **Plan Validation**: Démarrer sans Redis, `/readyz` → doit retourner 200 ou 503 avec status "degraded"
|
||
|
|
- **Effet de Bord**: Service peut être marqué "degraded" au lieu de "ready"
|
||
|
|
- **Effort**: S (1h)
|
||
|
|
|
||
|
|
## P2 — MOYEN (Qualité / Maintenabilité / Perf Non Critique)
|
||
|
|
|
||
|
|
### MOD-P2-001: 25+ TODOs/FIXMEs dans Code
|
||
|
|
- **ID**: `MOD-P2-001`
|
||
|
|
- **Titre**: 25+ occurrences de TODO/FIXME/HACK/XXX dans code
|
||
|
|
- **Impact**: Dette technique, code incomplet
|
||
|
|
- **Preuve**: `grep -r "TODO|FIXME|HACK|XXX" --include="*.go"` → 25+
|
||
|
|
- **Cause**: Code en développement, TODOs non résolus
|
||
|
|
- **Fix Minimal**: Auditer tous TODOs, prioriser, résoudre ou créer tickets
|
||
|
|
- **Plan Validation**: Liste TODOs documentée, tickets créés
|
||
|
|
- **Effet de Bord**: Aucun
|
||
|
|
- **Effort**: M (4h)
|
||
|
|
|
||
|
|
### MOD-P2-002: 2 Points d'Entrée Créent Confusion
|
||
|
|
- **ID**: `MOD-P2-002`
|
||
|
|
- **Titre**: 2 points d'entrée (`cmd/api/main.go`, `cmd/modern-server/main.go`)
|
||
|
|
- **Impact**: Développeurs peuvent utiliser le mauvais point d'entrée
|
||
|
|
- **Preuve**: `cmd/api/main.go`, `cmd/modern-server/main.go`
|
||
|
|
- **Cause**: Migration/refactoring partiel
|
||
|
|
- **Fix Minimal**: Documenter ou supprimer `cmd/modern-server/main.go`
|
||
|
|
- **Plan Validation**: Vérifier que seul `cmd/api/main.go` est utilisé
|
||
|
|
- **Effet de Bord**: Aucun
|
||
|
|
- **Effort**: S (1h)
|
||
|
|
|
||
|
|
### MOD-P2-003: Gestion Erreurs Incohérente
|
||
|
|
- **ID**: `MOD-P2-003`
|
||
|
|
- **Titre**: Certains handlers retournent `gin.H{"error": "..."}` au lieu de `AppError`
|
||
|
|
- **Impact**: Incohérence format erreur
|
||
|
|
- **Preuve**: Audit nécessaire, certains handlers
|
||
|
|
- **Cause**: Migration partielle vers `AppError`
|
||
|
|
- **Fix Minimal**: Refactoriser tous handlers pour utiliser `AppError`
|
||
|
|
- **Plan Validation**: Tous handlers retournent `AppError`
|
||
|
|
- **Effet de Bord**: Aucun
|
||
|
|
- **Effort**: M (6h)
|
||
|
|
|
||
|
|
### MOD-P2-004: Métriques DB Pool Manquantes
|
||
|
|
- **ID**: `MOD-P2-004`
|
||
|
|
- **Titre**: Métriques DB pool pas exposées (connections, wait time)
|
||
|
|
- **Impact**: Monitoring limité
|
||
|
|
- **Preuve**: Pas de métriques pool dans `/api/v1/metrics`
|
||
|
|
- **Cause**: Métriques non implémentées
|
||
|
|
- **Fix Minimal**: Exposer métriques `database/sql` stats
|
||
|
|
- **Plan Validation**: `/api/v1/metrics` contient métriques pool
|
||
|
|
- **Effet de Bord**: Aucun
|
||
|
|
- **Effort**: S (1h)
|
||
|
|
|
||
|
|
### MOD-P2-005: Headers Sécurité Manquants
|
||
|
|
- **ID**: `MOD-P2-005`
|
||
|
|
- **Titre**: Headers sécurité manquants (HSTS, CSP, X-Frame-Options, etc.)
|
||
|
|
- **Impact**: Sécurité renforcée manquante
|
||
|
|
- **Preuve**: Pas de middleware sécurité avec headers
|
||
|
|
- **Cause**: Headers non implémentés
|
||
|
|
- **Fix Minimal**: Ajouter middleware sécurité avec headers recommandés
|
||
|
|
- **Plan Validation**: Headers présents dans réponses HTTP
|
||
|
|
- **Effet de Bord**: Aucun
|
||
|
|
- **Effort**: S (2h)
|
||
|
|
|
||
|
|
### MOD-P2-006: Pas de Retry sur Requêtes HTTP Externes
|
||
|
|
- **ID**: `MOD-P2-006`
|
||
|
|
- **Titre**: Pas de retry sur requêtes HTTP externes (Chat Server, Stream Server)
|
||
|
|
- **Impact**: Échecs temporaires non récupérés
|
||
|
|
- **Preuve**: Pas de retry dans `internal/services/stream_service.go`
|
||
|
|
- **Cause**: Retry non implémenté
|
||
|
|
- **Fix Minimal**: Ajouter retry avec backoff exponentiel
|
||
|
|
- **Plan Validation**: Requête avec service down → doit retry 3 fois
|
||
|
|
- **Effet de Bord**: Latence augmentée en cas d'échec
|
||
|
|
- **Effort**: M (3h)
|
||
|
|
|
||
|
|
### MOD-P2-007: Pas de Circuit Breakers
|
||
|
|
- **ID**: `MOD-P2-007`
|
||
|
|
- **Titre**: Pas de circuit breakers implémentés
|
||
|
|
- **Impact**: Service peut être surchargé si dépendances lentes
|
||
|
|
- **Preuve**: Pas de circuit breakers dans code
|
||
|
|
- **Cause**: Circuit breakers non implémentés
|
||
|
|
- **Fix Minimal**: Intégrer `sony/gobreaker` ou similaire
|
||
|
|
- **Plan Validation**: Service lent → circuit breaker s'ouvre après seuil
|
||
|
|
- **Effet de Bord**: Service peut rejeter requêtes si dépendance down
|
||
|
|
- **Effort**: M (4h)
|
||
|
|
|
||
|
|
### MOD-P2-008: File I/O Synchrone
|
||
|
|
- **ID**: `MOD-P2-008`
|
||
|
|
- **Titre**: File I/O synchrone (peut bloquer goroutines)
|
||
|
|
- **Impact**: Performance dégradée sur uploads
|
||
|
|
- **Preuve**: File I/O dans handlers sans goroutines
|
||
|
|
- **Cause**: I/O synchrone
|
||
|
|
- **Fix Minimal**: File I/O asynchrone (goroutines pour uploads)
|
||
|
|
- **Plan Validation**: Uploads ne bloquent pas autres requêtes
|
||
|
|
- **Effet de Bord**: Aucun
|
||
|
|
- **Effort**: M (4h)
|
||
|
|
|
||
|
|
### MOD-P2-009: Pas de Versioning API
|
||
|
|
- **ID**: `MOD-P2-009`
|
||
|
|
- **Titre**: Pas de versioning API (toutes routes `/api/v1/*`)
|
||
|
|
- **Impact**: Breaking changes difficiles
|
||
|
|
- **Preuve**: Toutes routes dans `/api/v1`
|
||
|
|
- **Cause**: Versioning non prévu
|
||
|
|
- **Fix Minimal**: Prévoir versioning pour futures versions
|
||
|
|
- **Plan Validation**: Documentation versioning
|
||
|
|
- **Effet de Bord**: Aucun (planification)
|
||
|
|
- **Effort**: S (2h)
|
||
|
|
|
||
|
|
### MOD-P2-010: Couverture Tests Non Mesurée
|
||
|
|
- **ID**: `MOD-P2-010`
|
||
|
|
- **Titre**: Couverture tests non mesurée systématiquement
|
||
|
|
- **Impact**: Qualité tests inconnue
|
||
|
|
- **Preuve**: Pas de métrique couverture dans CI/CD
|
||
|
|
- **Cause**: Couverture non intégrée
|
||
|
|
- **Fix Minimal**: Ajouter `make test-coverage` dans CI/CD
|
||
|
|
- **Plan Validation**: CI/CD affiche couverture
|
||
|
|
- **Effet de Bord**: Aucun
|
||
|
|
- **Effort**: S (1h)
|
||
|
|
|
||
|
|
## P3 — MINEUR (Cosmétique / Refactors Non Urgents)
|
||
|
|
|
||
|
|
### MOD-P3-001: Fichiers Backup UUID Migration
|
||
|
|
- **ID**: `MOD-P3-001`
|
||
|
|
- **Titre**: Fichiers backup UUID migration présents (`.backup-pre-uuid-migration/`)
|
||
|
|
- **Impact**: Confusion, code mort
|
||
|
|
- **Preuve**: `internal/models/.backup-pre-uuid-migration/`, `internal/services/.backup-pre-uuid-migration/`
|
||
|
|
- **Cause**: Backup non supprimé après migration
|
||
|
|
- **Fix Minimal**: Supprimer fichiers backup si migration complétée
|
||
|
|
- **Plan Validation**: Fichiers backup supprimés
|
||
|
|
- **Effet de Bord**: Aucun
|
||
|
|
- **Effort**: S (5min)
|
||
|
|
|
||
|
|
### MOD-P3-002: Code Mort (simple_main.go)
|
||
|
|
- **ID**: `MOD-P3-002`
|
||
|
|
- **Titre**: `cmd/simple_main.go` présent mais non utilisé
|
||
|
|
- **Impact**: Confusion
|
||
|
|
- **Preuve**: `cmd/simple_main.go` existe
|
||
|
|
- **Cause**: Code de test/demo non supprimé
|
||
|
|
- **Fix Minimal**: Supprimer si non utilisé
|
||
|
|
- **Plan Validation**: Fichier supprimé
|
||
|
|
- **Effet de Bord**: Aucun
|
||
|
|
- **Effort**: S (5min)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
# PHASE G — PLAN D'EXÉCUTION
|
||
|
|
|
||
|
|
## Checklist P0 (Ordre Strict)
|
||
|
|
|
||
|
|
1. ✅ **MOD-P0-003**: Corriger `Dockerfile.production` chemin (5min)
|
||
|
|
2. ⚠️ **MOD-P0-001**: CORS strict mode - Fail-fast ou documenter (1h)
|
||
|
|
3. ⚠️ **MOD-P0-002**: Redaction secrets dans logs DEBUG (2h)
|
||
|
|
|
||
|
|
**Total P0**: ~3h
|
||
|
|
|
||
|
|
## Checklist P1 (Par Lots Cohérents)
|
||
|
|
|
||
|
|
### Lot 1: Tests & Robustesse (8h)
|
||
|
|
1. **MOD-P1-001**: Fix tests d'intégration testcontainers (4h)
|
||
|
|
2. **MOD-P1-002**: Rollback automatique migrations (4h)
|
||
|
|
|
||
|
|
### Lot 2: Performance & Timeouts (10h)
|
||
|
|
3. **MOD-P1-003**: Fix N+1 queries (6h)
|
||
|
|
4. **MOD-P1-004**: Timeout context dans tous handlers (4h)
|
||
|
|
|
||
|
|
### Lot 3: Observabilité (2h)
|
||
|
|
5. **MOD-P1-005**: Stack traces conditionnels (1h)
|
||
|
|
6. **MOD-P1-006**: /readyz tolérance Redis/RabbitMQ (1h)
|
||
|
|
|
||
|
|
**Total P1**: ~20h
|
||
|
|
|
||
|
|
## Quick Wins (≤ 1h chacun)
|
||
|
|
|
||
|
|
1. **MOD-P0-003**: Dockerfile production chemin (5min)
|
||
|
|
2. **MOD-P1-005**: Stack traces conditionnels (1h)
|
||
|
|
3. **MOD-P1-006**: /readyz tolérance (1h)
|
||
|
|
4. **MOD-P2-004**: Métriques DB pool (1h)
|
||
|
|
5. **MOD-P2-010**: Couverture tests CI/CD (1h)
|
||
|
|
6. **MOD-P3-001**: Supprimer fichiers backup UUID (5min)
|
||
|
|
7. **MOD-P3-002**: Supprimer simple_main.go (5min)
|
||
|
|
|
||
|
|
**Total Quick Wins**: ~5h
|
||
|
|
|
||
|
|
## Tests à Ajouter en Priorité
|
||
|
|
|
||
|
|
1. **Tests E2E**: Scénarios complets (auth → upload → playlist)
|
||
|
|
2. **Tests de Charge**: k6 scripts (présents mais non exécutés)
|
||
|
|
3. **Tests Race Conditions**: `go test -race ./...` dans CI/CD
|
||
|
|
4. **Tests Sécurité**: Injection SQL, XSS, path traversal
|
||
|
|
|
||
|
|
## PR Plan (Découpe en PRs Petites)
|
||
|
|
|
||
|
|
### PR 1: Fix P0 Critiques (3h)
|
||
|
|
- MOD-P0-003: Dockerfile production
|
||
|
|
- MOD-P0-001: CORS strict mode
|
||
|
|
- MOD-P0-002: Redaction secrets
|
||
|
|
|
||
|
|
**Titre**: `fix(security): P0 security fixes (CORS, secrets, Dockerfile)`
|
||
|
|
|
||
|
|
### PR 2: Fix Tests Intégration (4h)
|
||
|
|
- MOD-P1-001: Tests d'intégration testcontainers
|
||
|
|
|
||
|
|
**Titre**: `fix(tests): Fix testcontainers PostgreSQL integration tests`
|
||
|
|
|
||
|
|
### PR 3: Robustesse Migrations (4h)
|
||
|
|
- MOD-P1-002: Rollback automatique migrations
|
||
|
|
|
||
|
|
**Titre**: `feat(db): Add automatic rollback for failed migrations`
|
||
|
|
|
||
|
|
### PR 4: Performance N+1 Queries (6h)
|
||
|
|
- MOD-P1-003: Fix N+1 queries
|
||
|
|
|
||
|
|
**Titre**: `perf(db): Fix N+1 queries in track and playlist handlers`
|
||
|
|
|
||
|
|
### PR 5: Timeouts & Observabilité (6h)
|
||
|
|
- MOD-P1-004: Timeout context handlers
|
||
|
|
- MOD-P1-005: Stack traces conditionnels
|
||
|
|
- MOD-P1-006: /readyz tolérance
|
||
|
|
|
||
|
|
**Titre**: `feat(robustness): Add timeouts and improve observability`
|
||
|
|
|
||
|
|
### PR 6: Quick Wins (5h)
|
||
|
|
- MOD-P2-004: Métriques DB pool
|
||
|
|
- MOD-P2-010: Couverture tests CI/CD
|
||
|
|
- MOD-P3-001: Supprimer fichiers backup
|
||
|
|
- MOD-P3-002: Supprimer simple_main.go
|
||
|
|
|
||
|
|
**Titre**: `chore: Quick wins (metrics, coverage, cleanup)`
|
||
|
|
|
||
|
|
### PR 7: P2 Améliorations (15h)
|
||
|
|
- MOD-P2-001: TODOs audit
|
||
|
|
- MOD-P2-002: Points d'entrée
|
||
|
|
- MOD-P2-003: Gestion erreurs
|
||
|
|
- MOD-P2-005: Headers sécurité
|
||
|
|
- MOD-P2-006: Retry HTTP externes
|
||
|
|
- MOD-P2-007: Circuit breakers
|
||
|
|
- MOD-P2-008: File I/O asynchrone
|
||
|
|
- MOD-P2-009: Versioning API
|
||
|
|
|
||
|
|
**Titre**: `feat: P2 improvements (error handling, security headers, retries, circuit breakers)`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
# BONUS — SPÉCIFICITÉS GO
|
||
|
|
|
||
|
|
## Go-Specific Findings
|
||
|
|
|
||
|
|
**Context Propagation**:
|
||
|
|
- ✅ Context propagé dans handlers → services → repositories
|
||
|
|
- ⚠️ Pas toujours utilisé pour timeouts DB
|
||
|
|
|
||
|
|
**Goroutines**:
|
||
|
|
- ✅ Timeout middleware fixé (pas de leak)
|
||
|
|
- ⚠️ À vérifier: autres goroutines sans cleanup
|
||
|
|
|
||
|
|
**Error Wrapping**:
|
||
|
|
- ✅ `fmt.Errorf("...: %w", err)` utilisé
|
||
|
|
- ✅ `errors.Is()` / `errors.As()` supporté
|
||
|
|
|
||
|
|
**Database**:
|
||
|
|
- ✅ GORM utilisé (ORM)
|
||
|
|
- ✅ Raw SQL paramétrisé (`$1, $2, ...`)
|
||
|
|
- ✅ Pool configuré correctement
|
||
|
|
|
||
|
|
**Testing**:
|
||
|
|
- ✅ `testify/assert` utilisé
|
||
|
|
- ✅ Testcontainers pour intégration
|
||
|
|
- ⚠️ Tests d'intégration échouent (à fixer)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
# CONCLUSION
|
||
|
|
|
||
|
|
## Résumé Exécutif
|
||
|
|
|
||
|
|
Le module `veza-backend-api` est **globalement en bon état** avec une architecture solide, une sécurité renforcée (JWT strict, ClamAV, RBAC), et une observabilité correcte (structured logging, Prometheus, Sentry).
|
||
|
|
|
||
|
|
**Points Forts**:
|
||
|
|
- ✅ Sécurité: JWT validation stricte, CORS configuré, ClamAV intégré
|
||
|
|
- ✅ Observabilité: Logging structuré, metrics, healthchecks
|
||
|
|
- ✅ Architecture: Structure claire, séparation des responsabilités
|
||
|
|
- ✅ Tests: 229 fichiers de tests (34% ratio)
|
||
|
|
|
||
|
|
**Points d'Amélioration**:
|
||
|
|
- ⚠️ Tests d'intégration échouent (testcontainers)
|
||
|
|
- ⚠️ Risque N+1 queries dans certains handlers
|
||
|
|
- ⚠️ Timeouts partiels dans handlers
|
||
|
|
- ⚠️ 25+ TODOs/FIXMEs dans code
|
||
|
|
|
||
|
|
**Priorités**:
|
||
|
|
1. **P0**: 3 items (~3h) - Sécurité critique
|
||
|
|
2. **P1**: 6 items (~20h) - Bugs, robustesse, performance
|
||
|
|
3. **P2**: 10 items (~30h) - Qualité, maintenabilité
|
||
|
|
4. **P3**: 2 items (~10min) - Nettoyage
|
||
|
|
|
||
|
|
**Effort Total Estimé**: ~53h (P0+P1+P2)
|
||
|
|
|
||
|
|
## Recommandations
|
||
|
|
|
||
|
|
1. **Immédiat**: Fixer P0 items (sécurité)
|
||
|
|
2. **Court terme**: Fixer P1 items (tests, robustesse, performance)
|
||
|
|
3. **Moyen terme**: Traiter P2 items (qualité, maintenabilité)
|
||
|
|
4. **Long terme**: Planifier versioning API, circuit breakers, retries
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Fin du Rapport**
|