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