veza/AUDIT_TECHNIQUE_VEZA_2026-03-04.md
2026-03-05 19:22:31 +01:00

58 KiB

AUDIT TECHNIQUE — VEZA MONOREPO

Champ Valeur
Date 2026-03-04
Auditeur Claude (Architecte IA) — Audit indépendant pour due diligence
Version analysée v1.0.2 (commit a007f4c7, 2026-03-03)
Périmètre Backend Go, Stream Server Rust, Frontend React, Infrastructure
Méthodologie Analyse statique exhaustive du code source, 6 passes
Classification Confidentiel — Usage interne

EXECUTIVE SUMMARY

Verdict global

Veza est un projet techniquement ambitieux et structurellement solide pour un projet de cette taille, mais qui présente des risques critiques empêchant un déploiement production immédiat sans correction. Le codebase totalise ~610K LOC réparties sur 3 langages (Go, Rust, TypeScript), ce qui est considérable et soulève des questions de maintenabilité pour une petite équipe.

Recommandation : GO CONDITIONNEL

Le projet peut être lancé en production après correction des 6 vulnérabilités critiques identifiées (estimé 2-3 semaines). Le socle architectural est sain, les bonnes pratiques de sécurité sont globalement respectées, et l'infrastructure de déploiement (Docker, CI/CD, blue-green) est mature.

Top 5 des risques

# Risque Gravité Impact
1 340+ unwrap()/expect() dans le stream server Rust — crash en production sous charge Critique Indisponibilité du streaming audio
2 Secret JWT par défaut dans veza-common — fallback exploitable si env var manquante Critique Compromission de tous les tokens
3 Webhook worker non enregistré dans le shutdown manager — fuite de goroutine Elevée Perte de webhooks au redéploiement
4 Incohérence politique mot de passe frontend (8 chars) vs backend (12 chars) Moyenne UX dégradée, faux sentiment de sécurité
5 ~500 LOC de code WebRTC mort avec dépendance commentée Moyenne Dette technique, confusion

Top 5 des forces

# Force Preuve
1 Architecture backend propre — séparation handler → service → repository veza-backend-api/internal/
2 Sécurité auth solide — httpOnly cookies, JWT HS256, bcrypt cost 12, rate limiting multi-couche middleware/auth.go, security_headers.go
3 CI/CD mature — 14 workflows GitHub Actions couvrant govulncheck, cargo audit, npm audit, E2E .github/workflows/
4 Storybook-first — 300 stories avec MSW, couverture des états (loading, error, empty) apps/web/src/**/*.stories.tsx
5 Infrastructure production-ready — blue-green HAProxy, health checks, resource limits, monitoring docker-compose.prod.yml

Scorecard rapide

Dimension Score
Architecture 7/10
Maintenabilité 5/10
Sécurité 7/10
Scalabilité 5/10
Testabilité 7/10
Opérabilité 7/10
Vélocité dev 4/10
Maturité produit 6/10

1. CARTOGRAPHIE GLOBALE

1.1 Stack réelle

Élément Version / Détail Statut
Go 1.24.0 (go.mod) Courant (released Feb 2025)
Rust edition 2021, stable (pas de rust-toolchain.toml) Courant
Node.js 20 (CI setup-node), pas de .nvmrc/.node-version LTS courant
TypeScript 5.9.3 Courant
React ^18.2.0 Stable (React 19 disponible mais non adopté)
Vite ^7.1.5 Courant
Gin 1.11.0 Courant
GORM 1.30.0 Courant
Axum 0.8 Courant
SQLx 0.8 Courant
PostgreSQL 16-alpine Courant
Redis 7-alpine Courant
RabbitMQ 3-management-alpine Courant
Hyperswitch 2025.01.21.0-standalone ~1 an de retard
HAProxy 2.8-alpine Courant LTS
Prometheus (Rust) 0.14 / (Go) client_golang 1.22.0 Courant
JWT golang-jwt/v5 5.3.0 (Go) / jsonwebtoken 10 (Rust) Courant
Bcrypt golang.org/x/crypto (Go) / bcrypt 0.17 (Rust) Courant
Stripe stripe-go/v82 82.5.1 (backup/fallback) Courant
AWS SDK aws-sdk-go-v2 1.41.0 Courant
HLS FFmpeg (externe) + m3u8-rs 5.0 + hls.js 1.6.14 (frontend) Réel
WebRTC Code présent mais webrtc = "0.7" commenté dans Cargo.toml Non fonctionnel
WebSocket coder/websocket 1.8.14 (Go) / tokio-tungstenite 0.21 (Rust) Fonctionnel
Storybook 8.6.15 Courant
MSW 2.11.2 Courant
Playwright 1.58.2 Courant
Vitest 3.2.4 Courant
Tailwind CSS ^4.0.0 Courant
Sentry sentry-go 0.40.0 (backend) / @sentry/react ^10.32.1 Courant
ClamAV clamav/clamav:latest Intégré pour scan antivirus uploads

Constat : Les dépendances sont globalement à jour. Seul Hyperswitch (~1 an de retard) mérite une mise à jour. Pas de dépendances abandonnées identifiées.

1.2 Organisation du monorepo

Outil de gestion : npm workspaces + Turborepo (turbo.json). Configuration minimale — 3 tâches (build, test, lint) avec dépendances ^build. Pas de cache remote configuré.

Répertoire Rôle réel Fichiers LOC Couplage
veza-backend-api/ API REST Go (Gin, GORM, JWT) — coeur métier 778 .go ~188K PostgreSQL, Redis, RabbitMQ, S3
veza-stream-server/ Serveur streaming Rust (Axum, HLS, FFmpeg) 138 .rs ~103K PostgreSQL, Redis, RabbitMQ
veza-common/ Bibliothèque Rust partagée (auth, config, types) 53 .rs ~4.3K Utilisé par stream-server uniquement
apps/web/ Frontend React SPA (Vite, Zustand, TanStack Query) 1887 .ts/.tsx ~211K API backend via Axios, WebSocket
packages/design-system/ Package partagé design system ~10 ~500 Utilisé par apps/web
fixtures/ Fixtures de test (npm package) ~20 ~1K Cross-service test data
config/ Configs déploiement (HAProxy, Prometheus, Grafana, Caddy, SSL) ~30 ~2K Infrastructure
k8s/ Manifestes Kubernetes (10+ sous-dossiers) ~40 yaml ~3K Non déployé (templates)
docs/ Documentation projet (285 fichiers .md) 285 ~15K Référence
loadtests/ Tests de charge k6 (backend, stream, chat) ~15 ~2K Backend, Stream
.github/workflows/ CI/CD (14 workflows) 14 ~600 Tous services
proto/ Définitions Protocol Buffers ~5 ~200 Stream server (gRPC)
scripts/ Scripts utilitaires (déploiement, dev, monitoring) ~25 ~1.5K Tous services
make/ Modules Makefile (config, dev, build, test, services) 11 ~800 Orchestration

Total estimé : ~319K LOC de code source (hors node_modules, target, dist, docs).

Packages orphelins et fantômes

