veza/docs/AUDIT_TECHNIQUE_V0803.md
senke 72d40990c5
Some checks failed
Backend API CI / test-unit (push) Failing after 0s
Backend API CI / test-integration (push) Failing after 0s
Frontend CI / test (push) Failing after 0s
Storybook Audit / Build & audit Storybook (push) Failing after 0s
feat(v0.923): API contract tests, OpenAPI generation, CI type sync check
2026-02-27 20:23:10 +01:00

580 lines
38 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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".