veza/docs/AUDIT_TECHNIQUE_V0803.md

581 lines
38 KiB
Markdown
Raw Normal View History

# AUDIT TECHNIQUE — VEZA MONOREPO
| Champ | Valeur |
|-------|--------|
| **Date** | 2026-02-26 |
| **Auditeur** | Claude 4.6 Opus — Architecte senior / Expert sécurité |
| **Version analysée** | v0.803 (tag 2026-02-25) |
| **Périmètre** | Go backend, Rust stream server, React frontend, Infrastructure |
| **Méthodologie** | Audit statique exhaustif du code source, 6 passes parallèles |
| **Classification** | Confidentiel — Usage interne |
---
## EXECUTIVE SUMMARY
### Verdict global
Veza est un projet **techniquement ambitieux et remarquablement structuré** pour ce qui semble être une petite équipe. Avec **435 833 LOC** répartis sur 3 langages (Go, TypeScript, Rust), 26 versions taguées, ~353 features déclarées, et une infrastructure CI/CD complète, le volume de travail est impressionnant.
Cependant, l'audit révèle un **décalage significatif entre l'ambition fonctionnelle et la maturité de production**. Le produit n'est **pas prêt pour un déploiement commercial** en l'état — principalement en raison de vulnérabilités de sécurité identifiées, d'un flux OAuth cassé, et d'un ratio features/tests qui reflète une priorité donnée à la couverture fonctionnelle plutôt qu'à la robustesse.
### Top 5 risques
1. **CRITIQUE** — Le flux OAuth génère des JWT invalides qui ne passent pas l'auth middleware → OAuth login cassé
2. **ÉLEVÉ**`PasswordService.GenerateJWT` crée des tokens sans issuer/audience/token_version → contournement potentiel si utilisé hors contexte
3. **ÉLEVÉ** — Absence de PKCE dans le flux OAuth → vulnérable à l'interception de code d'autorisation
4. **ÉLEVÉ** — Tokens OAuth providers stockés en clair en base → compromission des comptes liés si la DB fuite
5. **ÉLEVÉ** — Vérification des webhooks Hyperswitch désactivable quand le secret est vide → forgery de webhooks de paiement possible
### Top 5 forces
1. **Architecture backend exemplaire** — Séparation handler/service/repository, middleware chain complète, configuration validée par environnement
2. **Sécurité proactive** — httpOnly cookies, CSRF Redis-based, security headers complets, account lockout, bcrypt cost 12, CSP stricte
3. **Infrastructure CI/CD mature** — 14 workflows GitHub Actions, Trivy, CodeQL, Gitleaks, govulncheck, cargo-audit, cosign signing
4. **Frontend bien structuré** — Feature-based architecture, Zustand + TanStack Query, 306 Storybook stories, 196 MSW endpoints, Zod validation
5. **Ops-ready** — Kubernetes manifests avec network policies, Prometheus/Grafana, External Secrets Operator, blue-green deployment
### Recommandation GO / NO-GO
**NO-GO pour production commerciale en l'état.** GO conditionnel après correction des 5 vulnérabilités critiques/élevées (effort estimé : 2-3 jours) et validation du flux OAuth end-to-end.
---
## 1⃣ CARTOGRAPHIE GLOBALE
### 1.1 Stack réelle
| Élément | Valeur vérifiée | Commentaire |
|---------|----------------|-------------|
| **Go** | 1.24.0 (`go.mod`) | Dernière stable, OK |
| **Rust** | 2021 edition, stable toolchain (`rust-toolchain.toml`) | OK |
| **TypeScript** | 5.9.3 (`package.json`) | Dernière stable, OK |
| **React** | 18.2.0 | Stable, pas encore React 19 |
| **Vite** | 7.1.5 | Dernière version |
| **Gin** | 1.11.0 | Framework web Go, maintenu |
| **Axum** | 0.8 | Framework web Rust, maintenu |
| **GORM** | 1.30.0 | ORM Go, dernière version |
| **SQLx** | 0.8 | Query builder Rust, runtime mode (pas offline) |
| **PostgreSQL** | 16-alpine | Dernière LTS, extensions: `pg_trgm`, `uuid-ossp` |
| **Redis** | 7-alpine | Dernière stable |
| **RabbitMQ** | 3-management-alpine | Message queue, optionnel |
| **MinIO** | S3-compatible storage | Object storage |
| **JWT** | `golang-jwt/v5` (Go), `jsonwebtoken 10` (Rust) | HS256, 5 min access / 14 jours refresh |
| **Paiement** | Hyperswitch (`Juspay/hyper.js 2.1.0`) | SDK frontend, webhook HMAC-SHA512 |
| **Streaming** | HLS réel (FFmpeg transcoding, `m3u8-rs`) | Pas un stub |
| **WebSocket** | `coder/websocket` (Go), `tokio-tungstenite` (Rust) | Chat en Go, streaming en Rust |
| **WebRTC** | Signalisation uniquement dans le chat store | Pas de TURN/STUN configuré |
| **CI/CD** | GitHub Actions, 14 workflows | Complet |
| **Docker** | Multi-stage, alpine, non-root | Bonnes pratiques suivies |
| **Monitoring** | Prometheus + Grafana + alerting | Configuré et dashboardé |
### 1.2 Organisation du monorepo
| Dossier | Rôle réel | Fichiers estimés | Couplage |
|---------|-----------|-----------------|----------|
| `apps/web/` | Frontend React SPA | ~2000+ | Consomme l'API Go via REST |
| `veza-backend-api/` | API REST Go — cœur du produit | ~1111 | PostgreSQL, Redis, RabbitMQ, S3 |
| `veza-stream-server/` | Serveur de streaming HLS + WebSocket | ~109 RS | PostgreSQL, Redis, gRPC vers backend |
| `veza-common/` | Bibliothèque Rust partagée | ~28 RS | Importée par stream-server |
| `veza-docs/` | Site Docusaurus | - | Indépendant |
| `packages/` | Packages npm partagés | - | Workspace npm |
| `k8s/` | Manifests Kubernetes | ~50+ | Référence les images Docker |
| `config/` | Configs Docker, Prometheus, Grafana | ~20 | Référencé par docker-compose |
| `migrations/` | Migrations SQL (racine) | ~90 | Dupliqué dans `veza-backend-api/migrations/` |
| `docs/` | Documentation technique | ~50+ | Indépendant |
| `make/` | Modules Makefile | ~10 | Orchestration build |
| `scripts/` | Scripts utilitaires | ~10 | Outillage |
| `fixtures/` | Données de test | - | Tests uniquement |
| `loadtests/` | Scripts de charge | - | Tests uniquement |
| `proto/` | Définitions Protobuf | ~5 | gRPC entre Go et Rust |
**Packages orphelins identifiés :**
- `veza-docs/` — Site Docusaurus, potentiellement non déployé (pas référencé dans CI/CD principal)
- `sub_task_agents/` — Documentation d'agents, pas du code
**Packages fantômes identifiés :**
- `veza-chat-server/`**ABSENT** du repo malgré des mentions dans la documentation et les `.cursorrules`. Le chat a été migré vers le backend Go en v0.502 (confirmé dans `PROJECT_STATE.md`)
**Duplications :**
- Le dossier `migrations/` existe à la racine ET dans `veza-backend-api/migrations/` — risque de désynchronisation
### 1.3 Métriques de taille
| Service | LOC | Test files | Stories | Ratio test/code |
|---------|-----|-----------|---------|----------------|
| **Go backend** | 184 501 | 292 | - | ~1:1.6 (élevé) |
| **React frontend** | 211 929 | 299 | 306 | ~1:1.4 (élevé) |
| **Rust stream** | 39 403 | 6 | - | ~1:43 (faible) |
| **TOTAL** | **435 833** | **597** | **306** | - |
### 1.4 Schémas de flux critiques
```mermaid
graph TB
subgraph "Auth Flow"
A[Frontend] -->|POST /auth/login| B[Go API]
B -->|Validate credentials| C[PostgreSQL]
B -->|Check lockout| D[Redis]
B -->|Set httpOnly cookies| A
A -->|Auto-send cookies| B
B -->|Verify JWT + Session| D
end
```
```mermaid
graph TB
subgraph "Upload & Playback Flow"
A[Frontend] -->|POST /uploads| B[Go API]
B -->|ClamAV scan| C[Virus Scanner]
B -->|Store file| D[MinIO S3]
B -->|Queue transcode| E[RabbitMQ]
E -->|Consume job| F[Go Worker]
F -->|FFmpeg transcode| G[HLS Segments]
G -->|Store segments| D
H[Frontend Player] -->|GET /stream/:id| I[Rust Stream Server]
I -->|Validate token| J[PostgreSQL]
I -->|Serve HLS| H
end
```
```mermaid
graph TB
subgraph "Payment Flow"
A[Frontend] -->|POST /commerce/cart/checkout| B[Go API]
B -->|Create payment| C[Hyperswitch]
C -->|Webhook| B
B -->|Verify HMAC-SHA512| D{Signature OK?}
D -->|Yes| E[Update Order]
D -->|No| F[Reject]
end
```
**Points de défaillance unique (SPOF) identifiés :**
- **PostgreSQL** — Pas de réplication configurée dans docker-compose. Single instance.
- **Redis** — Utilisé pour CSRF, rate limiting, sessions, cache, presence. Si Redis tombe, les utilisateurs sont déconnectés et ne peuvent plus faire de requêtes mutantes (CSRF fail-secure → 503).
- **RabbitMQ** — Optionnel (fallback in-process), bon design.
- **MinIO** — Storage des fichiers audio. Pas de réplication visible.
**Timeouts :**
- HTTP server : 30s read/write ✅
- Request middleware timeout : configuré ✅
- `exec.CommandContext` : context-based ✅
- Redis operations : timeout configuré ✅
- External HTTP calls : à vérifier cas par cas
---
## 2⃣ CE QUE LE PRODUIT PERMET RÉELLEMENT
### 2.1 Classification des features
#### ✅ Fonctionnelles (backend + frontend + DB + MSW)
| Feature | Backend | Frontend | DB | Tests |
|---------|---------|----------|-----|-------|
| Auth (register, login, JWT, refresh) | ✅ Complet | ✅ Complet | ✅ Migrations 010-020 | ✅ |
| 2FA (TOTP) | ✅ Complet | ✅ Complet | ✅ Migration MFA | ✅ |
| Sessions management | ✅ Complet | ✅ Complet | ✅ Migration 020 | ✅ |
| Track CRUD + upload | ✅ Complet | ✅ Complet | ✅ Migration 030-040 | ✅ |
| HLS Streaming | ✅ Réel (FFmpeg) | ✅ HLS.js | ✅ Migration 040 | ✅ |
| Playlists (CRUD, collab, share) | ✅ Complet | ✅ Complet | ✅ Migrations 044 | ✅ |
| Search (pg_trgm) | ✅ Complet | ✅ Complet | ✅ Migration 048-085 | ✅ |
| Notifications | ✅ Complet | ✅ Complet | ✅ Migration 047 | ✅ |
| Chat (WebSocket, Go) | ✅ Migré en Go | ✅ Complet | ✅ Migration 051+ | ✅ |
| Social (feed, posts, groups) | ✅ Complet | ✅ Complet | ✅ Migrations 069-070 | ✅ |
| Marketplace (products, orders) | ✅ Complet | ✅ Complet | ✅ Migrations + Hyperswitch | ✅ |
| Cloud Storage (files, folders, quota) | ✅ Complet | ✅ Complet | ✅ Migrations 105-106 | ✅ |
| Gear/Inventory | ✅ Complet | ✅ Complet | ✅ Migrations 076+ | ✅ |
| Analytics (creator dashboard) | ✅ Complet | ✅ Complet | ✅ Migration 081 | ✅ |
| Admin panel | ✅ Complet | ✅ Complet | ✅ | ✅ |
| Developer portal (API keys, webhooks) | ✅ Complet | ✅ Complet | ✅ Migrations 075, 082 | ✅ |
| RBAC (roles, permissions) | ✅ Complet | ✅ Complet | ✅ Migration 021 | ✅ |
| Audit logs | ✅ Complet | ✅ Admin UI | ✅ Migration 910 | ✅ |
| Feature flags (DB-backed) | ✅ Complet | ✅ Admin UI | ✅ Migration 935 | ✅ |
#### ⚠️ Partiellement implémentées
| Feature | État | Détail |
|---------|------|--------|
| **OAuth** | Backend ⚠️ | `generateJWT` produit des tokens invalides (manque issuer/audience). Le flux OAuth callback est probablement cassé. |
| **Live Streaming** | Backend ✅, Frontend ⚠️ | Routes API complètes, UI existante, mais pas de serveur RTMP/WebRTC de diffusion réel |
| **WebRTC Audio Calls** | Frontend store ✅ | Signalisation dans le chat store, mais pas de TURN/STUN server configuré. P2P audio non fonctionnel en conditions réseau réelles. |
| **Cloud file versioning** | ✅ Backend + DB | Frontend stories en cours (fichier modifié dans git status) |
| **Stripe Connect** | Backend ✅ | Seller onboarding, transfers, balance — mais Hyperswitch SDK côté frontend (pas Stripe Elements) |
#### 👻 Features fantômes
| Feature | Déclarée dans | Réalité |
|---------|--------------|---------|
| **Studio** | Anciennes versions | Explicitement retiré du scope (FEATURE_STATUS.md) |
| **Education** | Anciennes versions | Explicitement retiré du scope |
| **Gamification** | FEATURE_STATUS.md | "MSW-only" — mocks existent, pas de backend |
| **veza-chat-server** (Rust) | `.cursorrules`, docs | Répertoire absent. Chat migré en Go v0.502. Documentation pas mise à jour. |
#### 💀 Code mort identifié
| Élément | Localisation | LOC estimé |
|---------|-------------|-----------|
| `PasswordService.GenerateJWT` | `password_service.go:260-267` | 8 LOC — Jamais appelé hors tests |
| Routes `/internal/tracks/:id/stream-ready` | `routes_core.go` | Marquées "deprecated" |
| Routes `/internal/stream-events` | `routes_core.go` | Marquées "deprecated" |
| `TokenBlacklist` service | `token_blacklist.go` | ~100 LOC — Implémenté mais non connecté au middleware auth |
| Références au chat-server Rust | `.cursorrules`, docs | Documentation obsolète |
### 2.2 Incohérences produit/code
1. **`.cursorrules` mentionne `veza-chat-server`** avec des instructions de compilation (`cargo build --release`) — ce service n'existe plus depuis v0.502.
2. **`.cursorrules` mentionne "Chat Server: ❌ Erreurs compilation SQLx"** — service supprimé.
3. **`VERSION` file dit `0.101.0`** mais le projet est en `v0.803` selon CHANGELOG et git tags — incohérence de versioning.
4. **Dockerfile dev utilise Go 1.23** mais `go.mod` et Dockerfile.production utilisent Go 1.24 — incohérence de version.
---
## 3⃣ VALIDATION FONCTIONNELLE
### 3.1 Couverture de tests
| Service | Test files | LOC test estimé | Tests désactivés | Commentaire |
|---------|-----------|----------------|-----------------|-------------|
| **Go backend** | 292 | ~55 000 | ~134 `t.Skip` | Majorité conditionnels (infra-dependent), pas hard-disabled |
| **React frontend** | 299 | ~45 000 | 12 `test.skip` | E2E principalement, conditionnels |
| **Rust stream** | 6 | ~3 000 | 0 | Couverture très faible |
| **Storybook** | 306 stories | - | - | Excellente couverture UI |
**Points positifs :**
- 897 artefacts de test au total
- Go : ratio test/code ~1:3.3 → bon
- Frontend : tests unitaires + E2E Playwright + Storybook + MSW → pipeline complet
- 196 endpoints MSW mockés → couverture quasi-totale des API calls
**Points négatifs :**
- Rust stream server : 6 fichiers de test pour 109 fichiers source → risque élevé de régressions
- 134 tests Go conditionnellement skippés → la couverture effective dépend de l'infrastructure de test
- Pas de tests de contrat API formalisés (pas d'OpenAPI validation automatique)
### 3.2 Points de rupture probables
| Scénario | Risque | Impact |
|----------|--------|--------|
| Redis down | ÉLEVÉ | CSRF → 503 sur toutes les requêtes mutantes. Sessions non validables. Rate limiting dégradé (fallback in-memory). |
| 10K tracks pour un utilisateur | MOYEN | Pagination implémentée, mais ORDER BY dynamique + OFFSET peut devenir lent. Cursor-based pagination absente. |
| Fichier audio de 10GB uploadé | FAIBLE | Taille max validée par `UploadValidator`. ClamAV scanner en place. |
| 1000 WebSocket simultanées | MOYEN | Go chat: goroutines, devrait tenir. Rust stream: `websocket.rs` a un connection manager mais pas de test de charge prouvé. |
| Webhook Hyperswitch en triple | FAIBLE | Les orders ont des statuts idempotents. Pas de déduplication explicite par webhook ID visible. |
| Token expiré mid-session | FAIBLE | Refresh token flow implémenté. Axios interceptor pour auto-refresh. httpOnly cookies. |
| Migration qui échoue à moitié | MOYEN | Pas de transactions explicites visibles autour des migrations. Pas de `BEGIN/COMMIT` wrapper. |
---
## 4⃣ AUDIT DE SÉCURITÉ
### Registre des vulnérabilités
| ID | Catégorie | Gravité | Fichier(s) | Description | Impact | Correctif | Effort |
|----|-----------|---------|-----------|-------------|--------|-----------|--------|
| **VEZA-SEC-001** | A07 Auth | **CRITIQUE** | `oauth_service.go:585-593` | `generateJWT` crée un JWT sans `iss`, `aud`, `token_version`, `session_id`. Ce token échoue à la validation dans `auth.go:191` (version mismatch) et possiblement `auth.go:166` (claims parsing). | OAuth login probablement non fonctionnel. Si un consommateur accepte ces tokens sans validation complète, contournement d'auth possible. | Remplacer par un appel à `JWTService.GenerateAccessToken()` + `GenerateRefreshToken()` avec création de session. | M |
| **VEZA-SEC-002** | A07 Auth | **ÉLEVÉ** | `password_service.go:260-267` | `GenerateJWT` crée un token 24h sans issuer/audience/token_version. Bien que non appelé en production (aucun appel trouvé hors tests), sa présence est un risque si un développeur l'utilise par erreur. | Contournement potentiel des contrôles de sécurité si utilisé. | Supprimer cette méthode ou la faire passer par `JWTService`. | S |
| **VEZA-SEC-003** | A07 Auth | **ÉLEVÉ** | `oauth_service.go:252` | Pas de PKCE (Proof Key for Code Exchange) dans le flux OAuth. Authorization Code flow sans PKCE. | Vulnérable à l'interception du code d'autorisation sur des clients publics (SPA). | Implémenter PKCE (S256). Ajouter `code_verifier` / `code_challenge`. | M |
| **VEZA-SEC-004** | A02 Crypto | **ÉLEVÉ** | `oauth_service.go:577-579` | `access_token` et `refresh_token` des providers OAuth stockés en clair dans `federated_identities`. | Si la base est compromise, l'attaquant a accès aux comptes OAuth liés (Google, GitHub, etc.). | Chiffrer les tokens au repos avec une clé de chiffrement séparée (AES-GCM). | M |
| **VEZA-SEC-005** | A08 Integrity | **ÉLEVÉ** | `hyperswitch/routes_webhooks.go:65-73` | Si `HyperswitchWebhookSecret` est vide, la vérification de signature est sautée (log warn seulement). En dev/staging, un attaquant peut forger des webhooks de paiement. | Création de commandes frauduleuses, confirmation de paiements non effectués. | Rendre la vérification obligatoire dans tous les environnements, ou bloquer les webhooks si le secret n'est pas configuré. | S |
| **VEZA-SEC-006** | A03 Injection | **MOYEN** | `waveform_service.go:72,82` | `inputPath` passé directement à `exec.CommandContext` sans appel à `ValidateExecPath()`. D'autres services (transcode, backup, export) l'appellent systématiquement. | Si `inputPath` contient des caractères spéciaux, path traversal possible (pas command injection car pas de shell). | Ajouter `utils.ValidateExecPath(inputPath)` avant les appels `exec.CommandContext`. | S |
| **VEZA-SEC-007** | A04 Design | **MOYEN** | `token_blacklist.go`, `auth.go` | Le `TokenBlacklist` service est implémenté (Redis-backed, SHA-256 hashed) mais n'est **jamais appelé** dans le middleware d'auth. La révocation repose uniquement sur `TokenVersion`. | Impossible de révoquer un token spécifique — seule la révocation de tous les tokens d'un utilisateur (via token version increment) est possible. | Connecter `TokenBlacklist.IsBlacklisted()` dans `authenticate()` après la validation JWT. | S |
| **VEZA-SEC-008** | A04 Design | **MOYEN** | `ratelimit.go:49-50` | `/auth/login` et `/auth/register` sont exclus du rate limiter global (100 req/min par IP). Ils ont des rate limiters endpoint-spécifiques (5/15min login, 3/h register) mais pas le plafond global. | Un attaquant peut potentiellement contourner la protection globale en ciblant ces endpoints. Les limites endpoint-spécifiques restent en place. | Appliquer le rate limiter global en amont des rate limiters spécifiques, ou documenter le choix. | S |
| **VEZA-SEC-009** | A02 Crypto | **FAIBLE** | `config.go:293` | `CHAT_JWT_SECRET` fallback au `JWT_SECRET` principal. Si non configuré séparément, un JWT crafté pour le chat pourrait être accepté par l'API principale (si les claims matchent). | Escalade potentielle entre services. | Documenter ou forcer des secrets séparés. | S |
| **VEZA-SEC-010** | A07 Auth | **FAIBLE** | `oauth_service.go` | Pas de validation whitelist pour l'URL de redirection OAuth post-callback. | Open redirect potentiel après OAuth. | Valider l'URL de redirection contre une whitelist de domaines autorisés. | S |
### Points de sécurité positifs (bonnes pratiques confirmées)
| Domaine | Implémentation | Fichier |
|---------|---------------|---------|
| **Tokens** | httpOnly cookies, non accessibles depuis JS | `tokenStorage.ts` (no-op class), backend sets cookies |
| **Passwords** | bcrypt cost 12, min 12 chars, complexity rules, 72-byte limit enforced | `password_service.go:23,311` |
| **JWT** | HS256 algorithm pinning, 5 min TTL, issuer/audience validation, token version | `jwt_service.go:126-131,37` |
| **CSRF** | Redis-backed, 32-byte random, timing-safe comparison, fail-secure | `csrf.go:131,115-127` |
| **CORS** | Wildcard blocked in production, credentials-aware, origin reflection | `cors.go:29,125` |
| **Headers** | HSTS, CSP, X-Frame-Options DENY, COEP, COOP, CORP, Permissions-Policy | `security_headers.go` |
| **Rate limiting** | Multi-layer (global IP, per-endpoint, per-user), Redis with in-memory fallback | `ratelimit*.go`, `endpoint_limiter.go` |
| **Account lockout** | 5 attempts / 15 min, 30 min lockout, fail-secure | `account_lockout_service.go` |
| **File upload** | ClamAV scanning, type validation, concurrent limiting, fail-secure (503) | `upload.go:182-197` |
| **SQL** | Parameterized queries throughout, ORDER BY fields whitelisted | `user_service_search.go:147-155` |
| **Exec** | `ValidateExecPath()` on most services, context-based exec | `utils/sanitizer.go:29-43` |
| **Secrets** | No hardcoded secrets, env vars required, masking in logs | `config.go`, `secrets.go` |
| **Audit** | Comprehensive audit middleware for sensitive actions | `middleware/audit.go` |
| **Bypass protection** | `validateNoBypassFlagsInProduction` blocks CSRF_DISABLED, DISABLE_RATE_LIMIT | `config/validation.go` |
| **Frontend XSS** | No `dangerouslySetInnerHTML`, DOMPurify available, no localStorage for tokens | Grep results |
| **Docker** | Non-root users (UID 1001), minimal alpine bases, health checks | All Dockerfiles |
---
## 5⃣ DETTE TECHNIQUE
### 5.1 Registre de la dette
| Cat. | Description | Impact | Fichier(s) | Effort |
|------|------------|--------|-----------|--------|
| 🔴 | OAuth `generateJWT` produit des tokens invalides | OAuth login cassé | `oauth_service.go:585` | M |
| 🔴 | `TokenBlacklist` déconnecté de l'auth | Révocation granulaire impossible | `token_blacklist.go` | S |
| 🟠 | Rust stream server : 6 fichiers de test pour 109 sources | Régressions non détectées | `veza-stream-server/src/` | L |
| 🟠 | 134 tests Go conditionnellement skippés (infra-dependent) | Couverture effective incertaine sans CI complet | `*_test.go` | XL |
| 🟠 | `veza-chat-server` référencé dans `.cursorrules` mais absent | Confusion pour nouveaux développeurs | `.cursorrules` | S |
| 🟠 | VERSION file (0.101.0) incohérent avec CHANGELOG (v0.803) | Confusion de versioning | `VERSION` | S |
| 🟠 | Migrations : 122 fichiers, numérotation non contiguë (001→122 puis 900→935) | Consolidation nécessaire avant scaling de l'équipe | `migrations/` | L |
| 🟠 | 40 fichiers Go > 500 lignes | Complexité, maintenabilité réduite | Voir liste section 3 | L |
| 🟡 | `docs.go` généré : 5482 lignes | Swagger spec dans le code source, alourdit le repo | `docs/docs.go` | S |
| 🟡 | Duplication `migrations/` racine vs `veza-backend-api/migrations/` | Risque de désynchronisation | Racine + backend | S |
| 🟡 | Go 1.23 dans Dockerfile dev vs 1.24 dans go.mod et Dockerfile.production | Comportement différent dev/prod | Dockerfiles | S |
| 🟡 | 21 TODO/FIXME/HACK dans le codebase | Minor mais à nettoyer | Distribués | S |
| 🟡 | Pas de cursor-based pagination | Performance dégradée sur grands datasets avec OFFSET | Services de listing | M |
| ⚪ | `soundcloud/` directory dans Rust stream server | Purpose unclear, naming confusion with SoundCloud brand | `veza-stream-server/src/soundcloud/` | S |
### 5.2 Quantification
| Métrique | Go | TypeScript | Rust | Total |
|----------|-----|-----------|------|-------|
| **LOC** | 184 501 | 211 929 | 39 403 | **435 833** |
| **LOC mort estimé** | ~200 | ~500 (generated types) | ~3000 (generated protobuf + soundcloud) | **~3 700** |
| **Fichiers de test** | 292 | 299 | 6 | **597** |
| **Stories** | - | 306 | - | **306** |
| **TODO/FIXME/HACK** | 9 | 8 | 4 | **21** |
| **Fichiers > 500 lignes** | 40 (1 generated) | 20 (1 generated) | 19 (1 generated) | **79** |
| **Dépendances directes** | ~35 | 82 (35 prod + 47 dev) | ~60 | **177** |
### 5.3 Hétérogénéité Go + Rust
Le choix de Go pour le backend API et Rust pour le streaming est **architecturalement justifié** :
- Go excelle en HTTP/REST APIs avec GORM, handlers, middleware
- Rust est pertinent pour le traitement audio temps-réel et HLS
Cependant, le chat server Rust a été migré en Go (v0.502), validant que Rust n'était pas nécessaire pour le WebSocket chat. La réduction à 2 langages (Go + Rust stream) est rationnelle.
Le coût réel : deux toolchains, deux CI pipelines, deux sets de dépendances à maintenir. Pour une équipe < 3 devs, c'est un overhead significatif.
---
## 6⃣ QUALITÉ ARCHITECTURALE
### 6.1 Monorepo
| Critère | Évaluation |
|---------|-----------|
| **Outil** | Turbo 2.3.0 + npm workspaces |
| **Build** | Parallélisable via Turbo, outputs cachés |
| **Versioning** | Incohérent (VERSION file ≠ CHANGELOG tags) |
| **Workspace** | npm workspaces, Cargo workspace partiel |
| **Makefile** | Excellent — 10 modules, orchestration complète |
### 6.2 Frontend
| Critère | Score | Détail |
|---------|-------|--------|
| **Structure** | ✅ | Feature-based, clean separation |
| **State** | ✅ | Zustand + TanStack Query, persist + broadcast sync |
| **Data fetching** | ✅ | TanStack Query avec cache/invalidation |
| **Routing** | ✅ | React Router 6.30, lazy loading, code splitting |
| **Design system** | ✅ | SUMI v2.0, 207+ UI components, Tailwind + CSS tokens |
| **TypeScript** | ✅ | Strict mode probable, minimal `any` usage |
| **Storybook** | ✅ | 306 stories, MSW addon, a11y addon |
| **MSW** | ✅ | 196 endpoints, 11 handler modules, catch-all |
| **Security** | ✅ | httpOnly cookies, no dangerouslySetInnerHTML, DOMPurify, Zod validation |
| **Env validation** | ✅ | Zod schema for env vars |
### 6.3 Backend Go
| Critère | Score | Détail |
|---------|-------|--------|
| **Architecture** | ✅ | Layered: handler → service → repository. Domain-driven (core/auth, core/track, core/marketplace) |
| **Error handling** | ✅ | Wrapped errors, structured responses, recovery middleware |
| **Middleware** | ✅ | 26 middlewares, correct ordering, comprehensive coverage |
| **Database** | ✅ | GORM with connection pooling, parameterized queries, 122 migrations |
| **Concurrency** | ✅ | Context propagation, graceful shutdown manager, goroutine management |
| **Config** | ✅ | Environment-based, validated at startup, production-specific checks |
| **API versioning** | ✅ | `/api/v1/` consistently |
| **OpenAPI** | ⚠️ | Swagger generated (`docs.go`) but not validated against code automatically |
### 6.4 Rust Stream Server
| Critère | Score | Détail |
|---------|-------|--------|
| **Architecture** | ✅ | Modular (auth, streaming, transcoding, codecs, monitoring) |
| **Error handling** | ✅ | Custom `AppError` enum, 30+ variants, `IntoResponse` |
| **Safety** | ✅ | 0 `unsafe` blocks, ~15 `expect()` only in initialization |
| **Tests** | ❌ | 6 test files for 109 source files — critical gap |
| **Compilation** | ⚠️ | No `sqlx-data.json` — requires live DB for compilation check |
### 6.5 Base de données
| Critère | Score | Détail |
|---------|-------|--------|
| **Schema** | ✅ | Well-normalized, UUID primary keys, FK constraints |
| **Indexes** | ✅ | `pg_trgm`, composite indexes, performance indexes (migration 920) |
| **Migrations** | ⚠️ | 122 migrations, non-contiguous numbering (1-122, 900-935), no consolidation |
| **Relations** | ✅ | FK constraints, cascades in migration 930 |
| **Redis usage** | ✅ | Cache, CSRF, sessions, rate limiting, presence, blacklist — well-defined roles |
### 6.6 Scorecard
| Dimension | Score | Justification |
|-----------|-------|---------------|
| **Architecture** | **8/10** | Excellente séparation des concerns, patterns cohérents, middleware chain exemplaire. -1 pour OAuth JWT bypass, -1 pour TokenBlacklist déconnecté. |
| **Maintenabilité** | **7/10** | Code lisible, conventions respectées, 21 TODO seulement. -1 pour 79 fichiers > 500 lignes, -1 pour incohérences de version, -1 pour documentation obsolète (chat-server). |
| **Sécurité** | **7/10** | Excellentes pratiques (httpOnly, bcrypt, CSRF, CSP, rate limiting). -1 pour OAuth cassé, -1 pour PKCE absent, -1 pour tokens OAuth en clair. |
| **Scalabilité** | **6/10** | Architecture horizontalement scalable en théorie. -1 pour SPOF PostgreSQL/Redis, -1 pour OFFSET pagination, -1 pour 134 tests conditionnels, -1 pour Rust tests insuffisants. |
| **Testabilité** | **7/10** | 897 artefacts de test, pipeline complet. -1 pour Rust coverage, -1 pour tests infra-dependent, -1 pour pas de contrat API formel. |
| **Opérabilité** | **8/10** | Prometheus, Grafana, alerting, structured logging, health checks, K8s manifests, blue-green. -1 pour monitoring chat non couvert, -1 pour pas de runbook opérationnel complet. |
| **Vélocité dev** | **7/10** | Makefile complet, MSW, Storybook, hot reload. -1 pour 3 langages, -1 pour onboarding multi-toolchain, -1 pour documentation incohérente. |
| **Maturité produit** | **6/10** | 19 features opérationnelles, 5 partielles, 4 fantômes. -1 pour OAuth cassé, -1 pour WebRTC non fonctionnel, -1 pour live streaming partiel, -1 pour gamification fantôme. |
**Score moyen : 7.0 / 10**
---
## 7⃣ INFRA & DEVOPS
### 7.1 Docker
| Critère | Status |
|---------|--------|
| **Multi-stage builds** | ✅ Tous les services |
| **Images de base** | ✅ Alpine (Go, Rust, Node, Nginx) |
| **Non-root** | ✅ UID 1001 partout |
| **Health checks** | ✅ Configurés |
| **Secrets en build args** | ✅ Aucun — env vars au runtime |
| **Taille optimisée** | ✅ Static binaries, stripped |
| **ClamAV** | ⚠️ Installé dans l'image backend — augmente la taille |
### 7.2 CI/CD
| Critère | Status |
|---------|--------|
| **Lint** | ✅ ESLint, Clippy, gofmt, go vet |
| **Tests** | ✅ Unit + integration + E2E + Storybook |
| **Security scanning** | ✅ Gitleaks, CodeQL, Trivy, govulncheck, cargo-audit, npm audit |
| **Container scanning** | ✅ Trivy CRITICAL/HIGH |
| **SBOM** | ✅ CycloneDX |
| **Signing** | ✅ Cosign (configurable) |
| **Deployment** | ✅ Blue-green via docker-compose.prod.yml |
| **Environments** | ✅ Dev, staging, production séparés |
| **Secrets** | ✅ GitHub Secrets + External Secrets Operator (Vault) |
| **Pre-commit** | ✅ Husky hooks (typecheck, lint, tests) |
### 7.3 Reproductibilité
| Critère | Status |
|---------|--------|
| **Single command build** | ✅ `make dev` ou `docker compose up` |
| **Lock files** | ✅ `go.sum`, `Cargo.lock`, `package-lock.json` |
| **Toolchain pinning** | ✅ `rust-toolchain.toml`, Go version in `go.mod` |
| **Onboarding doc** | ✅ `ONBOARDING.md` existe |
---
## 8⃣ PERFORMANCE & SCALABILITÉ
| Composant | Risque | Seuil estimé | Mitigation |
|-----------|--------|-------------|------------|
| **PostgreSQL** | N+1 queries possibles via GORM | > 5K req/min | GORM `Preload` utilisé, mais à profiler |
| **Redis** | SPOF pour CSRF/sessions/rate-limit | Si Redis down → 503 global | Sentinelle ou cluster non configuré |
| **Chat WebSocket (Go)** | Goroutine per connection | > 5K connexions simultanées | Goroutine-safe, mais backpressure à valider |
| **Stream server** | HLS segment serving | > 500 streams simultanés | Rust + Tokio devrait tenir, mais 6 tests |
| **File storage (MinIO)** | Single instance | > 5TB | Pas de réplication configurée |
| **OFFSET pagination** | O(n) scan | > 100K records | Migrer vers cursor-based pagination |
**Scalabilité horizontale :**
- ✅ Backend Go : stateless (sessions en Redis), scalable
- ✅ Frontend : statique, CDN-ready
- ⚠️ Stream server : WebSocket = session affinity nécessaire
- ⚠️ Chat : WebSocket = session affinity nécessaire
- ❌ PostgreSQL : single instance, pas de sharding
- ❌ Redis : single instance
---
## 9⃣ RISQUES BUSINESS
### 9.1 Verdict catégorique
| Question | Réponse | Justification |
|----------|---------|---------------|
| Peut-on lancer en production tel quel ? | **NON** | OAuth cassé, webhook verification optionnelle, TokenBlacklist déconnecté |
| Peut-on vendre/monétiser tel quel ? | **NON** | Flux de paiement dépend de Hyperswitch webhook non vérifié en staging. OAuth non fonctionnel empêche le social login. |
| Peut-on maintenir avec 2 devs ? | **Conditionnel** | Oui si Go + TS. Le Rust stream server est un risque si le dev Rust part. |
| Faut-il refactorer avant prod ? | **OUI** | Corriger les 5 vulnérabilités, consolider les migrations, connecter le TokenBlacklist |
| Faut-il réécrire certains services ? | **NON** | L'architecture est saine. Corrections ciblées suffisent. |
| La vélocité (353 features) est-elle un red flag ? | **Attention** | Le volume est impressionnant mais le ratio features/tests sur le Rust server et la présence de features fantômes suggèrent que certaines "features" sont des endpoints avec MSW mocks mais pas de validation E2E réelle. |
### 9.2 Point de vue investisseur
| Question | Réponse |
|----------|---------|
| Le produit est-il fonctionnel ou une démo ? | **Fonctionnel** pour 80% des features. Les 19 features opérationnelles ont du code backend réel, des migrations, des handlers, des services, des tests. Ce n'est pas un prototype Figma ni du mock-only. |
| Risques d'incident public ? | **Oui** — les tokens OAuth providers en clair et le webhook payment non vérifié sont exploitables. Correctifs estimés à 2-3 jours. |
| Code repris par une autre équipe ? | **Oui** avec 2-3 semaines d'onboarding. Architecture claire, conventions cohérentes, documentation existante. La multi-stack Go+Rust+TS nécessite des profils polyvalents. |
| Coût pour v1.0 production-ready ? | **4-8 semaines** pour corrections sécurité + tests Rust + consolidation migrations + monitoring complet + load testing. |
| IP technique défendable ? | **Oui** — le pipeline HLS complet (upload → transcode → streaming), le système de chat WebSocket intégré, le marketplace avec Hyperswitch, et le système d'analytics constituent une plateforme cohérente. |
| Ratio features/qualité ? | **Quantité priorisée** sur la qualité pour le stream server Rust (6 tests). Backend Go et frontend React ont un bon équilibre. |
### 9.3 Score de rachetabilité
**7/10** — Code bien structuré, architecture claire, documentation existante. Points de friction : multi-stack (3 langages), 122 migrations à comprendre, quelques incohérences documentaires.
---
## 🔟 PLAN D'ACTION PRIORISÉ
### Phase 1 — Critique (semaines 1-2)
| # | Action | Pourquoi | Fichiers | Effort |
|---|--------|----------|---------|--------|
| 1 | **Corriger OAuth `generateJWT`** — utiliser `JWTService.GenerateAccessToken()` + créer une session | OAuth login cassé | `oauth_service.go:585-593`, `oauth_service.go:307` | M (1-2j) |
| 2 | **Supprimer `PasswordService.GenerateJWT`** | Code mort à risque | `password_service.go:260-267` | S (<1j) |
| 3 | **Rendre webhook Hyperswitch verification obligatoire** dans tous les envs | Forgery de paiement possible | `routes_webhooks.go:65-73` | S (<1j) |
| 4 | **Connecter `TokenBlacklist` au middleware auth** | Révocation granulaire non fonctionnelle | `auth.go`, `token_blacklist.go` | S (<1j) |
| 5 | **Ajouter `ValidateExecPath` dans `waveform_service.go`** | Path traversal sur FFmpeg | `waveform_service.go:72,82` | S (<1j) |
| 6 | **Chiffrer les tokens OAuth providers au repos** | Compromission DB = accès aux comptes liés | `oauth_service.go:577-579` | M (1-2j) |
### Phase 2 — Stabilisation (semaines 3-6)
| # | Action | Pourquoi | Effort |
|---|--------|----------|--------|
| 7 | **Implémenter PKCE dans le flux OAuth** | OWASP A07 compliance | M |
| 8 | **Ajouter des tests au Rust stream server** — objectif 50% coverage | 6 tests pour 109 fichiers = risque | XL |
| 9 | **Valider l'URL de redirection OAuth** contre whitelist | Open redirect prevention | S |
| 10 | **Harmoniser VERSION file** avec les tags git | Confusion de versioning | S |
| 11 | **Mettre à jour `.cursorrules`** — retirer les références au chat-server Rust | Documentation obsolète | S |
| 12 | **Harmoniser Go version** dans tous les Dockerfiles (1.24) | Comportement dev ≠ prod | S |
| 13 | **Load testing du stream server** sous charge (1000 connexions WebSocket) | Pas de preuve de performance | L |
### Phase 3 — Consolidation (semaines 7-12)
| # | Action | Pourquoi | Effort |
|---|--------|----------|--------|
| 14 | **Consolider les migrations** — squash 1-122 en un schéma initial | 122 migrations = lent au setup, risque d'erreur | L |
| 15 | **Implémenter cursor-based pagination** sur les listings à volume | OFFSET O(n) ne scale pas | L |
| 16 | **Configurer Redis Sentinel/Cluster** pour HA | Redis = SPOF pour auth/CSRF | M |
| 17 | **Refactorer les 10 fichiers Go > 1000 lignes** | Complexité, maintenabilité | L |
| 18 | **Tests de contrat API** — valider OpenAPI spec contre le code | Drift API documentation | M |
| 19 | **Configurer PostgreSQL replication** | SPOF pour toutes les données | L |
| 20 | **Déduplication des migrations** racine vs backend | Source unique de vérité | S |
### Phase 4 — Évolution (mois 4+)
| # | Action | Effort |
|---|--------|--------|
| 21 | WebRTC avec TURN/STUN pour audio calls | XL |
| 22 | Live streaming réel (RTMP ingestion) | XL |
| 23 | Gamification (backend, pas juste MSW) | L |
| 24 | Multi-region deployment | XL |
| 25 | CDN pour assets audio | M |
---
## CONCLUSION STRATÉGIQUE
Veza est un projet **techniquement solide dans sa conception** mais qui souffre d'un déséquilibre classique des projets early-stage : **trop de features, pas assez de profondeur sur chacune**. L'architecture est saine, les patterns sont cohérents, la sécurité est proactive dans 90% des cas — mais les 10% restants contiennent des vulnérabilités exploitables.
Le **backend Go est le point fort** du projet : layered architecture, 292 test files, middleware chain exemplaire, configuration validée. Le **frontend React** est également bien structuré avec son approche Storybook-first et ses 306 stories. Le **Rust stream server** est le point faible : fonctionnel mais insuffisamment testé (6 fichiers de test).
**Recommandation : Investir, mais conditionné à la correction des 6 actions Phase 1 (2-3 jours de travail).** Le coût de mise en production complète est estimé à 4-8 semaines. Le rapport qualité/ambition est favorable pour un projet de cette taille. L'architecture ne nécessite pas de réécriture — des corrections ciblées suffisent.
La question stratégique n'est pas technique mais organisationnelle : **cette vélocité est-elle soutenable ?** 26 versions en quelques mois avec une petite équipe suggère soit une productivité exceptionnelle, soit une accumulation de dette invisible. L'audit montre que la dette est **quantifiable et gérable** (21 TODO, ~3700 LOC mortes, 79 fichiers volumineux) — ce n'est pas un projet en perdition technique, c'est un projet qui a besoin de passer du mode "sprint feature" au mode "hardening for production".