Répertoire Statut Détail
chat_exports/ Orphelin 15 fichiers, artefacts de chat export. Aucune référence dans le code.
sub_task_agents/ Orphelin 15 fichiers de documentation IA. Aucun code exécutable.
tmt/ Orphelin 18 fichiers de config test management. Pas d'intégration CI.
full_veza_audit_data/ Orphelin 7 fichiers de données d'audit passé.
veza-docs/ Partiellement orphelin Site Docusaurus non intégré dans les workflows CI.
k8s/chat-server/ Fantôme Manifestes pour veza-chat-server supprimé en v0.502. Image Docker inexistante.
Makefile.old Mort Ancien Makefile remplacé par make/*.mk.

Duplications cross-packages : Les types d'authentification sont définis séparément dans Go (internal/services/jwt_service.go), Rust (veza-common/src/auth.rs), et TypeScript (src/types/generated/api.ts). Le TypeScript est généré depuis l'OpenAPI spec, mais Go et Rust sont indépendants — source d'incohérences (cf. mismatch issuer/audience Section 4).

Dépendances circulaires : Aucune détectée. Le flux de dépendances est unidirectionnel : veza-common -> veza-stream-server ; apps/web -> API backend (HTTP).

1.3 Dépendances critiques

Service Deps directes Vulnérabilités CI Deps > 2 ans sans release
Go backend 45 directes + 116 indirectes = 161 govulncheck en CI — 0 identifié Aucune
Rust stream ~78 directes cargo audit en CI — 0 identifié dotenv 0.15 (last: 2020, remplacé par dotenvy)
Frontend 35 deps + 37 devDeps = 72 npm audit --audit-level=critical en CI Aucune

Dépendance préoccupante : dotenv 0.15 dans le stream server Rust est maintenu par un nouveau mainteneur mais la version 0.15 date de 2020. Recommandation : migrer vers dotenvy.

1.4 Schéma des flux

flowchart TB
    subgraph client [Client Browser]
        ReactApp["React SPA<br/>Vite + HLS.js"]
    end
    
    subgraph proxy [Reverse Proxy]
        HAProxy["HAProxy 2.8<br/>Blue-Green"]
    end
    
    subgraph backend [Backend API - Go]
        GinRouter["Gin Router<br/>Middleware Chain"]
        AuthSvc["Auth Service<br/>JWT HS256"]
        TrackSvc["Track Service"]
        MarketSvc["Marketplace Service"]
        SocialSvc["Social Service"]
        ChatWS["Chat WebSocket<br/>Hub Pattern"]
        UploadSvc["Upload Service<br/>ClamAV Scan"]
    end
    
    subgraph stream [Stream Server - Rust]
        AxumRouter["Axum Router"]
        HLSGen["HLS Generator<br/>FFmpeg"]
        TranscodeEng["Transcoding Engine"]
        StreamWS["Stream WebSocket"]
    end
    
    subgraph data [Data Layer]
        PostgreSQL["PostgreSQL 16"]
        Redis["Redis 7"]
        RabbitMQ["RabbitMQ 3"]
        MinIO["MinIO / S3"]
        ClamAV["ClamAV"]
    end
    
    subgraph payments [Payment]
        Hyperswitch["Hyperswitch Router"]
        HyperswitchDB["Hyperswitch PostgreSQL"]
    end
    
    ReactApp -->|"HTTPS"| HAProxy
    HAProxy -->|"/api/v1/*"| GinRouter
    HAProxy -->|"/stream/*"| AxumRouter
    
    GinRouter --> AuthSvc
    GinRouter --> TrackSvc
    GinRouter --> MarketSvc
    GinRouter --> SocialSvc
    GinRouter --> ChatWS
    GinRouter --> UploadSvc
    
    UploadSvc --> ClamAV
    UploadSvc --> MinIO
    TrackSvc --> PostgreSQL
    MarketSvc --> Hyperswitch
    Hyperswitch --> HyperswitchDB
    
    AuthSvc --> PostgreSQL
    AuthSvc --> Redis
    ChatWS --> Redis
    
    AxumRouter --> HLSGen
    AxumRouter --> TranscodeEng
    AxumRouter --> StreamWS
    HLSGen --> MinIO
    
    GinRouter --> RabbitMQ
    AxumRouter --> RabbitMQ
    
    GinRouter --> PostgreSQL
    AxumRouter --> PostgreSQL
    AxumRouter --> Redis

Flux critiques — Points de défaillance

1. Auth Flow (Register -> Login -> JWT -> Refresh)

  • SPOF : PostgreSQL (stockage users/sessions)
  • Timeouts : Configurés (middleware timeout global)
  • Retry : Refresh token automatique côté frontend (intercepteur Axios)
  • Fallback : Rate limiting en mémoire si Redis down
  • Race condition : Token refresh concurrent — géré par mutex dans le frontend interceptor

2. Upload Flow (Frontend -> API -> ClamAV -> S3)

  • SPOF : ClamAV (scan antivirus), MinIO/S3 (stockage)
  • Timeouts : exec.CommandContext avec context pour FFmpeg
  • Retry : Chunked upload avec resume (/tracks/resume/:uploadId)
  • Fallback : CLAMAV_REQUIRED=false permet de bypasser le scan en dev
  • Race condition : Upload concurrent du même fichier — ID unique par upload

3. Playback Flow (Frontend -> Stream Server -> HLS -> Player)

  • SPOF : Stream server Rust (single instance en dev), FFmpeg
  • Timeouts : Non explicitement configurés pour le stream server
  • Retry : hls.js gère les retries nativement
  • Fallback : Dev mode renvoie des segments factices
  • RISQUE : JWT issuer/audience mismatch entre Go et Rust (cf. Section 4)

4. Payment Flow (Frontend -> API -> Hyperswitch -> Webhook)

  • SPOF : Hyperswitch (payment router)
  • Timeouts : HTTP client avec timeout configuré
  • Retry : Webhook delivery avec retry intégré
  • Fallback : HYPERSWITCH_ENABLED=false désactive les paiements
  • Idempotence : Webhook signature HMAC-SHA512 vérifiée

5. Chat Flow (Frontend -> WebSocket -> Go Hub -> Redis PubSub)

  • SPOF : Redis (PubSub, présence)
  • Timeouts : WebSocket ping/pong configuré
  • Retry : Reconnection automatique côté frontend
  • Fallback : Chat fonctionne sans Redis (mode dégradé, pas de cross-instance)
  • Race condition : Messages concurrents gérés par le Hub pattern

2. CE QUE LE PRODUIT PERMET RÉELLEMENT

2.1 Classification des features

Fonctionnelles (flux complet front + back + DB + tests)

Feature Backend Frontend Tests Preuve
Auth (register, login, JWT, refresh, logout) Routes + services + middleware Login/Register pages + authStore 306 test files Go, E2E Playwright routes_core.go, auth.go, jwt_service.go
2FA (TOTP) Setup/Verify/Disable handlers 2FA settings UI Unit tests two_factor_handler.go, two_factor_service.go
OAuth (Google, GitHub, Discord, Spotify) PKCE, circuit breaker OAuth buttons + callback Service tests oauth_service.go
User profiles CRUD, avatar, social links, follow/block Profile pages + components Tests routes_users.go, user_service.go
Upload audio Chunked upload, ClamAV scan, S3 storage Upload components + progress Handler tests upload.go, upload_validator.go
CRUD Tracks Create, read, update, delete, batch ops Track list/detail pages Tests + E2E routes_tracks.go, track/service.go
Playlists CRUD, collaborators, share links, ordering Playlist pages + drag-drop Tests + E2E routes_playlists.go, playlist_service.go
Chat WebSocket Hub pattern, Redis PubSub, presence Chat page + real-time messages Tests websocket/chat/, routes_chat in router.go
Dashboard Stats, analytics Dashboard page + charts (Recharts) Tests dashboard_handler.go
Search Full-text (pg_trgm), suggestions Search page + filters Tests track_search_service.go
Social (posts, feed, groups, follows) CRUD + feed algorithm Social pages + components Tests routes_social.go, social/service.go
Marketplace (products, orders, payments) Hyperswitch integration Product listing + checkout Tests routes_marketplace.go, marketplace/service.go
Notifications Push + in-app Notification center Tests notification_handler.go
Webhooks Delivery, signature, retry Webhook management UI Tests routes_webhooks.go, webhook_service.go
Gear/Inventory CRUD gear items + images Gear pages Tests gear_handler.go
Analytics Playback analytics, aggregation Analytics dashboard Tests playback_analytics_handler.go
Admin (reports, maintenance, flags, transfers) Admin routes + RBAC Admin pages Tests routes_core.go admin section
Sessions management CRUD, logout-all, stats Sessions settings page Tests session_service.go

Partiellement implémentées

Feature Statut Détail
HLS Streaming Backend OK, stream server real FFmpeg Frontend hls.js intégré, mais JWT mismatch Go/Rust empêche l'auth
Live Streaming Routes backend + stream server Frontend pages existent, dépend du stream server
Cloud Storage Backend CRUD + S3 Frontend pages + share links
GDPR Export Backend async export Frontend trigger + download

Fantômes (déclarées mais non fonctionnelles)

Feature Déclarée où Réalité
WebRTC Audio Calls FEATURE_STATUS.md "WebRTC Beta" Code Rust (~500 LOC) mais dépendance webrtc = "0.7" commentée. Signaling seulement, aucun média P2P.
2FA SMS Planifié v0.104 Aucun code SMS trouvé
Passkeys/WebAuthn Planifié v0.104 Aucun code trouvé
Electron Desktop Mentionné dans les règles Aucun code Electron trouvé, .gitignore only

Code mort

Élément LOC estimé Détail
veza-stream-server/src/streaming/webrtc.rs + webrtc/config.rs ~500 WebRTC sans dépendance native, jamais appelable
veza-stream-server/src/soundcloud/ (5 fichiers) ~4000 Discovery, playback, creator, management, social — module "SoundCloud-like" mais aucune route ne l'expose
k8s/chat-server/ ~100 yaml Manifestes pour service supprimé en v0.502
Makefile.old ~200 Ancien Makefile remplacé
chat_exports/, sub_task_agents/, tmt/, full_veza_audit_data/ ~500 Artefacts orphelins
internal/features/features.go 3 Stub vide, feature flags implémentées ailleurs

Total code mort estimé : ~5300 LOC

2.2 Incohérences produit/code

Incohérence Détail Impact
Version annoncée vs réelle Le prompt mentionne "v0.402 Phase 4 Commerce". Le code est v1.0.2. Le projet a significativement avancé depuis le contexte du prompt.
JWT issuer/audience mismatch Go backend émet iss: veza-api, aud: veza-app. Stream server Rust attend iss: veza-platform, aud: veza-services. Les tokens émis par le backend échoueront la validation dans le stream server. HLS auth cassé.
Password policy frontend vs backend Frontend valide 8 chars minimum. Backend rejette < 12 chars. UX confuse : le formulaire accepte, le serveur rejette.
Feature flags runtime internal/features/features.go est un stub vide. Les feature flags sont en DB via admin/feature-flags. Le stub crée de la confusion ; un développeur pourrait l'importer par erreur.
onCreateProduct no-op routeConfig.tsx : onCreateProduct={() => {}} dans le seller dashboard. Le bouton "créer produit" depuis le seller dashboard ne fait rien.

3. VALIDATION FONCTIONNELLE APPROFONDIE

3.1 Couverture de tests

Service Fichiers test Fichiers code Ratio Couverture CI
Go backend 306 *_test.go 472 .go (non-test) 0.65 go test ./... en CI
Rust stream ~90 #[test] fonctions 138 .rs inline cargo test en CI
Frontend unit 273 .test.ts/.tsx 1614 .ts/.tsx (non-test) 0.17 vitest --run en CI
Frontend stories 300 .stories.tsx ~1200 composants 0.25 Storybook build + audit en CI
Frontend E2E 26 .spec.ts - - Playwright avec backend réel

Seuils de couverture frontend (vitest.config.ts) : 50% minimum (branches, functions, lines, statements). Seuil bas mais raisonnable pour un MVP.

Tests désactivés / skip : Aucun skip ou .only trouvé dans le code Go. Pas de .skip systématique dans Vitest.

MSW vs API réelle : ~100% des tests unitaires frontend utilisent MSW. Les 26 tests E2E Playwright utilisent le backend Go réel avec PostgreSQL/Redis en CI.

3.2 Error handling

Backend Go :

  • Pattern principal : RespondWithAppError / RespondWithError avec codes d'erreur structurés
  • Incohérence : ~12 handlers utilisent encore c.JSON(status, gin.H{"error": "..."}) au lieu du pattern standardisé
  • Fichiers concernés : account_deletion_handler.go, comment_handler.go, search_handlers.go, tag_handler.go, sell_handler.go, admin_transfer_handler.go, cloud_handler.go
  • Impact : Réponses d'erreur inconsistantes pour le frontend

Rust stream server :

  • Utilise thiserror pour les types d'erreur custom et anyhow pour la propagation
  • Error handler Axum centralisé via error.rs (783 lignes, complet)

Frontend React :

  • Error boundaries configurés dans le routing
  • Logger custom remplace console.error
  • Intercepteur Axios gère 401 (refresh/logout), 429 (rate limit store), 5xx (retry)

3.3 Validation input

Backend : Double validation — go-playground/validator/v10 pour les structs, validations manuelles dans les services. Password policy stricte (12 chars, complexité, blocklist). File uploads validés par ClamAV.

Frontend : Zod schemas + react-hook-form pour la validation côté client. Env vars validées au démarrage via Zod.

3.4 Pagination

Les listes utilisent offset-based pagination avec page et limit query params. Pas de cursor-based pagination. Limite max non explicitement vérifiée dans tous les handlers — risque de requêtes avec limit=100000.

3.5 Points de rupture probables

Scénario Impact Mitigation
10K tracks dans la DB Requêtes de recherche pg_trgm potentiellement lentes Index GIN configurés (048_search_indexes.sql)
100K users Listes utilisateurs paginées, OK -
1M messages chat Pas de pagination serveur explicite dans le chat Risque : chargement mémoire du Hub
Fichier non-audio uploadé ClamAV scan + validation MIME type Extension validée, magic bytes si ClamAV actif
Fichier > 10GB Pas de limite explicite dans le code d'upload Devrait être configuré au niveau proxy/nginx
1000 WebSocket simultanées Chat Hub en mémoire Go (goroutines légères) OK pour Go, limite Redis PubSub potentielle
Webhook replay (3x même event) ProcessPaymentWebhook idempotent — vérifie statut existant OK
Token expiré mid-session Intercepteur Axios refresh transparent, retry queue OK
Migration échoue à moitié Migrations non transactionnelles (extensions hors transaction) Risque de schéma partiel
Redis down Rate limiting fallback en mémoire, chat dégradé (single-instance) OK mais perte de cross-instance

4. AUDIT DE SÉCURITÉ

4.0 Registre des vulnérabilités

ID Catégorie Gravité Fichier(s) Description Impact Correctif Effort
VEZA-SEC-001 A02 Crypto Critique veza-common/src/config_rust.rs:234 Secret JWT par défaut "your-super-secret-jwt-key" en fallback dans JwtConfig::default() Si un service Rust démarre sans JWT_SECRET env, tous les tokens sont signés avec un secret prévisible Supprimer le default ou panic si absent S
VEZA-SEC-002 A04 Design Critique veza-stream-server/src/auth/mod.rs:150-151 vs veza-backend-api/internal/services/jwt_service.go JWT issuer/audience mismatch : Go émet iss:veza-api, aud:veza-app, Rust attend iss:veza-platform, aud:veza-services Tokens émis par Go invalides dans le stream server. HLS streaming authentifié cassé. Aligner les valeurs iss/aud entre Go et Rust, ou utiliser le stream token dédié M
VEZA-SEC-003 A05 Config Elevée veza-stream-server/src/main.rs:74 shutdown_signal reçoit un nouvel AppState au lieu de celui en cours d'exécution Shutdown ne ferme pas correctement les connexions WebSocket ni l'event bus du state actif Passer le même AppState à shutdown_signal S
VEZA-SEC-004 A04 Design Elevée veza-backend-api/internal/api/routes_webhooks.go:31 Webhook worker goroutine démarré avec context.Background(), non enregistré dans le shutdown manager Goroutine fuite au redéploiement. Webhooks en cours de livraison perdus. Enregistrer dans shutdownManager.Register avec context annulable S
VEZA-SEC-005 A04 Design Moyenne apps/web/src/lib/passwordValidator.ts vs internal/validators/password_validator.go Frontend accepte 8 chars, backend rejette < 12 chars UX confuse, formulaire accepte puis serveur rejette Aligner frontend sur 12 chars min S
VEZA-SEC-006 A05 Config Moyenne Routes /metrics, /metrics/aggregated, /system/metrics Métriques Prometheus exposées publiquement sans auth Information disclosure : un attaquant peut observer les patterns de charge, DB pool, error rates Protéger par auth ou réseau interne en prod S
VEZA-SEC-007 A07 Auth Moyenne veza-backend-api/internal/services/password_reset_service.go:47,73,126,160 Utilisation de context.Background() au lieu du context de la requête Opérations DB non liées au cycle de vie de la requête (timeout ignoré, cancellation ignorée) Propager c.Request.Context() S
VEZA-SEC-008 A04 Design Faible apps/web/src/router/routeConfig.tsx onCreateProduct={() => {}} — callback no-op dans le seller dashboard Bouton visible mais inopérant, UX cassée Connecter au vrai handler de création S
VEZA-SEC-009 A06 Components Faible veza-stream-server/Cargo.toml dotenv 0.15 — dernière release 2020 Dépendance potentiellement non maintenue Migrer vers dotenvy S

4.1 A01 — Broken Access Control

Routes protégées : Exhaustivement auditées (cf. Section 1.4 routes). Toutes les routes de mutation (POST/PUT/DELETE) sont derrière RequireAuth. Les routes admin ajoutent RequireAdmin. Les routes de modification de ressource utilisent RequireOwnershipOrAdmin.

IDOR : Protégé par RequireOwnershipOrAdmin sur users, tracks, playlists, products. Le resolver charge le propriétaire depuis la DB et compare avec userID du JWT.

CORS : Strict en production — whitelist explicite requise, wildcard interdit avec credentials. Validation fail-fast au démarrage.

Rate limiting : Multi-couche (DDoS global 1000 req/s, per-IP 100 req/s, per-endpoint login/register, per-user, upload 10/heure).

WebSocket auth : Chat utilise JWT via header. Stream server utilise query param ?token= — ce token est un stream token dédié à durée courte (5 min), pas le JWT principal.

Verdict A01 : Solide. Pas de faille IDOR identifiée.

4.2 A02 — Cryptographic Failures

Hashing mots de passe : bcrypt cost 12, conforme aux recommandations OWASP (>= 10).

JWT : HS256 (HMAC-SHA256). Secret minimum 32 chars, validé au démarrage. Durée access token : 5 min (court, bon). Refresh token : 14 jours (30 si "remember me"). Token versioning pour révocation.

Secrets en dur : Un seul trouvé en production — veza-common/src/config_rust.rs:234 (cf. VEZA-SEC-001). Les autres sont dans les tests uniquement.

Secrets dans Git : .env correctement dans .gitignore. Pas de secret trouvé dans l'historique Git (validé par les fichiers .env.example).

Données sensibles en clair : Logger Go avec filtrage des secrets (internal/logging/secret_filter.go). Pas de tokens dans les logs.

Verdict A02 : Bon, sauf VEZA-SEC-001.

4.3 A03 — Injection

SQL Injection : GORM utilisé partout en production. Raw SQL uniquement dans les tests (testutils/db.go) avec table whitelist. Pas de fmt.Sprintf dans les requêtes SQL de production.

Command Injection : exec.CommandContext utilisé pour FFmpeg avec ValidateExecPath. Pas d'interpolation de string dans les commandes.

XSS : DOMPurify côté frontend pour dangerouslySetInnerHTML (3 usages, tous sanitisés). Tags autorisés : p, br, strong, em, u, i, b, ul, ol, li, span, a. Attributs interdits : onerror, onload, onclick.

Path Traversal : Noms de fichiers sanitisés dans l'upload service. UUID comme nom de fichier en stockage.

Verdict A03 : Bon. Pas d'injection identifiée.

4.4 A04 — Insecure Design

Principaux risques identifiés :

  • JWT issuer/audience mismatch (VEZA-SEC-002)
  • Webhook worker lifecycle (VEZA-SEC-004)
  • Pagination sans limite max explicite

Business logic : Les ordres de paiement vérifient le statut existant avant de retraiter un webhook (idempotence). Promo codes validés côté serveur. Pas de prix négatif possible (validation struct Go).

Enumeration : Les erreurs de login ne distinguent pas "user inexistant" de "mot de passe incorrect" — conforme aux bonnes pratiques.

4.5 A05 — Security Misconfiguration

Security headers : Complets (HSTS, CSP strict pour API, X-Frame-Options DENY, X-Content-Type-Options nosniff, Referrer-Policy strict-origin-when-cross-origin, Permissions-Policy restrictive).

Debug mode : Swagger désactivé en production. pprof derrière RequireAdmin et uniquement hors production.

CORS : Strict en production. CORSDefault() panic en production pour forcer la configuration explicite.

Docker : Secrets via env avec :? (required). Pas de secrets dans les layers Docker.

Métriques exposées : /metrics public (VEZA-SEC-006).

4.6 A06 — Vulnerable & Outdated Components

CI exécute automatiquement : govulncheck (Go), cargo audit (Rust), npm audit --audit-level=critical (Node). Dependabot configuré. Seule préoccupation : dotenv 0.15 (VEZA-SEC-009).

4.7 A07 — Identification & Authentication Failures

Password policy : 12 chars, complexité, blocklist de 25 mots de passe courants, rejet patterns répétitifs/séquentiels. Robuste.

Brute force : Rate limiting sur /auth/login (configurable AUTH_RATE_LIMIT_LOGIN_ATTEMPTS / AUTH_RATE_LIMIT_LOGIN_WINDOW). Account lockout (ACCOUNT_LOCKOUT_EXEMPT_EMAILS pour tests).

JWT validation : Signature, expiration, issuer, audience vérifiés. Token versioning pour révocation.

Refresh token : Rotation via token versioning. Stockage en httpOnly cookies (pas localStorage). Révocation via token blacklist Redis.

OAuth : State parameter + PKCE. Domaines de redirect en whitelist. Circuit breaker sur les appels externes.

Sessions : Page de gestion des sessions, logout-all, logout-others. Révocation effective via token version.

4.8 A08 — Software & Data Integrity Failures

Webhooks : Hyperswitch HMAC-SHA512 vérifié avec constant-time comparison. Secret vide = 500 (pas de traitement).

File uploads : ClamAV scan obligatoire en production (CLAMAV_REQUIRED=true).

Migrations : Non transactionnelles pour les extensions (CREATE EXTENSION ne supporte pas les transactions dans certains cas). Risque de schéma partiel si une migration échoue.

4.9 A09 — Security Logging & Monitoring

Audit trail : Middleware audit logge les actions POST/PUT/DELETE avec user ID, IP, endpoint, timestamp (audit.go). Logs d'audit consultables via routes admin.

Log level : Configurable. Production interdit LOG_LEVEL=DEBUG (validation config). Filtrage des secrets dans les logs (secret_filter.go).

Request ID : Propagé via middleware request_id.go. Header X-Request-ID dans les réponses.

Monitoring : Prometheus metrics configurées. Alertmanager + Grafana dans le stack production.

4.10 A10 — Server-Side Request Forgery (SSRF)

Pas de SSRF identifié. Le backend ne fait pas de requêtes vers des URLs fournies par l'utilisateur. Les webhooks sortants utilisent des URLs enregistrées par l'utilisateur authentifié — pas de filtrage IP privée, ce qui pourrait théoriquement être exploité pour scanner le réseau interne.

4.11 Sécurité spécifique à la stack

Go :

  • defer correctement utilisé pour les ressources DB et fichiers
  • context.Context propagé dans la majorité des cas (sauf password_reset_service.go)
  • Goroutines avec lifecycle géré via shutdownManager (sauf webhook worker)
  • Pas de race conditions évidentes (Hub pattern thread-safe)

Rust :

  • Aucun bloc unsafe dans le code applicatif
  • ~15-20 unwrap() en production, principalement dans l'initialisation (safe) ou avec fallback unwrap_or
  • panic! dans les env vars requises au démarrage (acceptable)
  • Default::default() pour TokenValidator et Config paniquent en production (gated par cfg(not(debug_assertions)))

React :

  • dangerouslySetInnerHTML : 3 usages, tous avec DOMPurify
  • Tokens : httpOnly cookies, pas de localStorage pour les tokens d'auth
  • console.log : remplacé par logger custom, 0 usage brut en production

5. DETTE TECHNIQUE

5.1 Registre de la dette technique

ID Catégorie Description Impact Fichier(s) Effort
DT-001 Critique JWT issuer/audience mismatch Go/Rust empêche l'auth HLS HLS streaming non fonctionnel en production jwt_service.go, auth/mod.rs M
DT-002 Critique Secret JWT par défaut dans veza-common Faille de sécurité potentielle config_rust.rs:234 S
DT-003 Structurante ~5300 LOC de code mort (WebRTC, soundcloud/, k8s/chat-server, orphelins) Confusion, coût maintenance Multiples M
DT-004 Structurante Error handling inconsistant — 12 handlers utilisent gin.H au lieu de RespondWithAppError Frontend doit gérer 2 formats d'erreur account_deletion_handler.go, etc. M
DT-005 Structurante 139 fichiers > 500 lignes (78 Go, 41 Rust, 20 TS/TSX) Complexité de maintenance track/service.go (1147), marketplace/service.go (1142), etc. L
DT-006 Structurante features.go est un stub vide alors que les feature flags sont en DB Confusion architecturale internal/features/features.go S
DT-007 Structurante shutdown_signal reçoit un nouvel AppState dans main.rs Shutdown ne ferme pas les connexions WebSocket correctement main.rs:74 S
DT-008 Opérationnelle Webhook worker goroutine non enregistré dans le shutdown manager Goroutine leak au redéploiement routes_webhooks.go:31 S
DT-009 Opérationnelle context.Background() dans password_reset_service.go Timeouts ignorés 4 endroits S
DT-010 Opérationnelle Pagination sans limite max — limit=100000 possible Requêtes DB excessives Tous les handlers de liste M
DT-011 Opérationnelle Migrations non transactionnelles Risque de schéma partiel si une migration échoue database/migrations.go L
DT-012 Opérationnelle 335 TODO, 9 FIXME, 12 HACK dans le codebase Indicateur de travail non terminé Répartis sur 3 langages XL
DT-013 Opérationnelle Password policy mismatch frontend/backend UX dégradée passwordValidator.ts, password_validator.go S
DT-014 Opérationnelle onCreateProduct={() => {}} no-op dans routeConfig Bouton seller inopérant routeConfig.tsx S
DT-015 Cosmétique dotenv 0.15 (2020) dans le stream server Rust Dépendance potentiellement non maintenue Cargo.toml S
DT-016 Cosmétique 285 fichiers de documentation — certains obsolètes Surcharge informationnelle docs/ M
DT-017 Cosmétique Makefile.old toujours présent Confusion Racine S

5.2 Métriques de dette

Métrique Valeur
LOC total (code source) ~319K
LOC mort estimé ~5300 (1.7%)
Ratio test/code (Go) 0.65 (306 tests / 472 fichiers code)
Ratio test/code (Frontend) 0.17 (273 tests / 1614 fichiers code)
Stories / Composants 0.25 (300 / ~1200)
Fichiers > 500 lignes 139 (78 Go, 41 Rust, 20 TS/TSX)
TODO/FIXME/HACK 356 total (335 TODO, 9 FIXME, 12 HACK)
Deps directes (tous services) ~195 (45 Go + 78 Rust + 72 Frontend)
Deps avec vulnérabilités connues 0 (CI scanne automatiquement)

5.3 Hétérogénéité Go + Rust

Le choix de Go et Rust est la décision architecturale la plus discutable du projet :

Justification originale (ADR-002) : Le chat server Rust a été migré vers Go en v0.502, reconnaissant que le surcoût de Rust n'était pas justifié pour le chat. Le stream server Rust est conservé pour les performances audio (transcoding, HLS).

Évaluation : Le stream server Rust représente ~103K LOC mais sa valeur ajoutée réelle se limite à l'appel FFmpeg (exec.CommandContext en Go ferait la même chose) et au serving HLS (servir des fichiers statiques n'exige pas Rust). Le code "SoundCloud-like" (~4K LOC dans soundcloud/) n'est pas exposé par les routes.

Coût : Maintenir 2 langages backend (Go + Rust) triple la complexité de recrutement, double les outils CI, et crée des incohérences inter-services (cf. JWT mismatch).

Recommandation : Évaluer la migration du stream server vers Go à moyen terme. À court terme, corriger le JWT mismatch et nettoyer le code mort Rust.


6. QUALITÉ ARCHITECTURALE

6.1 Monorepo

Critère Évaluation
Outil de gestion npm workspaces + Turborepo. Config minimale (3 tâches). Pas de cache remote.
Build orchestration Turbo parallélise build/test/lint. Builds Docker séparés.
Versionning Fichier VERSION à la racine (1.0.2). Pas de versionning par service.
Dépendances internes veza-common (Rust) utilisé par veza-stream-server. packages/design-system par apps/web.
Workspace config npm workspaces (pas pnpm). package-lock.json à la racine.
Makefile Modulaire (11 fichiers dans make/). Cible help disponible.

6.2 Frontend (React/Vite)

Critère Score Détail
Structure 8/10 Feature-based (src/features/, src/components/). Claire et organisée.
State management 8/10 Zustand (6 stores), léger et bien séparé. React Query pour les données serveur.
Data fetching 8/10 TanStack React Query avec Axios. Intercepteurs pour refresh, rate limit, retry.
Routing 7/10 React Router 6 avec lazy loading via LazyComponent. Code splitting configuré dans Vite.
TypeScript 8/10 strict: true avec noUncheckedIndexedAccess. ~150 any restants (principalement tests et generated).
Storybook 8/10 300 stories, MSW intégré, 3 viewports, addon a11y. CI valide le build.
Accessibilité 7/10 ARIA, roles, tabIndex largement utilisés. ESLint jsx-a11y configuré.
Bundle analysis 6/10 Manual chunks dans Vite (React, TanStack, lucide). Rollup visualizer en build.
MSW coverage 9/10 11 handler modules couvrant toutes les features. Catch-all pour les routes non mockées.
DOMPurify 10/10 3 usages de dangerouslySetInnerHTML, tous sanitisés.

6.3 Backend Go

Critère Score Détail
Architecture 8/10 Handler -> Service -> Repository bien séparé. Clean architecture.
Error handling 6/10 Pattern RespondWithAppError existe mais 12 handlers utilisent encore gin.H.
Middleware stack 9/10 15+ middlewares dans le bon ordre. Auth, CORS, rate limit, security headers, CSRF.
Database 8/10 Connection pooling (50 max, 12 idle). Migrations SQL. Read replica supporté.
Concurrency 7/10 Goroutines gérées via shutdownManager (sauf webhook worker). Context propagé.
Configuration 8/10 Env vars avec validation au démarrage. Fail-fast en production. Secrets filtrés.
API versioning 7/10 /api/v1/ partout. VersionMiddleware présent. Pas de plan v2 explicite.
OpenAPI 7/10 Swagger generé (swaggo). Frontend types generées depuis l'OpenAPI spec. Validation types sync en CI.

6.4 Stream Server Rust

Critère Score Détail
HLS 7/10 Réel (FFmpeg). Dev-only fallbacks pour les segments manquants.
WebRTC 1/10 Session management sans stack média. Non fonctionnel.
Compilation 7/10 Build musl static. Cargo.lock versionné. Pas de sqlx-data.json.
Error handling 7/10 thiserror + anyhow. 783 lignes dans error.rs.
Tests 5/10 ~90 tests inline. Pas de tests d'intégration avec DB.
Code mort 3/10 ~4500 LOC dans soundcloud/ + webrtc.rs non exposées.

6.5 Base de données

Critère Évaluation
Schéma 95 migrations, normalisé, UUID primary keys. FK constraints.
Indexes Index GIN pour pg_trgm search. Index composite (049_composite_indexes.sql). Performance indexes (920, 940).
Migrations Numérotation non continue (gap 019-020, 050-060, 066-069, etc.). Down migrations pour certaines seulement.
Redis Cache, rate limiting, sessions, token blacklist, chat PubSub, CSRF tokens, presence. TTL configurés.
N+1 Preload utilisé correctement dans la majorité des cas. 1 risque identifié dans analytics_aggregation_service.go.

6.6 Scores détaillés

Dimension Score Justification
Architecture 7/10 Bonne séparation des concerns. Go clean architecture. Rust plus chaotique (soundcloud/, webrtc dead code). Le choix Go+Rust ajoute de la complexité injustifiée.
Maintenabilité 5/10 139 fichiers > 500 lignes, 356 TODO/FIXME/HACK, error handling inconsistant, 2 langages backend. Documentation abondante (285 docs) mais parfois obsolète.
Sécurité 7/10 httpOnly cookies, bcrypt cost 12, rate limiting multi-couche, security headers complets, CSRF, ClamAV. Mais : JWT secret default (VEZA-SEC-001), issuer mismatch (VEZA-SEC-002).
Scalabilité 5/10 Single instance par service, pas de load balancer inter-service (sauf HAProxy). Redis SPOF. PostgreSQL sans réplication configurée (read replica supporté mais non déployé). Pas de sharding.
Testabilité 7/10 306 tests Go, 273 tests frontend, 300 stories, 26 E2E. MSW complet. Couverture seuil 50%. CI automatisée avec govulncheck/cargo audit/npm audit.
Opérabilité 7/10 Docker multi-stage, blue-green HAProxy, health checks, Prometheus/Grafana configs, Alertmanager, request ID, structured logging, Sentry. k8s templates prêts.
Vélocité dev 4/10 2 langages backend = barrière à l'entrée. ~319K LOC. Makefile modulaire aide. Storybook-first accélère l'UI. Un nouveau dev aura besoin de 2-3 semaines pour être productif (Go OR Rust, pas les deux).
Maturité produit 6/10 19 features opérationnelles sur ~22 déclarées. HLS partiellement cassé (JWT mismatch). WebRTC non fonctionnel. Payment flow opérationnel mais en mode test.

7. INFRASTRUCTURE & DEVOPS

7.1 Docker

Critère Backend Go Stream Rust Frontend
Multi-stage Oui (golang:1.24-alpine -> alpine:3.21) Oui (rust:1.84-alpine -> alpine:3.21) Oui (node:20-alpine -> nginx:1.27-alpine)
Non-root Oui (user app, UID 1001) Oui (user app, UID 1001) Oui (user nginx)
Health check wget /api/v1/health wget /health wget /health
Static binary CGO_ENABLED=0, ldflags -w -s -static musl target, strip N/A (nginx)
Source maps N/A N/A Supprimées en production (find dist -name "*.map" -delete)
Secrets dans layers Non Non Build args pour VITE_* (non secrets)
Image base alpine:3.21 (officielle) alpine:3.21 (officielle) nginx:1.27-alpine (officielle)

Docker Compose (production) :

  • Secrets via env avec :? (required) — fail-fast si absent
  • Blue-green deployment (backend-blue/green, stream-blue/green, web-blue/green)
  • HAProxy reverse proxy avec SSL
  • Health checks sur tous les services
  • Resource limits configurés (CPU, memory)
  • Réseau isolé (bridge, subnet 172.20.0.0/16)
  • Pas de ports exposés directement (sauf HAProxy 80/443 et Alertmanager 9093)

7.2 CI/CD

Workflow Couverture Détail
ci.yml Principal 5 jobs : backend-go (govulncheck, vet, lint, test, build), rust-services (cargo audit, lint, build, test), frontend (npm audit, generate types, lint, format, typecheck, test, build), storybook (build, serve, audit), e2e (Postgres+Redis+RabbitMQ, migrations, Playwright)
cd.yml Déploiement Deployment workflow
backend-ci.yml Backend Backend-specific CI
frontend-ci.yml Frontend Frontend-specific CI
rust-ci.yml Rust Clippy for stream server
stream-ci.yml Stream Clippy, audit, tests
sast.yml Sécurité Static Application Security Testing
security-scan.yml Sécurité Security scans
container-scan.yml Sécurité Container image scanning
storybook-audit.yml UI Storybook validation
load-test-nightly.yml Performance k6 nightly (02:00 UTC)
Dependabot Dépendances Mise à jour automatique

Ce qui manque :

  • Pas de cache remote Turborepo (builds plus lents en CI)
  • Pas de déploiement automatique vers staging/production (seulement cd.yml mais pas vérifié si complet)
  • Pas de smoke tests post-déploiement automatisés en CI

7.3 Reproductibilité

Critère Statut
Build en une commande docker compose up pour dev, docker compose -f docker-compose.prod.yml up pour prod
Onboarding doc docs/ONBOARDING.md existe et est détaillé
Versions outils lockées Go 1.24 (go.mod), Rust stable (pas de toolchain file), Node 20 (CI, pas de .nvmrc)
Dépendances lockées go.sum, Cargo.lock, package-lock.json — tous versionnés
Manque .nvmrc ou .node-version pour Node. rust-toolchain.toml pour Rust.

8. PERFORMANCE & SCALABILITÉ

8.1 Goulots d'étranglement

Composant Risque Seuil estimé Mitigation
PostgreSQL Requêtes non optimisées sans index, N+1 > 10K req/min Index GIN pg_trgm. Preload GORM. Read replica supporté.
Redis SPOF pour cache, rate limiting, sessions, PubSub Si Redis down : rate limit in-memory, chat single-instance Sentinel/Cluster non configuré
Chat server (Go) Hub pattern en mémoire > 1000 connexions simultanées Go goroutines légères (~8KB/goroutine)
Stream server (Rust) FFmpeg transcoding CPU-intensif > 100 transcodings simultanés Tokio runtime multi-threaded
File storage MinIO/S3 — pas de CDN configuré en dev > 10TB de tracks S3/MinIO horizontalement scalable. CDN configs dans k8s/
HAProxy Single instance reverse proxy > 5000 req/s Suffisant pour le lancement. LB cloud dans k8s/load-balancing/

8.2 Scalabilité horizontale

Service Horizontalement scalable ? Obstacle
Backend Go Oui (stateless sauf WebSocket) Chat WebSocket a affinité de session. Redis PubSub résout partiellement.
Stream server Oui (stateless pour HLS serving) Transcoding est CPU-bound, scalable par ajout d'instances.
Frontend Oui (fichiers statiques nginx) Aucun obstacle.
PostgreSQL Verticalement + read replicas Pas de sharding configuré.
Redis Non configuré pour cluster Single instance. Sentinel/Cluster nécessaire pour HA.

8.3 Load tests existants

Les scripts k6 dans loadtests/ couvrent :

  • Smoke test (30s, sanity check)
  • Backend: health, auth, tracks, uploads, playlists, marketplace, full scenario
  • Stream: health, HLS, ramp test
  • Chat: WebSocket, stress 1000 connexions simultanées
  • Stress: 500 req/s

Verdict : Bonne couverture de load testing pour un MVP. Les scripts sont réutilisables et paramétrables.


9. RISQUES BUSINESS

9.1 Point de vue CTO

Question Réponse
Recruter des devs productifs en < 2 semaines ? Non. La stack Go + Rust + React exige des profils polyvalents rares. Un dev Go sera productif sur le backend en 1-2 semaines, mais ne touchera pas le stream server. Un dev Rust full-stack capable de Go et React est un profil exceptionnel.
Vélocité soutenable ? Non. ~319K LOC en monorepo avec 356 TODO, 139 fichiers > 500 lignes, et 5300 LOC de code mort indiquent une vélocité qui a sacrifié la qualité. Le rythme doit ralentir pour consolider.
Dette technique va-t-elle exploser ? Oui, si le rythme actuel continue. Les 12 handlers avec error handling inconsistant, les migrations non transactionnelles, et le JWT mismatch sont des bombes à retardement.
Refactorings inévitables avant scaling ? (1) Corriger le JWT mismatch Go/Rust. (2) Nettoyer le code mort Rust. (3) Standardiser error handling. (4) Configurer Redis Sentinel/Cluster.
Go + Rust justifié pour cette taille d'équipe ? Non. Le stream server Rust pourrait être migré en Go sans perte de fonctionnalité significative (FFmpeg est l'outil lourd, pas le wrapper). La complexité de maintenance de 2 langages backend n'est pas justifiée par les gains de performance pour un service qui sert principalement des fichiers HLS.

9.2 Point de vue investisseur

Question Réponse
Produit réellement fonctionnel ? Partiellement. 19 features opérationnelles. Mais HLS auth cassé (JWT mismatch), WebRTC non fonctionnel, payments en mode test. C'est un MVP fonctionnel, pas une plateforme production-ready.
Risques de sécurité incident public ? Faibles. httpOnly cookies, bcrypt, rate limiting, CSP. Le seul risque critique (VEZA-SEC-001 JWT default secret) est mitigeable en < 1 jour. Pas de données utilisateur exposées.
Code repris par une autre équipe ? Oui, avec réserves. Le Go backend est bien structuré et documenté. Le Rust stream server est plus complexe à reprendre. Le frontend React est standard. Documentation abondante (285 docs).
Coût pour v1.0 production-ready ? 4-8 semaines avec 2 développeurs. Corriger les vulnérabilités critiques (1 semaine), stabiliser le streaming (2 semaines), configurer la production (1 semaine), tests de charge (1 semaine), monitoring (1 semaine).
Propriété intellectuelle défendable ? Limitée. Stack standard (Go/Rust/React), pas d'algorithme propriétaire. La valeur est dans l'intégration et le produit, pas dans la technologie. Le code Rust stream server avec ses codecs et pipeline audio est le plus différenciant mais aussi le plus coûteux à maintenir.
Ratio features/qualité = quantité sur qualité ? Partiellement. 19 features fonctionnelles est impressionnant, mais 5300 LOC de code mort, 356 TODO, et le JWT mismatch suggèrent une priorisation de la quantité. La qualité de base (auth, sécurité, CI/CD) est néanmoins solide.

9.3 Point de vue acquéreur

Question Réponse
Code réutilisable ? Backend Go : oui. Architecture propre, bien découpée. Stream Rust : partiellement. Code HLS et transcoding réutilisable, le reste (soundcloud/, webrtc) est du dead code. Frontend : oui. Standard React/Vite.
Données utilisateur migrables ? Oui. PostgreSQL avec schéma normalisé. UUID primary keys. GDPR export implémenté.
Vendor-lock ? Faible. Hyperswitch est open-source (remplaçable). MinIO est S3-compatible. Redis et PostgreSQL sont standards.
Temps onboarding 5 devs ? 4-6 semaines. 1 semaine setup + 1 semaine architecture backend + 1 semaine frontend + 1-2 semaines Rust (si maintenu). Documentation ONBOARDING.md existe.
Score de rachetabilité /10 6/10. Code propre pour un MVP, documentation abondante, stack standard. Pénalisé par la complexité Rust et le code mort.

9.4 Verdict

Question Réponse Justification
Peut-on lancer en production tel quel ? Non JWT mismatch Go/Rust (HLS auth cassé), secret JWT default en Rust, webhook worker leak
Peut-on vendre / monétiser tel quel ? Conditionnel Après correction des 3 vulnérabilités critiques + configuration Hyperswitch en mode live
Peut-on maintenir avec 2 devs ? Conditionnel Oui si le stream server Rust est gelé ou migré en Go. Non avec 2 langages backend actifs.
Faut-il refactorer avant prod ? Oui JWT mismatch, error handling, code mort, pagination limits
Faut-il réécrire certains services ? Non Le code est de qualité suffisante. Migration Rust -> Go du stream server recommandée à moyen terme, pas de réécriture urgente.
La vélocité de développement est-elle un red flag ? Oui (modéré) Le volume de code (319K LOC) et le nombre de features (19) pour ce qui semble être un petit team est impressionnant mais a généré de la dette. Le rythme doit ralentir pour consolider.

10. PLAN D'ACTION PRIORISÉ

Phase 1 — Critique (Semaines 1-2) : Sécurité et Stabilité

# Action Risque si non corrigé Fichiers Effort
1 Supprimer le JWT secret par défaut dans veza-common/src/config_rust.rs — panic si JWT_SECRET absent Compromission de tous les tokens si env var manquante config_rust.rs:234 S
2 Aligner JWT issuer/audience entre Go et Rust (utiliser veza-api/veza-app partout, ou configurable par env) HLS streaming auth cassé jwt_service.go, auth/mod.rs M
3 Enregistrer le webhook worker dans shutdownManager avec context annulable Perte de webhooks au redéploiement routes_webhooks.go:31 S
4 Corriger shutdown_signal dans main.rs — passer le AppState existant Shutdown ne ferme pas les connexions correctement main.rs:74 S
5 Aligner la politique de mot de passe frontend (12 chars min) Formulaire accepte, serveur rejette passwordValidator.ts S
6 Protéger les routes /metrics par auth ou réseau interne Information disclosure des métriques système routes_core.go S

Phase 2 — Stabilisation (Semaines 3-6) : Déployabilité

# Action Fichiers Effort
7 Standardiser error handling — migrer les 12 handlers vers RespondWithAppError account_deletion_handler.go, etc. M
8 Ajouter une limite max de pagination (ex: limit capped à 100) Tous les handlers de liste M
9 Propager context.Context dans password_reset_service.go 4 endroits S
10 Configurer Redis Sentinel ou Cluster pour la haute disponibilité docker-compose.prod.yml L
11 Ajouter .nvmrc (Node 20) et rust-toolchain.toml pour lock les versions Racine, veza-stream-server/ S
12 Configurer Turborepo remote cache pour accélérer la CI turbo.json M
13 Smoke tests post-déploiement automatisés .github/workflows/cd.yml M

Phase 3 — Consolidation (Semaines 7-12) : Dette technique

# Action Fichiers Effort
14 Supprimer le code mort : soundcloud/ (~4K LOC), webrtc.rs (~500 LOC), k8s/chat-server/, Makefile.old Multiples M
15 Supprimer les dossiers orphelins : chat_exports/, sub_task_agents/, tmt/, full_veza_audit_data/ Racine S
16 Découper les 10 plus gros fichiers (> 1000 lignes) en sous-modules track/service.go, marketplace/service.go, playlist_handler.go, etc. L
17 Adresser les 356 TODO/FIXME/HACK — résoudre ou convertir en issues Tout le codebase XL
18 Consolider les migrations — squash des 95 migrations en une base + delta veza-backend-api/migrations/ L
19 Supprimer features.go stub ou implémenter le runtime feature flag system internal/features/features.go S
20 Connecter onCreateProduct dans le seller dashboard routeConfig.tsx S

Phase 4 — Évolution (Mois 4+)

# Action Effort
21 Évaluer la migration du stream server Rust vers Go XL
22 Implémenter WebRTC audio calls (v1.1) ou supprimer définitivement le code L
23 Configurer un CDN (CloudFront/Cloudflare) pour les assets audio M
24 Implémenter cursor-based pagination pour les listes volumineuses L
25 Ajouter des tests d'intégration Rust avec base de données L
26 Passer les couverture tests frontend de 50% à 70% XL

ANNEXES

A. Métriques brutes

Métrique Valeur
Commit analysé a007f4c7 (2026-03-03)
Version v1.0.2
LOC Go (backend) ~188K (778 fichiers)
LOC Rust (stream + common) ~107K (191 fichiers)
LOC TypeScript/TSX (frontend) ~211K (1887 fichiers)
LOC SQL (migrations) ~3.5K (95 fichiers)
LOC total code source ~319K
Tests Go 306 fichiers
Tests Frontend 273 fichiers
Stories Storybook 300 fichiers
Tests E2E 26 specs
Workflows CI/CD 14
Docs Markdown 285 fichiers
Direct deps Go 45
Direct deps Rust ~78
Direct deps Frontend 72
Fichiers > 500 lignes 139
TODO/FIXME/HACK 356
Code mort estimé ~5300 LOC
Vulnérabilités CVE (CI) 0
Vulnérabilités identifiées (audit) 9 (2 critiques, 2 élevées, 3 moyennes, 2 faibles)

B. Fichiers les plus volumineux (top 15)

Fichier LOC
apps/web/src/types/generated/api.ts 6550
veza-backend-api/docs/docs.go 5448
veza-stream-server/src/generated/veza.stream.rs 1925
apps/web/e2e/utils/test-helpers.ts 1215
veza-stream-server/src/core/sync.rs 1183
veza-stream-server/src/soundcloud/discovery.rs 1181
veza-backend-api/internal/core/track/service.go 1147
veza-backend-api/internal/core/marketplace/service.go 1142
veza-backend-api/internal/handlers/playlist_handler.go 1137
veza-backend-api/tests/search/search_test.go 1099
veza-backend-api/internal/config/config.go 1037
veza-stream-server/src/streaming/websocket.rs 1029
veza-backend-api/internal/core/auth/service.go 1019
veza-stream-server/src/codecs/mp3.rs 932
veza-backend-api/internal/handlers/marketplace.go 919

C. Conclusion stratégique

Veza est un MVP techniquement solide qui démontre une capacité d'exécution impressionnante pour une petite équipe. L'architecture backend Go est propre et bien sécurisée. L'infrastructure de déploiement (Docker, CI/CD, blue-green) est mature pour un projet de cette taille.

Cependant, la vélocité de développement a créé une dette technique significative : code mort, incohérences inter-services (JWT mismatch), et hétérogénéité injustifiée (Go + Rust). Le stream server Rust, avec ses ~103K LOC, est le composant le plus risqué — non pas pour sa qualité intrinsèque, mais pour le coût de maintenance qu'il impose à une petite équipe.

Recommandation finale : Investir, avec les conditions suivantes :

  1. Corriger les 6 actions critiques (Phase 1, 2 semaines) avant tout déploiement client
  2. Geler le développement de nouvelles features pendant 4 semaines pour la stabilisation (Phase 2)
  3. Planifier la migration du stream server Rust vers Go à 6-12 mois pour réduire la complexité de maintenance
  4. Recruter au minimum 1 développeur Go senior pour soutenir la phase de consolidation

Le ratio risque/potentiel est favorable : les fondations sont saines, les vulnérabilités sont corrigeables, et le produit couvre un périmètre fonctionnel large. Le principal risque n'est pas technique mais organisationnel — maintenir la qualité avec une petite équipe sur un codebase de 319K LOC.