703 lines
48 KiB
Markdown
703 lines
48 KiB
Markdown
|
|
# AUDIT TECHNIQUE — VEZA MONOREPO
|
|||
|
|
|
|||
|
|
| Champ | Valeur |
|
|||
|
|
|-------|--------|
|
|||
|
|
| **Date** | 2026-02-22 |
|
|||
|
|
| **Auditeur** | Claude 4.6 Opus (IA) — mandat due diligence |
|
|||
|
|
| **Version analysée** | v0.402, main (HEAD+49 commits non poussés) |
|
|||
|
|
| **Périmètre** | Backend Go, Chat Server Rust, Stream Server Rust, Frontend React, Infra Docker/CI |
|
|||
|
|
| **Méthodologie** | Analyse statique du code source, 6 passes d'exploration |
|
|||
|
|
| **Classification** | Confidentiel — Usage interne |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## EXECUTIVE SUMMARY
|
|||
|
|
|
|||
|
|
### Verdict global
|
|||
|
|
|
|||
|
|
Veza est un projet **ambitieux et structurellement bien pensé** pour un effort solo/micro-équipe. L'architecture backend Go est la pièce la plus mature : séparation handler → service → repository, middleware stack complète, couverture de tests proche de 1:1. Le frontend React est extensif (~131K LOC source) avec un design system cohérent (SUMI), Storybook-driven development, et 288 stories.
|
|||
|
|
|
|||
|
|
**Cependant, le projet n'est pas prêt pour la production.** La vélocité affichée (345+ features, 12 releases en ~3 mois) masque une réalité : de nombreuses features sont partiellement implémentées (frontend mock, backend stub, ou flux E2E non connecté). Les services Rust compilent mais ne sont pas intégrés (gRPC = stub, boot mode = chat/stream OFF). L'infrastructure CI/CD contient des défauts critiques (pipeline CD non fonctionnel, secrets en clair, versions Go incohérentes).
|
|||
|
|
|
|||
|
|
### Top 5 risques
|
|||
|
|
|
|||
|
|
| # | Risque | Gravité |
|
|||
|
|
|---|--------|---------|
|
|||
|
|
| 1 | **Pipeline CD non fonctionnel** — Les conditions `secrets.*` dans les `if` GitHub Actions ne s'évaluent jamais. Les étapes push, sign, deploy ne s'exécutent pas. | CRITIQUE |
|
|||
|
|
| 2 | **Authentification HLS/WebSocket cassée** — `TokenStorage.getAccessToken()` retourne toujours `null` (cookies httpOnly). Les clients HLS et WebSocket ne peuvent pas s'authentifier. | CRITIQUE |
|
|||
|
|
| 3 | **Redis sans mot de passe en production** — `docker-compose.prod.yml` ne configure aucune authentification Redis. | ÉLEVÉ |
|
|||
|
|
| 4 | **Rate limiter en mémoire** — Ne fonctionne pas en multi-instance. Brute force possible en prod scalée. | ÉLEVÉ |
|
|||
|
|
| 5 | **Services Rust non intégrés** — Chat et Stream servers compilent mais tournent en "boot mode" (OFF). 21.5% des 600 features annoncées sont réellement fonctionnelles. | ÉLEVÉ |
|
|||
|
|
|
|||
|
|
### Top 5 forces
|
|||
|
|
|
|||
|
|
| # | Force |
|
|||
|
|
|---|-------|
|
|||
|
|
| 1 | **Architecture backend Go exemplaire** — Séparation claire des responsabilités, middleware stack complète (23 middlewares), ratio test/code 0.97:1 |
|
|||
|
|
| 2 | **Sécurité auth solide** — Tokens httpOnly, access token 5min, bcrypt cost 12, CSRF timing-safe, validation JWT stricte (iss/aud/exp/algo) |
|
|||
|
|
| 3 | **Design system cohérent** — SUMI Design System v2.0, 882 lignes de tokens CSS, Storybook-first, 288 stories |
|
|||
|
|
| 4 | **Infrastructure de qualité** — CI multi-pipeline, Dependabot, security scanning, Dockerfiles multi-stage, utilisateur non-root |
|
|||
|
|
| 5 | **Documentation extensive** — 63 docs frontend, scope control par version, CHANGELOG structuré, FEATURE_STATUS tracé |
|
|||
|
|
|
|||
|
|
### Recommandation go/no-go
|
|||
|
|
|
|||
|
|
**NO-GO pour production en l'état.** Conditionnel à 4-6 semaines de stabilisation ciblée (voir Phase 1-2 du plan d'action). Le code est de qualité suffisante pour être corrigé, pas réécrit.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1️⃣ CARTOGRAPHIE GLOBALE
|
|||
|
|
|
|||
|
|
### 1.1 Stack réelle
|
|||
|
|
|
|||
|
|
| Élément | Constaté dans le code |
|
|||
|
|
|---------|----------------------|
|
|||
|
|
| **Go** | 1.24.0 (`go.work`), mais Dockerfile.production utilise 1.23-alpine — **incohérence** |
|
|||
|
|
| **Rust** | Stable channel (`rust-toolchain.toml`), Edition 2021 |
|
|||
|
|
| **Node.js** | 20 (CI workflows), npm 10.9.2 (`packageManager`) |
|
|||
|
|
| **React** | 18.2.0 |
|
|||
|
|
| **Vite** | 7.1.5 |
|
|||
|
|
| **TypeScript** | 5.3.3 (package.json) mais 5.9.3 (root devDependencies) — **incohérence** |
|
|||
|
|
| **Tailwind CSS** | 4.0.0 (CSS-first config) |
|
|||
|
|
| **Framework Go** | Gin 1.11.0 (dernière stable, maintenu) |
|
|||
|
|
| **ORM Go** | GORM 1.30.0 + lib/pq 1.10.9 (parameterized queries) |
|
|||
|
|
| **Framework Rust** | Axum 0.8 (chat + stream), Tokio 1.35 |
|
|||
|
|
| **SQLx** | 0.8 (Rust services) |
|
|||
|
|
| **PostgreSQL** | 16-alpine (dev/prod), 15-alpine (test/hybrid) — **incohérence** |
|
|||
|
|
| **Redis** | 7 (docker-compose), go-redis/v9 9.16.0 |
|
|||
|
|
| **RabbitMQ** | 3-management-alpine |
|
|||
|
|
| **Auth** | JWT HS256 via `golang-jwt/jwt/v5`, access 5min, refresh 14j, remember-me 30j |
|
|||
|
|
| **Paiement** | Hyperswitch via `@juspay-tech/hyper-js`, SDK frontend uniquement, mode test |
|
|||
|
|
| **Streaming** | HLS prévu mais **désactivé** (`HLS_STREAMING=false`), service stub |
|
|||
|
|
| **WebSocket** | Gorilla (Go), Axum WS (Rust), native WebSocket API (frontend) |
|
|||
|
|
| **WebRTC** | Code présent dans stream-server mais **commenté/désactivé** |
|
|||
|
|
| **CI/CD** | GitHub Actions — 12 workflows |
|
|||
|
|
| **Containerisation** | Docker multi-stage, images alpine, utilisateur non-root |
|
|||
|
|
| **Monitoring** | Prometheus configuré, Grafana référencé, Sentry intégré, zap structured logging |
|
|||
|
|
| **Monorepo** | Turborepo + npm workspaces + Go workspace |
|
|||
|
|
|
|||
|
|
### 1.2 Organisation du monorepo
|
|||
|
|
|
|||
|
|
| Répertoire | Rôle réel | Fichiers | LOC |
|
|||
|
|
|-----------|-----------|----------|-----|
|
|||
|
|
| `veza-backend-api/` | API REST Go — cœur fonctionnel du produit | 671 .go | 174,022 |
|
|||
|
|
| `veza-chat-server/` | Serveur chat Rust — compile, non intégré | 78 .rs | ~60,000* |
|
|||
|
|
| `veza-stream-server/` | Serveur streaming Rust — compile, non intégré | 113 .rs | ~80,000* |
|
|||
|
|
| `apps/web/` | Frontend React/Vite — interface utilisateur | 1,837 .ts/.tsx | ~206,000 |
|
|||
|
|
| `veza-docs/` | Site Docusaurus — squelette non alimenté | ~20 | ~500 |
|
|||
|
|
| `docs/` | Documentation projet/versioning | 332 .md | ~15,000 |
|
|||
|
|
| `scripts/` | Scripts utilitaires (audit, migration, deploy) | 85+ | ~5,000 |
|
|||
|
|
| `.github/` | CI/CD workflows + templates | 12 workflows | ~800 |
|
|||
|
|
| `config/` | Prometheus, métriques, SSL | 5 | ~100 |
|
|||
|
|
| `infra/` | docker-compose lab | 1 | ~50 |
|
|||
|
|
| `make/` | Makefile modulaire | 11 .mk | ~800 |
|
|||
|
|
| `dev-environment/` | Templates de services | ~10 | ~400 |
|
|||
|
|
| `fixtures/` | Package npm vide | 5 | ~50 |
|
|||
|
|
| `packages/` | Shared packages — **vide** | 0 | 0 |
|
|||
|
|
|
|||
|
|
*LOC Rust estimée (total 352K inclut le code généré gRPC/protobuf)
|
|||
|
|
|
|||
|
|
**Packages orphelins :**
|
|||
|
|
- `packages/` — déclaré dans npm workspaces mais vide
|
|||
|
|
- `fixtures/` — package npm avec `vitest.config.ts` mais aucun test
|
|||
|
|
- `veza-docs/` — Docusaurus configuré mais non alimenté
|
|||
|
|
|
|||
|
|
**Packages fantômes :**
|
|||
|
|
- `veza-backend-api/internal/api/archive/api_manager.go` — 789 lignes de code commenté/TODO, jamais importé
|
|||
|
|
- `dev-environment/templates/` — templates de génération de code non utilisés par un outil
|
|||
|
|
|
|||
|
|
**Duplications cross-packages :**
|
|||
|
|
- JWT validation implémentée 3 fois (Go `jwt_service.go`, Rust chat `jwt_manager.rs`, Rust stream `token_validator.rs`)
|
|||
|
|
- Configuration loading implémentée 3 fois avec des patterns différents
|
|||
|
|
- gRPC protobuf généré dupliqué entre chat et stream servers
|
|||
|
|
|
|||
|
|
### 1.3 Dépendances critiques
|
|||
|
|
|
|||
|
|
#### Backend Go (44 dépendances directes)
|
|||
|
|
|
|||
|
|
| Dépendance | Version | Statut | Risque |
|
|||
|
|
|-----------|---------|--------|--------|
|
|||
|
|
| `gin-gonic/gin` | 1.11.0 | Maintenu activement | Faible |
|
|||
|
|
| `gorm.io/gorm` | 1.30.0 | Maintenu activement | Faible |
|
|||
|
|
| `golang-jwt/jwt/v5` | 5.3.0 | Maintenu | Faible |
|
|||
|
|
| `redis/go-redis/v9` | 9.16.0 | Maintenu | Faible |
|
|||
|
|
| `gorilla/websocket` | 1.5.3 | **Archivé** (décembre 2024) | MOYEN — migrer vers `nhooyr.io/websocket` |
|
|||
|
|
| `lib/pq` | 1.10.9 | En maintenance minimale | Faible (GORM l'utilise via driver) |
|
|||
|
|
| `swaggo/swag` | 1.16.6 | Maintenu | Faible |
|
|||
|
|
| `sony/gobreaker` | 1.0.0 | Maintenu | Faible |
|
|||
|
|
| `getsentry/sentry-go` | 0.40.0 | Maintenu | Faible |
|
|||
|
|
| `testcontainers-go` | 0.33.0 | Maintenu | Faible |
|
|||
|
|
|
|||
|
|
#### Frontend React (dépendances majeures)
|
|||
|
|
|
|||
|
|
| Dépendance | Version | Statut | Risque |
|
|||
|
|
|-----------|---------|--------|--------|
|
|||
|
|
| `react` | 18.2.0 | **React 19 disponible** — 1 majeure de retard | MOYEN |
|
|||
|
|
| `@tanstack/react-query` | 5.17.0 | Maintenu | Faible |
|
|||
|
|
| `zustand` | 4.5.0 | Maintenu | Faible |
|
|||
|
|
| `msw` | 2.11.2 | Maintenu | Faible |
|
|||
|
|
| `dompurify` | Utilisé via sanitize.ts | Maintenu | Faible |
|
|||
|
|
| `@juspay-tech/hyper-js` | Hyperswitch SDK | Niche — petit écosystème | MOYEN |
|
|||
|
|
|
|||
|
|
#### Rust (dépendances clés)
|
|||
|
|
|
|||
|
|
| Dépendance | Version | Risque |
|
|||
|
|
|-----------|---------|--------|
|
|||
|
|
| `axum` | 0.8 | Faible — maintenu par Tokio |
|
|||
|
|
| `sqlx` | 0.8 | Faible — maintenu |
|
|||
|
|
| `jsonwebtoken` | 10 | Faible |
|
|||
|
|
| `tonic` | 0.11 | Faible — gRPC bien maintenu |
|
|||
|
|
| `lapin` | 2.3 | MOYEN — RabbitMQ Rust, communauté petite |
|
|||
|
|
| `symphonia` | 0.5 | MOYEN — audio processing, niche |
|
|||
|
|
|
|||
|
|
### 1.4 Schéma des flux
|
|||
|
|
|
|||
|
|
#### Auth flow
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Browser → POST /api/v1/auth/register → AuthHandler → AuthService → GORM → PostgreSQL
|
|||
|
|
→ POST /api/v1/auth/login → AuthHandler → PasswordService.VerifyPassword → bcrypt
|
|||
|
|
→ Set-Cookie: access_token (httpOnly, 5min)
|
|||
|
|
→ Set-Cookie: refresh_token (httpOnly, 14j)
|
|||
|
|
→ POST /api/v1/auth/refresh → Cookie → JWTService.ValidateToken → TokenVersion check → New tokens
|
|||
|
|
→ POST /api/v1/auth/oauth/:provider → OAuthService → Google/GitHub → JWT
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**SPOF :** PostgreSQL (session lookup per request), Redis (CSRF tokens)
|
|||
|
|
**Timeout :** 30s request timeout (middleware), context propagation
|
|||
|
|
**Retry :** Pas de retry sur DB failure
|
|||
|
|
**Race condition :** Token version increment non transactionnel — deux refresh simultanés pourraient invalider l'un l'autre
|
|||
|
|
|
|||
|
|
#### Payment flow
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Frontend → POST /api/v1/marketplace/checkout → MarketplaceHandler → HyperswitchService
|
|||
|
|
→ Hyperswitch API → Create PaymentIntent → client_secret
|
|||
|
|
→ Frontend → Hyperswitch SDK → Card form → Confirm payment
|
|||
|
|
→ Hyperswitch → Webhook → POST /api/v1/webhooks/hyperswitch (?)
|
|||
|
|
→ MarketplaceService → Update order status
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**SPOF :** Hyperswitch API (externe)
|
|||
|
|
**Risque critique :** Le handler de webhook entrant Hyperswitch n'a pas été trouvé dans `webhook_handlers.go` (ce fichier ne gère que les webhooks sortants). La vérification de signature webhook est potentiellement absente.
|
|||
|
|
**Timeout :** Non vérifié pour les appels Hyperswitch
|
|||
|
|
**Idempotence :** Non vérifiée pour les webhooks de paiement
|
|||
|
|
|
|||
|
|
#### Chat flow (théorique — non intégré)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Frontend → WebSocket /ws → Chat Server (Rust/Axum) → JWT validation → Hub
|
|||
|
|
→ Message → SQLx → PostgreSQL (chat DB séparée)
|
|||
|
|
→ Broadcast → Connected clients
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**État actuel :** Boot mode — chat server OFF. Frontend utilise MSW mocks.
|
|||
|
|
|
|||
|
|
#### Stream flow (théorique — non intégré)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Frontend → GET /stream/hls/:track_id/playlist.m3u8 → Stream Server (Rust/Axum)
|
|||
|
|
→ JWT validation (cassée — token null) → HLS segments → Player
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**État actuel :** Stream server OFF. HLS désactivé. Frontend fallback sur des URLs directes.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2️⃣ CE QUE LE PRODUIT PERMET RÉELLEMENT
|
|||
|
|
|
|||
|
|
### 2.1 Classification des features
|
|||
|
|
|
|||
|
|
#### ✅ Fonctionnelles (flux complet front + back + DB)
|
|||
|
|
|
|||
|
|
1. **Authentication** — Register/Login/Logout avec JWT httpOnly cookies
|
|||
|
|
2. **2FA TOTP** — Activation, vérification, codes de récupération
|
|||
|
|
3. **OAuth** — Google, GitHub (Discord/Spotify : code présent mais non fonctionnel)
|
|||
|
|
4. **Profils utilisateur** — CRUD, avatar, banner, liens sociaux, profil privé
|
|||
|
|
5. **Upload audio** — Validation magic bytes, ClamAV, métadonnées
|
|||
|
|
6. **CRUD Tracks** — Création, édition, suppression, métadonnées enrichies (BPM, key, lyrics, tags)
|
|||
|
|
7. **Playlists** — CRUD, collaboration, partage, recommandations
|
|||
|
|
8. **Dashboard** — Vue d'ensemble utilisateur
|
|||
|
|
9. **Sessions** — Liste, révocation
|
|||
|
|
10. **Settings** — Profil, sécurité, notifications, préférences
|
|||
|
|
11. **Marketplace** — Catalogue produits, panier, wishlist
|
|||
|
|
12. **Search** — Recherche full-text avec pg_trgm, filtres
|
|||
|
|
13. **Social posts** — CRUD, likes, commentaires (feed basique)
|
|||
|
|
14. **RBAC** — Rôles utilisateur, middleware d'autorisation
|
|||
|
|
|
|||
|
|
#### ⚠️ Partiellement implémentées
|
|||
|
|
|
|||
|
|
| Feature | Backend | Frontend | Écart |
|
|||
|
|
|---------|---------|----------|-------|
|
|||
|
|
| **Checkout Hyperswitch** | Handler + Hyperswitch SDK | Formulaire paiement | Webhook entrant non trouvé, mode test uniquement |
|
|||
|
|
| **Promo codes** | Migration 099-100, handler | Modal + cart integration | En cours (fichiers modifiés dans git status) |
|
|||
|
|
| **Notifications** | Service + push web | Composants UI | Backend OK, frontend MSW pour certaines routes |
|
|||
|
|
| **Analytics** | Handler + service (7% complet selon audit interne) | Dashboard composants | Données réelles partielles |
|
|||
|
|
| **Admin panel** | Routes protégées | Pages admin | Fonctionnalités limitées |
|
|||
|
|
| **Webhooks** | CRUD outbound | Developer UI | Pas de delivery engine visible |
|
|||
|
|
| **Gear/Inventory** | Handler | Composants | Backend minimal |
|
|||
|
|
| **Live streaming** | Handler | Composants | Backend stub |
|
|||
|
|
| **Trending** | TrendingService | Feed explore | Algorithme basique |
|
|||
|
|
|
|||
|
|
#### 👻 Fantômes (déclarées mais absentes ou stub)
|
|||
|
|
|
|||
|
|
| Feature | Déclarée dans | Réalité |
|
|||
|
|
|---------|--------------|---------|
|
|||
|
|
| **HLS Streaming** | FEATURE_STATUS ("operational") | `HLS_STREAMING=false`, stream server OFF, `getHLSXhrSetup()` retourne token null |
|
|||
|
|
| **WebRTC Audio Calls** | CHANGELOG v0.303 | Code commenté/désactivé dans stream-server |
|
|||
|
|
| **OAuth Discord/Spotify** | FEATURE_STATUS ("operational") | Audit interne confirme : non implémentés |
|
|||
|
|
| **Chat temps réel** | FEATURE_STATUS ("operational") | Chat server en boot mode (OFF), frontend MSW |
|
|||
|
|
| **gRPC inter-services** | Architecture déclarée | Stub — protobuf généré mais endpoints non connectés |
|
|||
|
|
|
|||
|
|
#### 💀 Mortes (code présent, jamais appelé)
|
|||
|
|
|
|||
|
|
| Code mort | Fichier | LOC |
|
|||
|
|
|-----------|---------|-----|
|
|||
|
|
| `api_manager.go` | `internal/api/archive/api_manager.go` | 789 |
|
|||
|
|
| `docs.go` (Swagger généré) | `internal/handlers/docs/docs.go` | 5,482 |
|
|||
|
|
| `GenerateJWT` dans PasswordService | `internal/services/password_service.go:249` | ~20 (méthode sans iss/aud, potentiellement dangereuse si appelée) |
|
|||
|
|
| `TokenStorage.getAccessToken()` | `apps/web/src/services/tokenStorage.ts` | ~107 (tout le fichier est un no-op) |
|
|||
|
|
| `isTokenExpiringSoon()` | `apps/web/src/services/tokenRefresh.ts` | ~30 (retourne toujours true) |
|
|||
|
|
| `MOCK_PURCHASES` | `apps/web/src/services/commerceService.ts` | ~50 (données mock retournées en production) |
|
|||
|
|
| `requestRefund()` | `apps/web/src/services/commerceService.ts` | ~10 (no-op, retourne toujours `{success: true}`) |
|
|||
|
|
|
|||
|
|
#### 🧪 Expérimentales abandonnées
|
|||
|
|
|
|||
|
|
| Feature | Traces |
|
|||
|
|
|---------|--------|
|
|||
|
|
| **Éducation/Gamification** | Supprimés du code, mentionnés dans FEATURE_STATUS comme "permanently deleted" |
|
|||
|
|
| **veza-mobile** | Mentionné dans FEATURE_STATUS comme abandonné |
|
|||
|
|
| **packages/design-system** | Répertoire `packages/` vide, design system migré dans `apps/web/src/index.css` |
|
|||
|
|
|
|||
|
|
### 2.2 Incohérences produit/code
|
|||
|
|
|
|||
|
|
| Source | Affirme | Réalité code |
|
|||
|
|
|--------|---------|-------------|
|
|||
|
|
| `docs/FEATURE_STATUS.md` | "19 features operational" | ~14 véritablement fonctionnelles E2E, 5 partielles ou fantômes |
|
|||
|
|
| `docs/FEATURE_STATUS.md` | "HLS_STREAMING = true, operational" | `HLS_STREAMING=false`, service OFF, auth cassée |
|
|||
|
|
| `docs/FEATURE_STATUS.md` | "OAuth Discord + Spotify operational" | Audit interne confirme non implémentés |
|
|||
|
|
| `CHANGELOG.md` v0.303 | "WebRTC audio calls 1-to-1" | Code commenté dans stream-server |
|
|||
|
|
| `CHANGELOG.md` v0.402 | "Checkout Hyperswitch production-ready" | Mode test, webhook entrant non trouvé |
|
|||
|
|
| Audit interne (103) | Score 32/100, 21.5% features done | FEATURE_STATUS liste 19 features "operational" |
|
|||
|
|
| `V0_101_RELEASE_SCOPE.md` | "All services must be running together" | Boot mode = chat/stream/RabbitMQ/ClamAV OFF |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3️⃣ VALIDATION FONCTIONNELLE
|
|||
|
|
|
|||
|
|
### 3.1 Couverture de tests
|
|||
|
|
|
|||
|
|
| Service | Fichiers test | LOC test | LOC source | Ratio | Commentaire |
|
|||
|
|
|---------|--------------|----------|-----------|-------|-------------|
|
|||
|
|
| **Go backend** | 264 | 85,455 | 87,930 | **0.97:1** | Excellent. Tests unitaires + intégration + sécurité |
|
|||
|
|
| **Rust chat** | ~28 modules | ~5,000* | ~55,000* | ~0.09:1 | Faible. Principalement des tests unitaires inline |
|
|||
|
|
| **Rust stream** | ~30 modules | ~8,000* | ~72,000* | ~0.11:1 | Faible. Tests de charge présents mais basiques |
|
|||
|
|
| **Frontend** | 274 | 58,816 | 130,976 | **0.45:1** | Correct. Tests composants Vitest + Storybook tests |
|
|||
|
|
| **Stories** | 288 | 15,987 | — | — | Bonne couverture Storybook |
|
|||
|
|
|
|||
|
|
*Estimé à partir des 352K LOC Rust totales incluant le code généré
|
|||
|
|
|
|||
|
|
**Tests E2E :** Playwright configuré (5 configs : smoke, storybook, visual, main, patch). Scénarios E2E dans `ci.yml` avec docker-compose full stack.
|
|||
|
|
|
|||
|
|
**Tests de sécurité :** Présents dans Go (`tests/security/authorization_test.go`, `injection_attack_test.go`).
|
|||
|
|
|
|||
|
|
**Mocks vs API réelle :** 100% du frontend teste contre MSW. Aucun test frontend contre l'API réelle (sauf E2E).
|
|||
|
|
|
|||
|
|
### 3.2 Points de rupture identifiés
|
|||
|
|
|
|||
|
|
| Scénario | Impact | Mitigation existante |
|
|||
|
|
|----------|--------|---------------------|
|
|||
|
|
| Redis tombe | CSRF cassé → toutes les mutations échouent (503) | Aucune — Redis est SPOF pour CSRF en prod |
|
|||
|
|
| 10K tracks par utilisateur | Pagination cursor OK, mais pas de limite `max` documentée | Pagination offset + limit avec max configurable |
|
|||
|
|
| Fichier audio 10GB | `MaxUploadSize` configurable, validation taille | Oui — configurable dans env |
|
|||
|
|
| 1000 WebSocket simultanées | Chat server non testé sous charge en intégration | Load testing basique dans stream server |
|
|||
|
|
| Webhook Hyperswitch replay | Handler webhook entrant non trouvé | **RISQUE** — pas d'idempotence vérifiable |
|
|||
|
|
| Token expiré mid-session | Proactive refresh toutes les 4 min + retry 401 avec queue | Robuste — bien implémenté |
|
|||
|
|
| Migration partielle | Pas de transaction wrapping dans les migrations SQL | **RISQUE** — état DB incohérent possible |
|
|||
|
|
| 2 refresh simultanés | Token version increment non-atomic | **RISQUE** — race condition possible |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4️⃣ REGISTRE DES VULNÉRABILITÉS
|
|||
|
|
|
|||
|
|
| ID | Catégorie | Gravité | Fichier(s) | Description | Impact | Correctif | Effort |
|
|||
|
|
|----|-----------|---------|-----------|-------------|--------|-----------|--------|
|
|||
|
|
| VEZA-SEC-001 | A05 Misconfig | **CRITIQUE** | `.github/workflows/cd.yml` | Conditions `secrets.*` dans `if` GHA ne s'évaluent jamais → pipeline CD non fonctionnel | Aucun déploiement automatisé ne fonctionne | Utiliser `vars.*` ou étape de vérification séparée | S |
|
|||
|
|
| VEZA-SEC-002 | A07 Auth | **CRITIQUE** | `apps/web/src/services/tokenStorage.ts`, `hlsService.ts`, `websocket.ts` | `getAccessToken()` retourne `null` → HLS et WebSocket ne peuvent pas s'authentifier | Streaming non protégé ou non fonctionnel | Implémenter auth par cookie pour WS/HLS ou endpoint de stream token | M |
|
|||
|
|
| VEZA-SEC-003 | A05 Misconfig | **CRITIQUE** | `docker-compose.hybrid.yml` | `network_mode: host` + Grafana password `admin` par défaut | Infrastructure accessible depuis le réseau sans auth | Supprimer network_mode host, forcer mot de passe | S |
|
|||
|
|
| VEZA-SEC-004 | A05 Misconfig | **ÉLEVÉ** | `docker-compose.prod.yml` | Redis sans authentification en production | Cache compromis → session hijacking, data poisoning | Ajouter `--requirepass` et `REDIS_PASSWORD` | S |
|
|||
|
|
| VEZA-SEC-005 | A01 Access | **ÉLEVÉ** | `docker-compose.prod.yml:217-220` | Stream server manque `JWT_SECRET` en prod compose | Service accepte potentiellement des requêtes non authentifiées | Ajouter `JWT_SECRET` dans la config stream-server | S |
|
|||
|
|
| VEZA-SEC-006 | A04 Design | **ÉLEVÉ** | `internal/middleware/ratelimit.go` | Rate limiter in-memory → ne fonctionne pas multi-instance | Brute force multiplié par nombre d'instances | Migrer vers rate limiting Redis | M |
|
|||
|
|
| VEZA-SEC-007 | A02 Crypto | **ÉLEVÉ** | `.github/workflows/ci.yml:248,287` | Mot de passe de test E2E en clair dans le workflow | Credential leakage si repo public | Migrer vers GitHub Secrets | S |
|
|||
|
|
| VEZA-SEC-008 | A01 Access | **MOYEN** | `internal/handlers/upload.go:308-326` | `GetUploadStatus` — IDOR, pas de vérification d'ownership | Un utilisateur authentifié peut voir le statut de n'importe quel upload | Ajouter check `upload.UserID == currentUserID` | S |
|
|||
|
|
| VEZA-SEC-009 | A10 SSRF | **MOYEN** | `internal/handlers/webhook_handlers.go:69` | URL de webhook accepte tout schéma (file://, http://169.254.x.x) | SSRF via webhook delivery | Valider schéma (https only), bloquer IPs privées | S |
|
|||
|
|
| VEZA-SEC-010 | A08 Integrity | **MOYEN** | Non trouvé | Webhook entrant Hyperswitch — handler non identifié, vérification de signature incertaine | Webhooks de paiement potentiellement non vérifiés | Vérifier/implémenter vérification HMAC-SHA256 | M |
|
|||
|
|
| VEZA-SEC-011 | A05 Misconfig | **MOYEN** | `cmd/api/main.go:8` | `import _ "net/http/pprof"` en production | Profiling endpoints accessibles si DefaultServeMux exposé | Conditionner import au mode dev | S |
|
|||
|
|
| VEZA-SEC-012 | A02 Crypto | **MOYEN** | `internal/services/password_service.go:92-95` | Reset tokens stockés en clair dans PostgreSQL | Si DB compromise, tous les tokens de reset actifs sont exposés | Stocker le hash SHA-256 du token | S |
|
|||
|
|
| VEZA-SEC-013 | A07 Auth | **MOYEN** | `internal/middleware/auth.go:312-406` | `OptionalAuth` ne vérifie pas la correspondance session/user | Session hijacking silencieux sur les routes optionnelles | Ajouter vérification `session.UserID == tokenUserID` | S |
|
|||
|
|
| VEZA-SEC-014 | A04 Design | **MOYEN** | `internal/middleware/csrf.go:153` | Un seul token CSRF par utilisateur → multi-onglet cassé | UX dégradée, utilisateurs forcés de rafraîchir | Implémenter pool de tokens ou token par session | M |
|
|||
|
|
| VEZA-SEC-015 | A05 Misconfig | **MOYEN** | `docker-compose.staging.yml:64` | `JWT_SECRET=${STAGING_JWT_SECRET}` sans check `?` → peut être vide | Staging potentiellement sans validation JWT | Ajouter `:?error message` | S |
|
|||
|
|
| VEZA-SEC-016 | A01 Access | **MOYEN** | `docker-compose.staging.yml` | Ports backend/frontend exposés directement sans reverse proxy | Pas de TLS termination, pas de WAF | Ajouter HAProxy comme en prod | M |
|
|||
|
|
| VEZA-SEC-017 | A09 Logging | **MOYEN** | Multiples fichiers | 15+ `fmt.Printf` dans le code production (upload_validator.go, router.go) | Bypass du logging structuré, potentielle fuite d'info | Remplacer par `logger.Debug()` | S |
|
|||
|
|
| VEZA-SEC-018 | A07 Auth | **FAIBLE** | `apps/web/src/features/auth/store/authStore.ts:352` | `isAuthenticated` persisté dans localStorage | XSS → bypass des guards UI (backend protège toujours) | Utiliser sessionStorage ou mémoire uniquement | S |
|
|||
|
|
| VEZA-SEC-019 | A02 Crypto | **FAIBLE** | `internal/services/password_service.go:150` | Coût bcrypt hardcodé `12` au lieu de la constante `bcryptCost` | Risque d'incohérence lors de maintenance | Utiliser la constante | S |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5️⃣ DETTE TECHNIQUE
|
|||
|
|
|
|||
|
|
### 5.1 Registre de la dette
|
|||
|
|
|
|||
|
|
| Cat. | Description | Fichier(s) | Impact | Effort |
|
|||
|
|
|------|-------------|-----------|--------|--------|
|
|||
|
|
| 🔴 | **Pipeline CD non fonctionnel** — secrets dans if conditions | `.github/workflows/cd.yml` | Pas de déploiement auto | S |
|
|||
|
|
| 🔴 | **Services Rust non intégrés** — gRPC stub, boot mode | Chat/Stream servers | 60% des features annoncées non disponibles | XL |
|
|||
|
|
| 🔴 | **Auth HLS/WebSocket cassée** — tokenStorage retourne null | Frontend services | Streaming/chat non fonctionnels | M |
|
|||
|
|
| 🔴 | **Versions Go incohérentes** — 1.24 (CI) vs 1.23 (Dockerfile) | CI + Dockerfile | Build divergence possible | S |
|
|||
|
|
| 🟠 | **Rate limiter in-memory** — ne scale pas | `ratelimit.go` | Sécurité dégradée en multi-instance | M |
|
|||
|
|
| 🟠 | **Postgres version incohérente** — 15 (test/hybrid) vs 16 (dev/prod) | docker-compose files | Tests passent sur mauvaise version | S |
|
|||
|
|
| 🟠 | **Code mort ~6,500+ LOC** — api_manager, docs.go, tokenStorage, commerceService mocks | Multiple | Confusion, maintenance inutile | M |
|
|||
|
|
| 🟠 | **22 fichiers Go >500 lignes** — track/handler.go (2,262), config.go (955) | Backend handlers | Complexité élevée, refactoring nécessaire | L |
|
|||
|
|
| 🟠 | **11 fichiers TS/TSX >500 lignes** — interceptors.ts (1,203), trackApi.ts (869) | Frontend services | Complexité élevée | L |
|
|||
|
|
| 🟠 | **`commerceService.ts` retourne des mocks en prod** — MOCK_PURCHASES, fake refund | `commerceService.ts` | Utilisateurs voient des fausses données | S |
|
|||
|
|
| 🟠 | **Migrations non transactionnelles** — SQL brut sans BEGIN/COMMIT | `migrations/*.sql` | État DB incohérent si migration échoue | M |
|
|||
|
|
| 🟡 | **90+ usages de `any` dans le frontend** (hors tests/generated) | Multiple .ts/.tsx | Perte de type safety | M |
|
|||
|
|
| 🟡 | **18 fichiers avec `console.log`** en production | Frontend src/ | Pollution console, pas de contrôle log level | S |
|
|||
|
|
| 🟡 | **15+ `fmt.Printf` dans le backend** | upload_validator, router | Bypass structured logging | S |
|
|||
|
|
| 🟡 | **gin.Logger() + gin.Recovery() en double** avec custom middleware | `main.go` + `router.go` | Double logging, double recovery | S |
|
|||
|
|
| 🟡 | **`gorilla/websocket` archivé** | `go.mod` | Plus de patches sécurité | M |
|
|||
|
|
| 🟡 | **chat-server sqlx-data.json vide** `{}` | `sqlx-data.json` | Builds offline impossibles | S |
|
|||
|
|
| 🟡 | **stream-server sqlx-data.json absent** | — | Builds offline impossibles | S |
|
|||
|
|
| ⚪ | **`APP_ENV` comparaison case-sensitive** — "Production" bypass | Multiple middleware | Risque théorique | S |
|
|||
|
|
| ⚪ | **Packages npm vides** — `packages/`, `fixtures/` | Monorepo config | Confusion | S |
|
|||
|
|
|
|||
|
|
### 5.2 Quantification
|
|||
|
|
|
|||
|
|
| Métrique | Go Backend | Rust Chat | Rust Stream | Frontend | Total |
|
|||
|
|
|----------|-----------|-----------|-------------|----------|-------|
|
|||
|
|
| **LOC source** | 87,930 | ~55,000 | ~72,000 | 130,976 | ~346,000 |
|
|||
|
|
| **LOC test** | 85,455 | ~5,000 | ~8,000 | 58,816 | ~157,000 |
|
|||
|
|
| **LOC stories** | — | — | — | 15,987 | 15,987 |
|
|||
|
|
| **Ratio test/code** | 0.97:1 | ~0.09:1 | ~0.11:1 | 0.45:1 | 0.45:1 |
|
|||
|
|
| **Fichiers source** | 402 | ~50 | ~80 | 1,275 | ~1,807 |
|
|||
|
|
| **Fichiers test** | 264 | ~28 | ~30 | 274 | ~596 |
|
|||
|
|
| **TODO/FIXME/HACK** | 20 | 5 | 5 | 8 | 38 |
|
|||
|
|
| **Fichiers >500 LOC** | 22 | ~10 | ~8 | 11 | ~51 |
|
|||
|
|
| **Code mort estimé** | ~6,500 | ~2,000 | ~1,000 | ~3,500 | ~13,000 |
|
|||
|
|
| **Dépendances directes** | 44 | ~25 | ~30 | ~45 | ~144 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6️⃣ QUALITÉ ARCHITECTURALE
|
|||
|
|
|
|||
|
|
### 6.1 Monorepo
|
|||
|
|
|
|||
|
|
| Critère | Évaluation |
|
|||
|
|
|---------|------------|
|
|||
|
|
| **Outil** | Turborepo — adapté, bien configuré |
|
|||
|
|
| **Build orchestration** | `turbo run build` — parallélisable, pas de cache custom |
|
|||
|
|
| **Versioning** | Unifié par release scope (v0.101 → v0.402) — correct |
|
|||
|
|
| **Dépendances internes** | Aucune shared package (`packages/` vide) — chaque service est indépendant |
|
|||
|
|
| **Workspace** | npm workspaces (root) + Go workspace (`go.work`) — cohérent |
|
|||
|
|
| **Problème** | Rust non intégré dans Turborepo — builds Rust gérés séparément via Makefile |
|
|||
|
|
|
|||
|
|
### 6.2 Frontend React
|
|||
|
|
|
|||
|
|
| Critère | Score |
|
|||
|
|
|---------|-------|
|
|||
|
|
| **Structure** | Feature-based (excellent) — `features/*/pages/`, `features/*/components/`, `features/*/hooks/` |
|
|||
|
|
| **State management** | Zustand (client) + React Query (server) — pattern moderne et correct |
|
|||
|
|
| **Data fetching** | React Query v5 avec invalidation, prefetching, optimistic updates |
|
|||
|
|
| **Routing** | React Router 6 avec lazy loading, route guards, preloading |
|
|||
|
|
| **Design system** | SUMI v2.0 — tokens CSS centralisés, composants shadcn/ui adaptés |
|
|||
|
|
| **TypeScript** | Strict mode activé, `noUncheckedIndexedAccess: true` — rigoureux |
|
|||
|
|
| **Storybook** | 288 stories, decorators avec providers, MSW intégré — mature |
|
|||
|
|
| **Accessibilité** | Audit A11Y documenté (`A11Y_AUDIT.md`), ARIA via shadcn/ui |
|
|||
|
|
| **MSW vs API** | 100% MSW pour composants/stories. API réelle uniquement en E2E |
|
|||
|
|
| **Problème** | Interceptors.ts à 1,203 lignes — trop complexe, à découper |
|
|||
|
|
|
|||
|
|
### 6.3 Backend Go
|
|||
|
|
|
|||
|
|
| Critère | Score |
|
|||
|
|
|---------|-------|
|
|||
|
|
| **Architecture** | Clean architecture avec séparation claire : handler → service → repository | ✅ |
|
|||
|
|
| **Error handling** | Custom `apperrors` package, errors wrappées, codes d'erreur HTTP cohérents | ✅ |
|
|||
|
|
| **Middleware stack** | 23 middlewares — complet et bien ordonné (CORS → Auth → CSRF → Handler) | ✅ |
|
|||
|
|
| **Database** | GORM + PostgreSQL, migrations numérotées, connection pooling via GORM | ✅ |
|
|||
|
|
| **Concurrency** | Graceful shutdown, context propagation, semaphore uploads | ✅ |
|
|||
|
|
| **Configuration** | Env vars validées au démarrage, production checks, secret masking | ✅ |
|
|||
|
|
| **API versioning** | `/api/v1/` — consistant | ✅ |
|
|||
|
|
| **OpenAPI** | `openapi.yaml` (3,655 lignes) + Swagger UI (dev only) | ✅ |
|
|||
|
|
| **Problème** | `track/handler.go` à 2,262 lignes — **urgent à découper** |
|
|||
|
|
|
|||
|
|
### 6.4 Services Rust
|
|||
|
|
|
|||
|
|
| Critère | Évaluation |
|
|||
|
|
|---------|------------|
|
|||
|
|
| **Chat server** | Architecture hub-based, Tokio runtime, WebSocket handler complet | Bien conçu |
|
|||
|
|
| **Stream server** | Transcoding engine, HLS segmenter, sync audio | Ambitieux |
|
|||
|
|
| **Compilation** | Compilent sans erreur (selon audit interne) | OK |
|
|||
|
|
| **Error handling** | anyhow + thiserror, propagation via `?` | Correct |
|
|||
|
|
| **Problème critique** | **Non intégrés au système** — boot mode OFF, gRPC stub, pas de tests d'intégration cross-service |
|
|||
|
|
| **Problème** | `unwrap()` en production : ~30 (chat), ~50 (stream) — certains dans des chemins critiques (rate_limiter, websocket handler) |
|
|||
|
|
| **Justification Go + Rust** | **Questionnable** pour cette taille d'équipe. Le chat server pourrait être un service Go avec gorilla/websocket. Le stream server est le seul cas justifiable (transcoding audio, performance). Le coût de maintenance de 3 langages est disproportionné. |
|
|||
|
|
|
|||
|
|
### 6.5 Base de données
|
|||
|
|
|
|||
|
|
| Critère | Évaluation |
|
|||
|
|
|---------|------------|
|
|||
|
|
| **Schéma** | 66 migrations backend, 10 chat, 2 stream — riche |
|
|||
|
|
| **Indexes** | pg_trgm pour recherche fuzzy, composite indexes, performance indexes |
|
|||
|
|
| **Extensions** | uuid-ossp, pg_trgm (migration 086) |
|
|||
|
|
| **FK constraints** | Migration 930 ajoute les FK manquantes — correction tardive |
|
|||
|
|
| **Audit triggers** | Migration 053, 910 — audit trail en DB |
|
|||
|
|
| **Problème** | Numérotation gaps (001→010→020, 069→070, 087→088→089→...→099→100→101→102, 900→910→920→930→931) — difficile à suivre |
|
|||
|
|
| **Problème** | Migration 100 fait 3 lignes (`ALTER TABLE orders ADD COLUMN discount_amount...`) — fragmentation excessive |
|
|||
|
|
| **Problème** | Pas de consolidation des 66 migrations — temps de setup initial long |
|
|||
|
|
| **Redis** | Cache, CSRF tokens, presence, trending, rate limiting (potentiel). Pas de TTL documenté systématiquement |
|
|||
|
|
|
|||
|
|
### 6.6 Scorecard
|
|||
|
|
|
|||
|
|
| Dimension | Score /10 | Justification |
|
|||
|
|
|-----------|-----------|---------------|
|
|||
|
|
| **Architecture** | **7/10** | Séparation claire des responsabilités, patterns modernes (feature-based frontend, clean arch backend). Perd des points : services Rust non intégrés, interceptors.ts monolithique, 3 langages pour une petite équipe. |
|
|||
|
|
| **Maintenabilité** | **6/10** | Code bien structuré mais 51 fichiers >500 LOC, 13K LOC de code mort, conventions parfois incohérentes (fmt.Printf vs logger). Documentation extensive mais parfois contradictoire. |
|
|||
|
|
| **Sécurité** | **5/10** | Bonnes bases (httpOnly cookies, bcrypt 12, CSRF, CSP, HSTS, secret masking). Perd des points : IDOR upload, rate limiter mémoire, Redis sans auth prod, auth HLS/WS cassée, CD pipeline mort, pprof enabled. |
|
|||
|
|
| **Scalabilité** | **4/10** | PostgreSQL single-instance, Redis SPOF, rate limiter mémoire, pas de load balancer config, WebSocket sticky sessions non gérées. Architecture permet le scaling théorique mais rien n'est configuré. |
|
|||
|
|
| **Testabilité** | **7/10** | Ratio test/code Go excellent (0.97:1), frontend correct (0.45:1), Storybook mature (288 stories). Perd des points : Rust quasi non testé, 100% MSW (aucun test composant contre API réelle), tests E2E fragiles (docker-compose full stack). |
|
|||
|
|
| **Opérabilité** | **3/10** | Pipeline CD non fonctionnel, staging incomplet (pas de chat/stream), Prometheus sans alerting, Grafana password admin, Redis sans auth. Perd beaucoup de points : impossible de déployer en production de manière fiable aujourd'hui. |
|
|||
|
|
| **Vélocité dev** | **6/10** | Storybook-first, MSW handlers, bonne documentation. Un dev React serait productif en <1 semaine. Un dev Go en ~2 semaines. Un dev Rust en 3+ semaines (code complexe, non documenté inline). |
|
|||
|
|
| **Maturité produit** | **3/10** | 14 features véritablement fonctionnelles E2E sur 600 annoncées (2.3%). 83/190 Tier 0 selon audit interne (44%). Score interne 32/100. Écart significatif entre documentation et réalité. |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7️⃣ INFRA & DEVOPS
|
|||
|
|
|
|||
|
|
### 7.1 Docker
|
|||
|
|
|
|||
|
|
| Critère | Résultat |
|
|||
|
|
|---------|---------|
|
|||
|
|
| **Dockerfiles** | Multi-stage, alpine, non-root — bien fait |
|
|||
|
|
| **docker-compose** | 5 fichiers (dev, prod, staging, test, hybrid) — trop, créent de la confusion |
|
|||
|
|
| **Secrets** | Env vars partout (pas de Docker secrets) — risque élevé en prod |
|
|||
|
|
| **Health checks** | Backend et Redis — OK. Frontend, Prometheus, Grafana — absents |
|
|||
|
|
| **Volumes** | Données persistées pour DB, Redis, RabbitMQ — OK |
|
|||
|
|
| **Réseau** | Prod: subnet /16 (trop large). Hybrid: host mode (aucune isolation) |
|
|||
|
|
| **Images** | ClamAV, Prometheus, Grafana en `latest` — non reproductible |
|
|||
|
|
|
|||
|
|
### 7.2 CI/CD
|
|||
|
|
|
|||
|
|
| Critère | Résultat |
|
|||
|
|
|---------|---------|
|
|||
|
|
| **Pipeline CI** | 12 workflows — couverture large mais incohérent (Go 1.23 vs 1.24) |
|
|||
|
|
| **Tests en CI** | Go tests + frontend tests + E2E — bonne couverture |
|
|||
|
|
| **Linting** | ESLint frontend. **Manque :** `go vet`, `gofmt`, `clippy` en CI |
|
|||
|
|
| **Security scanning** | Gitleaks uniquement. **Manque :** SAST (CodeQL), container scanning, DAST |
|
|||
|
|
| **Build** | Docker build en CI — oui, mais utilise le mauvais Dockerfile (dev au lieu de prod) |
|
|||
|
|
| **Deployment** | CD pipeline existe mais **ne fonctionne pas** (conditions secrets jamais vraies) |
|
|||
|
|
| **Environments** | Dev/staging/prod séparés en théorie. Staging manque chat/stream servers |
|
|||
|
|
| **Secrets management** | Hardcodés dans workflow files. Pas de vault. |
|
|||
|
|
|
|||
|
|
### 7.3 Reproductibilité
|
|||
|
|
|
|||
|
|
| Critère | Résultat |
|
|||
|
|
|---------|---------|
|
|||
|
|
| **Build one-command** | `docker compose up` pour dev — oui, fonctionnel |
|
|||
|
|
| **Onboarding** | Pas de ONBOARDING.md dédié. `.env.example` existe. README basique |
|
|||
|
|
| **Versions lockées** | `rust-toolchain.toml` (stable, pas de version), `go.work` (1.24), pas de `.nvmrc` |
|
|||
|
|
| **Lock files** | `go.sum` ✅, `Cargo.lock` ✅, `package-lock.json` ✅ |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 8️⃣ PERFORMANCE & SCALABILITÉ
|
|||
|
|
|
|||
|
|
| Composant | Risque | Seuil estimé | Mitigation |
|
|||
|
|
|-----------|--------|-------------|------------|
|
|||
|
|
| **PostgreSQL** | N+1 queries (GORM), full table scans possibles | >10K req/min | Indexes pg_trgm, composite indexes présents |
|
|||
|
|
| **Redis** | **SPOF** — CSRF, cache, presence, trending dépendent de Redis | Si Redis down : CSRF → 503, presence → stale, cache miss | Aucun fallback implémenté |
|
|||
|
|
| **Chat server** | WebSocket concurrentes, broadcast fan-out | >1000 connexions | Hub-based architecture, mais non testé sous charge réelle |
|
|||
|
|
| **Stream server** | Transcoding CPU-intensive, HLS segment serving | >100 streams simultanés | Semaphore pour limiter concurrence (bon) |
|
|||
|
|
| **File storage** | Stockage local par défaut, S3 optionnel | >10TB | S3 service implémenté mais non configuré par défaut |
|
|||
|
|
| **API Gateway** | Single instance, pas de load balancer configuré | >1000 req/s | HAProxy en prod compose mais config minimale |
|
|||
|
|
|
|||
|
|
**Scalabilité horizontale :** Le backend Go est stateless (sessions en DB, CSRF en Redis) — scalable horizontalement SI rate limiter migré vers Redis. Les services Rust ont des connexions WebSocket qui nécessitent sticky sessions ou Redis pub/sub pour broadcasting multi-instance.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 9️⃣ RISQUES BUSINESS
|
|||
|
|
|
|||
|
|
### 9.1 Point de vue CTO
|
|||
|
|
|
|||
|
|
| Question | Réponse |
|
|||
|
|
|----------|---------|
|
|||
|
|
| Recrutement productif <2 semaines ? | **Oui pour React** (Storybook-first, bonne doc, patterns standards). **Oui pour Go** (clean architecture, tests abondants). **Non pour Rust** (code complexe, non documenté, non intégré). |
|
|||
|
|
| Vélocité soutenable ? | **Non.** 12 releases en ~3 mois avec 345+ features déclarées = ~3 features/jour. L'audit interne confirme que seules 21.5% sont réellement fonctionnelles. La vélocité est une vélocité de code, pas de produit. |
|
|||
|
|
| Dette technique explosive ? | **Oui si le rythme continue.** 13K LOC de code mort, 51 fichiers >500 lignes, features fantômes documentées comme "operational". La divergence doc/réalité va s'aggraver. |
|
|||
|
|
| Refactorings inévitables ? | 1) Intégrer ou abandonner les services Rust. 2) Migrer rate limiter vers Redis. 3) Fixer le pipeline CD. 4) Consolider les migrations. |
|
|||
|
|
| Go + Rust + React justifié ? | **Partiellement.** Go + React = justifié et bien exécuté. Rust stream server = justifiable (audio transcoding). Rust chat server = **injustifié** — un service Go avec gorilla/websocket ferait le même travail avec une maintenance unifiée. |
|
|||
|
|
|
|||
|
|
### 9.2 Point de vue investisseur
|
|||
|
|
|
|||
|
|
| Question | Réponse |
|
|||
|
|
|----------|---------|
|
|||
|
|
| Produit fonctionnel ou démo ? | **Entre les deux.** 14 features fonctionnelles E2E constituent un MVP viable (auth, upload, tracks, playlists, marketplace). Mais les features différenciantes (streaming HLS, chat temps réel, WebRTC) sont non fonctionnelles. C'est un CMS audio avec marketplace, pas une plateforme de streaming. |
|
|||
|
|
| Risques sécurité publics ? | **Oui.** Redis sans auth en prod, IDOR sur uploads, pipeline CD mort, auth streaming cassée. Un audit de sécurité professionnel est nécessaire avant tout lancement. |
|
|||
|
|
| Code repris par une autre équipe ? | **Oui.** Le code Go et React est propre, bien structuré, avec de bons tests. Le Rust est plus risqué (non intégré, peu documenté). Un onboarding de 3-4 semaines est réaliste pour une équipe de 3 devs (1 Go, 1 React, 1 Rust/infra). |
|
|||
|
|
| Coût v1.0 production-ready ? | **3-4 mois, 2-3 développeurs** (estimation basée sur : fixer sécurité 2 semaines, stabiliser services Rust 4 semaines, fixer CD/infra 2 semaines, tests E2E complets 2 semaines, polish UX 2 semaines). |
|
|||
|
|
| IP technique défendable ? | **Limitée.** Architecture standard (Go API + React SPA), pas d'algorithme propriétaire, pas de technologie unique. La valeur est dans l'exécution (qualité du code, design system SUMI, couverture tests) plutôt que dans l'innovation technique. |
|
|||
|
|
| Ratio features/qualité ? | **Red flag modéré.** La quantité (345 features déclarées) masque la qualité (21.5% fonctionnelles). Mais les features qui fonctionnent sont bien implémentées avec des tests. C'est un problème de scope control, pas de compétence. |
|
|||
|
|
|
|||
|
|
### 9.3 Point de vue acquéreur
|
|||
|
|
|
|||
|
|
| Question | Réponse |
|
|||
|
|
|----------|---------|
|
|||
|
|
| Code réutilisable ? | **Oui à 70%.** Backend Go et frontend React sont réutilisables. Services Rust = à réévaluer (garder stream, réécrire chat en Go). Infra = à refaire proprement. |
|
|||
|
|
| Données migrables ? | **Oui.** PostgreSQL standard, schéma normalisé, migrations numérotées. Export/import straightforward. |
|
|||
|
|
| Vendor-lock ? | **Faible.** Hyperswitch (paiement) est un choix moins mainstream que Stripe mais l'interface est abstraite. Pas de lock cloud (S3 compatible). |
|
|||
|
|
| Onboarding 5 devs ? | **4-6 semaines.** 2 semaines pour Go/React (bien documenté), 4 semaines pour Rust + infra (complexe, non documenté). |
|
|||
|
|
| Score rachetabilité ? | **6/10.** Code propre et testable, architecture saine, stack mainstream. Perd des points : 3 langages, services non intégrés, écart doc/réalité, dette infra. |
|
|||
|
|
|
|||
|
|
### 9.4 Verdict
|
|||
|
|
|
|||
|
|
| Question | Réponse | Justification |
|
|||
|
|
|----------|---------|---------------|
|
|||
|
|
| Lancer en production tel quel ? | **Non** | CD pipeline mort, Redis sans auth, auth streaming cassée, features fantômes |
|
|||
|
|
| Vendre / monétiser tel quel ? | **Non** | Checkout en mode test, webhook paiement non vérifié, features commerciales (streaming, chat) non fonctionnelles |
|
|||
|
|
| Maintenir avec 2 devs ? | **Conditionnel** | Oui si on abandonne les services Rust et se concentre sur Go + React. Non si on veut tout maintenir. |
|
|||
|
|
| Refactorer avant prod ? | **Oui** | Sécurité (2 semaines) + infra (2 semaines) + intégration services (4 semaines) minimum |
|
|||
|
|
| Réécrire certains services ? | **Oui** | Chat server Rust → service Go. Le stream server Rust peut être conservé mais doit être intégré. |
|
|||
|
|
| Vélocité = red flag ? | **Oui, modéré** | 345 features déclarées en ~3 mois avec un écart de 78% entre déclaré et fonctionnel suggère une optimisation pour les métriques plutôt que pour la valeur produit. Mais le code qui existe est de qualité correcte — ce n'est pas du "feature stuffing" de basse qualité. |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🔟 PLAN D'ACTION PRIORISÉ
|
|||
|
|
|
|||
|
|
### Phase 1 — Critique (semaines 1-2) — Sécurité & CI/CD
|
|||
|
|
|
|||
|
|
| # | Quoi | Pourquoi | Fichiers | Effort |
|
|||
|
|
|---|------|----------|----------|--------|
|
|||
|
|
| 1 | **Fixer pipeline CD** — remplacer `secrets.*` par `vars.*` dans les `if`, utiliser `Dockerfile.production`, ajouter `needs: ci` | Aucun déploiement ne fonctionne | `.github/workflows/cd.yml` | S |
|
|||
|
|
| 2 | **Redis auth en production** — ajouter `--requirepass`, configurer `REDIS_PASSWORD` | Cache/CSRF compromettable | `docker-compose.prod.yml` | S |
|
|||
|
|
| 3 | **Ajouter `JWT_SECRET` au stream-server** prod compose | Service potentiellement sans auth | `docker-compose.prod.yml:217` | S |
|
|||
|
|
| 4 | **Supprimer `docker-compose.hybrid.yml`** ou fixer network_mode | Infrastructure ouverte au réseau | `docker-compose.hybrid.yml` | S |
|
|||
|
|
| 5 | **Fixer auth HLS/WebSocket** — implémenter cookie-based auth ou stream token endpoint | Streaming non protégé | `hlsService.ts`, `websocket.ts`, backend `/auth/stream-token` | M |
|
|||
|
|
| 6 | **Unifier version Go** — 1.24 partout (go.mod, CI, Dockerfile) | Builds divergents | `go.mod`, `ci.yml`, `backend-ci.yml`, `Dockerfile.production` | S |
|
|||
|
|
| 7 | **Migrer secrets CI vers GitHub Secrets** | Credentials en clair dans le repo | `.github/workflows/ci.yml` | S |
|
|||
|
|
| 8 | **Fixer IDOR GetUploadStatus** — ajouter ownership check | Fuite d'information | `internal/handlers/upload.go:308` | S |
|
|||
|
|
| 9 | **Ajouter validation SSRF webhooks** — whitelist schéma, bloquer IPs privées | SSRF via webhook delivery | `webhook_handlers.go`, webhook delivery service | S |
|
|||
|
|
| 10 | **Vérifier webhook Hyperswitch** — signature HMAC-SHA256 | Paiements potentiellement non vérifiés | Handler webhook paiement (à localiser/créer) | M |
|
|||
|
|
|
|||
|
|
### Phase 2 — Stabilisation (semaines 3-6)
|
|||
|
|
|
|||
|
|
| # | Quoi | Pourquoi | Effort |
|
|||
|
|
|---|------|----------|--------|
|
|||
|
|
| 11 | **Migrer rate limiter vers Redis** | Sécurité multi-instance | M |
|
|||
|
|
| 12 | **Aligner Postgres 16 partout** (test, hybrid) | Tests sur mauvaise version | S |
|
|||
|
|
| 13 | **Compléter staging compose** (chat, stream, reverse proxy) | Staging ne reflète pas la prod | M |
|
|||
|
|
| 14 | **Ajouter alerting Prometheus** (service down, error rate, latence) | Monitoring sans alerting = inutile | M |
|
|||
|
|
| 15 | **Supprimer code mort** (~13K LOC) | Confusion, maintenance inutile | M |
|
|||
|
|
| 16 | **Supprimer/corriger commerceService mocks** | Données factices en production | S |
|
|||
|
|
| 17 | **Ajouter `go vet`, `clippy`, `gofmt` en CI** | Qualité code non vérifiée en CI | S |
|
|||
|
|
| 18 | **Remplacer `fmt.Printf` par logger structuré** (15+ occurrences) | Fuite d'info, bypass logging | S |
|
|||
|
|
| 19 | **Ajouter SAST en CI** (CodeQL ou Semgrep) | Vulnérabilités non détectées automatiquement | M |
|
|||
|
|
| 20 | **Fixer `frontend-ci.yml`** — ajouter lint, typecheck, build | PRs frontend sans vérification | S |
|
|||
|
|
|
|||
|
|
### Phase 3 — Consolidation (semaines 7-12)
|
|||
|
|
|
|||
|
|
| # | Quoi | Pourquoi | Effort |
|
|||
|
|
|---|------|----------|--------|
|
|||
|
|
| 21 | **Intégrer ou abandonner le chat server Rust** | Service non connecté, coût de maintenance | XL |
|
|||
|
|
| 22 | **Intégrer le stream server** — connecter gRPC, activer HLS | Feature différenciante non fonctionnelle | XL |
|
|||
|
|
| 23 | **Découper fichiers >1000 LOC** (track/handler.go, interceptors.ts, config.go) | Complexité maintenance | L |
|
|||
|
|
| 24 | **Consolider migrations** — squash 66 migrations en baseline | Setup initial long | L |
|
|||
|
|
| 25 | **Éliminer 90+ `any` dans le frontend** | Type safety dégradée | M |
|
|||
|
|
| 26 | **Remplacer `gorilla/websocket`** (archivé) | Plus de patches sécurité | M |
|
|||
|
|
| 27 | **Ajouter tests d'intégration cross-service** | Services jamais testés ensemble | L |
|
|||
|
|
| 28 | **Mettre en place Docker secrets** pour la prod | Secrets dans env vars | M |
|
|||
|
|
| 29 | **Aligner FEATURE_STATUS avec la réalité** | Écart doc/code = perte de confiance | S |
|
|||
|
|
| 30 | **Implémenter hash des reset tokens** | Sécurité en cas de compromission DB | S |
|
|||
|
|
|
|||
|
|
### Phase 4 — Évolution (mois 4+)
|
|||
|
|
|
|||
|
|
- Activer Hyperswitch en mode production
|
|||
|
|
- Implémenter payout (Stripe Connect — v0.403)
|
|||
|
|
- Compléter analytics (7% → 50%+)
|
|||
|
|
- Implémenter social (13% → 50%+)
|
|||
|
|
- Évaluer migration React 19
|
|||
|
|
- Considérer réécriture chat server en Go
|
|||
|
|
- Mettre en place blue-green deployment
|
|||
|
|
- Ajouter container image scanning en CI
|
|||
|
|
- Implémenter IaC (Terraform/Pulumi)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## ANNEXES
|
|||
|
|
|
|||
|
|
### A. Arbre des dépendances inter-services
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌──────────────┐
|
|||
|
|
│ Frontend │
|
|||
|
|
│ React/Vite │
|
|||
|
|
└──────┬───────┘
|
|||
|
|
│
|
|||
|
|
┌────────────┼────────────┐
|
|||
|
|
│ │ │
|
|||
|
|
▼ ▼ ▼
|
|||
|
|
┌────────────┐ ┌──────────┐ ┌──────────┐
|
|||
|
|
│ Backend Go │ │Chat Rust │ │Stream │
|
|||
|
|
│ (API REST) │ │(WebSocket│ │Rust (HLS)│
|
|||
|
|
└─────┬──────┘ └────┬─────┘ └────┬─────┘
|
|||
|
|
│ │ │
|
|||
|
|
┌─────┼─────┐ ┌────┘ ┌───┘
|
|||
|
|
│ │ │ │ │
|
|||
|
|
▼ ▼ ▼ ▼ ▼
|
|||
|
|
┌────┐ ┌────┐ ┌─────┐ ┌───────────┐
|
|||
|
|
│ PG │ │Redis│ │Rabbit│ │ PG (chat) │
|
|||
|
|
└────┘ └────┘ └─────┘ └───────────┘
|
|||
|
|
|
|||
|
|
Légende:
|
|||
|
|
──── = Connexion fonctionnelle
|
|||
|
|
- - - = Connexion prévue mais non connectée (gRPC stub)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### B. Métriques brutes
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
Total LOC (source + test + stories) : ~519,000
|
|||
|
|
Total fichiers source : ~2,400
|
|||
|
|
Total fichiers test : ~596
|
|||
|
|
Total stories : 288
|
|||
|
|
Total migrations SQL : 78
|
|||
|
|
Total workflows CI : 12
|
|||
|
|
Total scripts : 85+
|
|||
|
|
Total docs markdown : 332
|
|||
|
|
Total dépendances directes : ~144
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### C. Fichiers critiques à auditer en priorité
|
|||
|
|
|
|||
|
|
1. `veza-backend-api/internal/middleware/auth.go` (704 LOC)
|
|||
|
|
2. `veza-backend-api/internal/middleware/ratelimit.go` (189 LOC)
|
|||
|
|
3. `veza-backend-api/internal/config/config.go` (955 LOC)
|
|||
|
|
4. `apps/web/src/services/api/interceptors.ts` (1,203 LOC)
|
|||
|
|
5. `apps/web/src/services/tokenStorage.ts` (107 LOC)
|
|||
|
|
6. `.github/workflows/cd.yml` (170 LOC)
|
|||
|
|
7. `docker-compose.prod.yml` (301 LOC)
|
|||
|
|
8. `veza-backend-api/internal/handlers/upload.go` (627 LOC)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## CONCLUSION STRATÉGIQUE
|
|||
|
|
|
|||
|
|
Veza est un projet techniquement compétent dans son exécution Go/React, mais souffrant d'un **excès d'ambition architecturale** par rapport à ses ressources. Le choix de trois langages (Go, Rust, TypeScript) pour un MVP crée une charge de maintenance disproportionnée. Les services Rust, bien que compilables, ne sont pas intégrés au système et représentent ~132K LOC de code non productif.
|
|||
|
|
|
|||
|
|
**La recommandation stratégique est : investir, mais avec recadrage.**
|
|||
|
|
|
|||
|
|
Le code Go et React constitue une base solide et testée. La sécurité auth (httpOnly cookies, JWT 5min, bcrypt 12) est supérieure à la moyenne des startups early-stage. Le design system SUMI et l'approche Storybook-first démontrent une maturité UX réelle.
|
|||
|
|
|
|||
|
|
Cependant, l'écart entre le narratif (345+ features, 12 releases) et la réalité (14 features E2E, score interne 32/100) est un signal d'alarme pour un investisseur. Ce n'est pas un signe de mauvaise foi technique — le code qui existe est de qualité — mais d'un scope management déficient et d'une communication produit trop optimiste.
|
|||
|
|
|
|||
|
|
**Avec 4-6 semaines de stabilisation ciblée et un recadrage stratégique (abandonner le chat Rust, intégrer le stream server, fixer l'infra), Veza peut devenir un MVP commercialisable.** Sans ce recadrage, la dette technique et l'écart doc/réalité continueront de croître, rendant le produit de plus en plus difficile à maintenir et à vendre.
|
|||
|
|
|
|||
|
|
**Verdict final : Investir sous condition de recadrage technique et produit dans les 60 jours.**
|