diff --git a/.gitignore b/.gitignore
index d619fd365..9517c46c5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -98,6 +98,10 @@ docker-data/
docker/haproxy/certs/*.key
docker/haproxy/certs/*.pem
+# JWT RSA keys (v0.9.1 RS256 migration — NEVER commit)
+jwt-private.pem
+jwt-public.pem
+
veza-backend-api/main
veza-backend-api/api
veza-backend-api/migrate_tool
diff --git a/AUDIT_TECHNIQUE_VEZA_2026-03-04.md b/AUDIT_TECHNIQUE_VEZA_2026-03-04.md
new file mode 100644
index 000000000..e9f56d2f4
--- /dev/null
+++ b/AUDIT_TECHNIQUE_VEZA_2026-03-04.md
@@ -0,0 +1,913 @@
+# 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
+
+```mermaid
+flowchart TB
+ subgraph client [Client Browser]
+ ReactApp["React SPA
Vite + HLS.js"]
+ end
+
+ subgraph proxy [Reverse Proxy]
+ HAProxy["HAProxy 2.8
Blue-Green"]
+ end
+
+ subgraph backend [Backend API - Go]
+ GinRouter["Gin Router
Middleware Chain"]
+ AuthSvc["Auth Service
JWT HS256"]
+ TrackSvc["Track Service"]
+ MarketSvc["Marketplace Service"]
+ SocialSvc["Social Service"]
+ ChatWS["Chat WebSocket
Hub Pattern"]
+ UploadSvc["Upload Service
ClamAV Scan"]
+ end
+
+ subgraph stream [Stream Server - Rust]
+ AxumRouter["Axum Router"]
+ HLSGen["HLS Generator
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 | `streaming/hls.rs`, `auth/mod.rs` |
+| Live Streaming | Routes backend + stream server | Frontend pages existent, dépend du stream server | `routes_core.go`, `live_stream` handlers |
+| Cloud Storage | Backend CRUD + S3 | Frontend pages + share links | Opérationnel mais feature flag masquée | `cloud_handler.go` |
+| GDPR Export | Backend async export | Frontend trigger + download | Long-running avec `context.Background()` | `gdpr_export.go` |
+
+#### 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.
+
diff --git a/CURSOR_PROMPT_VERSIONING.md b/CURSOR_PROMPT_VERSIONING.md
new file mode 100644
index 000000000..279c6531e
--- /dev/null
+++ b/CURSOR_PROMPT_VERSIONING.md
@@ -0,0 +1,147 @@
+# PROMPT CURSOR — Initialisation / Mise à jour du système de versionnage Veza
+
+---
+
+## USAGE
+
+Ce prompt est à utiliser dans deux cas :
+1. **Première initialisation** : créer `VEZA_VERSIONS_ROADMAP.md` à partir des ORIGIN docs
+2. **Mise à jour** : ajuster le roadmap après une évolution du projet
+
+Pour le travail quotidien, tu n'as pas besoin de ce prompt.
+Dis simplement à Cursor : **"implémente la prochaine version"**
+
+---
+
+## PROMPT À COLLER DANS CURSOR
+
+```
+Tu es l'architecte principal du projet Veza, une plateforme de collaboration audio pour musiciens indépendants.
+
+## Contexte
+
+Le projet possède une documentation de référence dans le dossier ORIGIN/ du monorepo :
+- ORIGIN_MASTER_ARCHITECTURE.md — architecture système complète
+- ORIGIN_FEATURES_REGISTRY.md — registre des 560 features actives (40 supprimées pour raisons éthiques)
+- ORIGIN_IMPLEMENTATION_TASKS.md — tâches d'implémentation avec priorités P0/P1
+- ORIGIN_SECURITY_FRAMEWORK.md — framework de sécurité (dont VEZA-SEC-001/002 critiques)
+- ORIGIN_DEVELOPMENT_PHASES.md — phases P3.5 → P6R
+- ORIGIN_REVISION_SUMMARY.md — résumé de la révision éthique v2.0.0
+- ORIGIN_CODE_STANDARDS.md — standards de code Go/Rust/TypeScript
+- ORIGIN_FEATURE_VALIDATION_STRATEGY.md — checklist de validation (dont Phase 7 éthique)
+- ORIGIN_ERROR_PATTERNS.md — patterns d'erreur à éviter (PAT-024 à PAT-028)
+- ORIGIN_BUSINESS_LOGIC.md — règles métier et principes éthiques
+
+## Ta mission
+
+Lire TOUS ces fichiers ORIGIN, puis créer (ou mettre à jour) le fichier `VEZA_VERSIONS_ROADMAP.md` à la racine du repo.
+
+Ce fichier est le système de versionnage opérationnel du projet. Il doit permettre de dire simplement "implémente la prochaine version" pour déclencher une session de travail complète, autonome, et correcte.
+
+## Structure requise du fichier VEZA_VERSIONS_ROADMAP.md
+
+### Pour chaque version, inclure :
+
+1. **Numéro de version** (ex: v0.9.1) en suivant le schéma :
+ - v0.9.x : Phase P3.5 (Consolidation & Sécurité)
+ - v0.10.x : Phase P4R (Social & Live)
+ - v0.11.x : Phase P5R (Analytics & Recherche)
+ - v0.12.x : Phase P6R (Premium & Infrastructure)
+ - v1.0.0 : Release stable
+
+2. **Nom descriptif** de la version (ex: "JWT Migration RS256")
+
+3. **Statut** : ⏳ TODO | 🔄 IN PROGRESS | ✅ DONE
+
+4. **Priorité** : P0 (bloquant) | P1 (haute) | P2 (moyenne) | P3 (basse)
+
+5. **Durée estimée** en jours
+
+6. **Prerequisite** : liste des versions qui doivent être DONE avant
+
+7. **Objectif** : une phrase claire sur ce que cette version accomplit
+
+8. **Tâches** : liste de checkboxes avec :
+ - Référence aux TASK-XXX de ORIGIN_IMPLEMENTATION_TASKS.md si applicable
+ - Référence aux features Fxxx de ORIGIN_FEATURES_REGISTRY.md
+ - Description précise de ce qui doit être implémenté
+ - Fichiers principaux à modifier (backend, frontend, infra)
+
+9. **Critères d'acceptation** : liste de conditions vérifiables (pas ambiguës)
+
+### Contraintes absolues (à respecter dans tout le fichier)
+
+- Les versions doivent être **atomiques** : chaque version est mergeable indépendamment
+- Les versions doivent être **séquentielles** dans chaque phase (pas de parallélisme)
+- Les tâches P0 de ORIGIN_IMPLEMENTATION_TASKS.md (TASK-SEC-001/002) passent EN PREMIER
+- Aucune version ne doit implémenter du code AI/ML, blockchain/Web3, ou gamification addictive
+- Les critères d'acceptation doivent être **vérifiables automatiquement** (tests, métriques) ou **vérifiables manuellement** (checklist UX)
+- La Phase 7 de validation éthique de ORIGIN_FEATURE_VALIDATION_STRATEGY.md s'applique à toute version touchant la découverte, les métriques, ou les interactions sociales
+
+### Section finale obligatoire : "Instructions pour Cursor"
+
+À la fin du fichier, inclure une section expliquant le protocole à suivre quand Cursor reçoit "implémente la prochaine version" :
+1. Identifier la prochaine version TODO
+2. Vérifier les prerequisites
+3. Lire les fichiers ORIGIN référencés
+4. Implémenter
+5. Valider selon ORIGIN_FEATURE_VALIDATION_STRATEGY.md
+6. Marquer comme DONE dans ce fichier
+7. Créer le tag git
+
+### Section finale obligatoire : "Règles immuables pour Cursor"
+
+Liste des choses que Cursor ne doit JAMAIS faire, dérivées de la révision éthique v2.0.0.
+
+## Critères de qualité du fichier généré
+
+- Le fichier doit être complet : de v0.9.1 jusqu'à v1.0.0, sans saut
+- Chaque version doit avoir minimum 3 tâches et 3 critères d'acceptation
+- Les références aux fichiers ORIGIN doivent être exactes (section + numéro de feature)
+- Les durées estimées doivent être réalistes (1 développeur, pas d'optimisme excessif)
+- Les prerequisites doivent former un graphe acyclique cohérent
+
+## Ce que tu NE dois PAS faire
+
+- Ne pas modifier les fichiers ORIGIN/ (ils sont en lecture seule)
+- Ne pas créer d'autres fichiers que VEZA_VERSIONS_ROADMAP.md
+- Ne pas inventer des features qui ne sont pas dans les ORIGIN docs
+- Ne pas ignorer les features supprimées pour raisons éthiques (F456-F470, F491-F500, F536-F550)
+
+## Format de sortie
+
+Fichier Markdown unique : VEZA_VERSIONS_ROADMAP.md
+Encodage : UTF-8
+Longueur : aussi long que nécessaire pour être complet et exploitable
+
+Commence par lire tous les fichiers ORIGIN/ avant d'écrire une seule ligne du fichier de sortie.
+```
+
+---
+
+## NOTES D'UTILISATION
+
+### Pour initialiser le roadmap (première fois)
+Colle le prompt ci-dessus dans Cursor. Il lira tes ORIGIN docs et générera le fichier.
+
+### Pour implémenter une version (usage quotidien)
+Dis simplement à Cursor dans un nouveau chat :
+```
+Implémente la prochaine version. Le fichier VEZA_VERSIONS_ROADMAP.md
+est à la racine du repo et contient les instructions.
+```
+
+### Pour mettre à jour le roadmap après un changement d'architecture
+```
+Le fichier VEZA_VERSIONS_ROADMAP.md est à la racine du repo.
+[Décrire le changement].
+Mets à jour les versions concernées sans toucher aux versions déjà DONE
+et sans modifier les fichiers ORIGIN/.
+```
+
+### Pour voir où en est le projet
+```
+Donne-moi un résumé de l'avancement dans VEZA_VERSIONS_ROADMAP.md :
+versions DONE, version en cours, prochaine version, et estimation
+pour atteindre v1.0.0.
+```
diff --git a/ORIGIN_GAP_ANALYSIS_2026-03-04.md b/ORIGIN_GAP_ANALYSIS_2026-03-04.md
new file mode 100644
index 000000000..b674390ac
--- /dev/null
+++ b/ORIGIN_GAP_ANALYSIS_2026-03-04.md
@@ -0,0 +1,989 @@
+# ORIGIN GAP ANALYSIS — Veza Platform
+## Date: 4 mars 2026
+
+---
+
+## 1. RÉSUMÉ EXÉCUTIF
+
+### Position sur la Timeline ORIGIN
+
+Le plan ORIGIN définit **600 features** réparties sur **8 phases** en **24 mois** (février 2025 – janvier 2027). Selon ce calendrier, en mars 2026, le projet devrait achever la **Phase 5** (Intelligence & Analytics) avec **~360 features cumulées**.
+
+**État réel** : le projet se situe au niveau de la **Phase 3 complétée** avec environ **~231 features individuelles** implémentées (dont ~55 partiellement), ce qui le place approximativement **6 mois en retard** sur le planning ORIGIN.
+
+### Métriques Clés
+
+| Indicateur | Objectif ORIGIN (mars 2026) | État Actuel | Écart |
+|---|---|---|---|
+| Features cumulées | 360 (fin P5) | ~231 (dont ~55 partielles) | -129 features |
+| Couverture tests | ≥ 80% | ~50% (frontend), non mesuré (Go) | -30% |
+| Vulnérabilités critiques | 0 | 2 (JWT default Rust, JWT mismatch) | -2 |
+| Phases complètes | P0 à P5 | P0 à P3 (P4 à ~30%) | -2 phases |
+| Uptime | 99.9% | Non mesuré en prod | N/A |
+| MAU | 5,000+ (P5) | Pre-launch | N/A |
+| MRR | $30,000+ (P5) | $0 (pre-launch) | N/A |
+
+### Complétion Globale
+
+| Catégorie | ORIGIN | Actuel | % |
+|---|---|---|---|
+| Features implémentées | 600 | ~176 pleinement | 29% |
+| Features partielles | — | ~55 | 9% |
+| Features manquantes | — | ~369 | 62% |
+| Architecture conforme | 100% | ~70% | — |
+| Qualité conforme | 100% | ~45% | — |
+
+### Verdict
+
+Le projet a construit des **fondations solides** (auth complète, streaming fonctionnel, marketplace opérationnel, infrastructure CI/CD mature) mais accuse un retard significatif par rapport au planning ORIGIN. Ce retard est principalement dû à :
+
+1. **Scope réaliste** : le plan ORIGIN avec 600 features en 24 mois pour une équipe de 2-8 devs est extrêmement ambitieux
+2. **Pivots architecturaux** : migration chat Rust→Go, Stripe→Hyperswitch, simplification de la stack
+3. **Modules abandonnés** : Education (F276-F305), Gamification (F536-F550)
+4. **Phases 5-8 non démarrées** : AI, Enterprise, Web3, VR/AR
+
+---
+
+## 2. MATRICE DE COMPLÉTION PAR PHASE
+
+### Vue d'ensemble
+
+```
+ORIGIN Timeline vs Réalité (mars 2026)
+
+Phase Prévu Réel Features Complétion
+─────────────────────────────────────────────────────────────
+P0 Fév 2025 ✅ Fait 0 (stab) 85%
+P1 Mar-Avr 2025 ✅ Fait 50 90%
+P2 Mai-Jun 2025 ✅ Fait 60 80%
+P3 Jul-Sep 2025 ⚠️ Partiel 80 65%
+P4 Oct-Déc 2025 ⚠️ ~30% 90 30%
+P5 Jan-Mar 2026 ❌ Non 80 5%
+P6 Avr-Jun 2026 ❌ Non 70 10%
+P7 Jul-Sep 2026 ❌ Non 90 5%
+P8 Oct-Jan 2027 ❌ Non 80 0%
+```
+
+### Phase 0 : Stabilisation (1 mois) — COMPLÉTÉE à 85%
+
+**Objectif ORIGIN** : Stabiliser l'existant, CI/CD, coverage 80%, monitoring, documentation, 0 bugs critiques.
+
+| Livrable ORIGIN | Objectif | État Actuel | Statut |
+|---|---|---|---|
+| L0.1 CI/CD pipeline fonctionnel | Pipeline vert | 14 workflows GitHub Actions | ✅ DÉPASSÉ |
+| L0.2 Tests coverage > 80% backend | 80% Go | 306 fichiers test, seuil non enforced | ⚠️ NON VÉRIFIÉ |
+| L0.3 Tests coverage > 80% Rust | 80% Rust | Stream server : pas de coverage CI | ❌ NON ATTEINT |
+| L0.4 Tests E2E frontend (10 scenarios) | 10 scénarios | Playwright configuré, specs existantes | ⚠️ PARTIEL |
+| L0.5 Prometheus + Grafana opérationnels | Monitoring | Configs Prometheus/Grafana/Alertmanager dans docker-compose prod | ✅ ATTEINT |
+| L0.6 Documentation ORIGIN complète | 15/15 docs | 22 documents ORIGIN | ✅ DÉPASSÉ |
+| L0.7 Zero bugs critiques | 0 critiques | 2 vulns critiques (JWT) | ❌ NON ATTEINT |
+| L0.8 Build vert stable 7 jours | Stabilité | CI vert sur main | ✅ ATTEINT |
+
+**Critères bloquants non atteints** : Coverage 80% non mesurée, 2 vulnérabilités critiques ouvertes.
+
+### Phase 1 : MVP Core (2 mois, 50 features) — COMPLÉTÉE à 90%
+
+**Objectif ORIGIN** : MVP fonctionnel — Auth, Profils, Streaming basique, Upload.
+
+| Module ORIGIN | Features | Implémentées | Partielles | Manquantes |
+|---|---|---|---|---|
+| Auth (F001-F015) | 15 | 13 | 1 (F008) | 1 (F014) |
+| Profils basiques (F031-F040) | 10 | 10 | 0 | 0 |
+| Streaming basique (F106-F120) | 15 | 12 | 2 (F119,F122) | 1 (F120) |
+| Upload (F066-F075) | 10 | 8 | 1 (F072) | 1 (F069) |
+| **Total P1** | **50** | **43** | **4** | **3** |
+
+**Features manquantes P1** : Password history (F014), URL import (F069), Equalizer (F120).
+
+### Phase 2 : Features Essentielles (2 mois, 60 features) — COMPLÉTÉE à 80%
+
+**Objectif ORIGIN** : Playlists, Chat, Social basique.
+
+| Module ORIGIN | Features | Implémentées | Partielles | Manquantes |
+|---|---|---|---|---|
+| Streaming suite (F121-F145) | 25 | 18 | 3 | 4 |
+| Chat (F151-F170) | 20 | 8 | 6 | 6 |
+| Social basique (F186-F200) | 15 | 8 | 4 | 3 |
+| **Total P2** | **60** | **34** | **13** | **13** |
+
+**Écarts notables P2** :
+- Chat migré de Rust vers Go (ADR-002) — fonctionnel mais features avancées manquantes (reactions, mentions, markdown, GIFs)
+- Social : follow/unfollow implémenté, mais pas de recommendations, QR code, close friends
+- Playlists : CRUD complet, collaboration, mais pas de smart playlists ni export
+
+### Phase 3 : Marketplace & Monétisation (3 mois, 80 features) — COMPLÉTÉE à 65%
+
+**Objectif ORIGIN** : Marketplace, Education, Hardware.
+
+| Module ORIGIN | Features | Implémentées | Partielles | Manquantes |
+|---|---|---|---|---|
+| Marketplace (F226-F275) | 50 | 28 | 10 | 12 |
+| Education (F276-F290) | 15 | 0 | 6 (backend only) | 9 |
+| Hardware/Gear (F306-F320) | 15 | 12 | 2 | 1 |
+| **Total P3** | **80** | **40** | **18** | **22** |
+
+**Écarts notables P3** :
+- **Education** : Backend et DB schema existent (`core/education/`), mais tests skippés et aucun frontend — module effectivement non livré
+- **Marketplace** : CRUD produits, licences (personal/commercial/exclusive), cart, checkout Hyperswitch — mais pas de PayPal/crypto, pas de e-signature, pas de licence history
+- **Paiement** : Hyperswitch au lieu de Stripe (pivot architectural documenté)
+
+### Phase 4 : Social & Collaboration (3 mois, 90 features) — COMPLÉTÉE à 30%
+
+**Objectif ORIGIN** : Social avancé, Collaboration DAW, Live streaming, Gamification.
+
+| Module ORIGIN | Features | Implémentées | Partielles | Manquantes |
+|---|---|---|---|---|
+| Social avancé (F201-F225) | 25 | 5 | 8 | 12 |
+| Collaboration (F481-F510) | 30 | 2 (playlist collab) | 0 | 28 |
+| Live Streaming (F471-F490) | 20 | 3 | 4 | 13 |
+| Gamification (F536-F550) | 15 | 0 | 2 (frontend UI only) | 13 |
+| **Total P4** | **90** | **10** | **14** | **66** |
+
+**Écarts notables P4** :
+- **DAW Collaboration** : non implémenté (0/30 features)
+- **Gamification** : supprimée du scope en v0.971 — `ProfileXPView` et `AchievementCard` existent côté frontend mais sans backend
+- **Live Streaming** : infrastructure HLS basique en place, `GoLiveView` et `TipStreamerModal` existent, mais features avancées manquantes
+- **WebRTC** : code présent mais non fonctionnel (dépendance commentée)
+
+### Phase 5 : Intelligence & Analytics (3 mois, 80 features) — COMPLÉTÉE à 5%
+
+| Module ORIGIN | Features | Implémentées | Partielles | Manquantes |
+|---|---|---|---|---|
+| AI/ML (F456-F470) | 15 | 0 | 2 (similarity, BPM detect) | 13 |
+| Analytics (F381-F410) | 30 | 4 | 8 | 18 |
+| Search avancé (F351-F370) | 20 | 4 | 6 | 10 |
+| Education suite (F291-F305) | 15 | 0 | 0 | 15 |
+| **Total P5** | **80** | **8** | **16** | **56** |
+
+### Phase 6 : Monétisation Avancée (3 mois, 70 features) — COMPLÉTÉE à 10%
+
+| Module ORIGIN | Features | Implémentées | Partielles | Manquantes |
+|---|---|---|---|---|
+| Notifications (F551-F570) | 20 | 6 | 4 | 10 |
+| Security Advanced (F571-F585) | 15 | 8 | 4 | 3 |
+| Developer API (F586-F600) | 15 | 5 | 4 | 6 |
+| UI/UX (F436-F455) | 20 | 6 | 6 | 8 |
+| **Total P6** | **70** | **25** | **18** | **27** |
+
+**Note** : Certaines features P6 ont été implémentées en avance (security headers, rate limiting, API keys, notifications basiques, thèmes light/dark).
+
+### Phase 7 : Scale & Enterprise (3 mois, 90 features) — COMPLÉTÉE à 5%
+
+| Module ORIGIN | Features | Implémentées | Partielles | Manquantes |
+|---|---|---|---|---|
+| Cloud Storage (F331-F350) | 20 | 6 | 6 | 8 |
+| Administration (F411-F435) | 25 | 8 | 6 | 11 |
+| External Integrations (F501-F520) | 20 | 4 (OAuth) | 2 | 14 |
+| Native Apps (F521-F535) | 15 | 1 (PWA) | 0 | 14 |
+| Scaling infra | 10 | 2 (K8s manifests) | 2 | 6 |
+| **Total P7** | **90** | **21** | **16** | **53** |
+
+### Phase 8 : Innovation & IA (4 mois, 80 features) — COMPLÉTÉE à 0%
+
+| Module ORIGIN | Features | Implémentées | Partielles | Manquantes |
+|---|---|---|---|---|
+| AI Avancé | 30 | 0 | 0 | 30 |
+| Web3/Blockchain (F491-F500) | 30 | 0 | 0 | 30 |
+| VR/AR Experimental | 20 | 0 | 0 | 20 |
+| **Total P8** | **80** | **0** | **0** | **80** |
+
+### Synthèse Phases
+
+| Phase | Prévu | Implémenté | Partiel | Manquant | % Complet |
+|---|---|---|---|---|---|
+| P0 | 0 (stab) | — | — | — | 85% |
+| P1 | 50 | 43 | 4 | 3 | 90% |
+| P2 | 60 | 34 | 13 | 13 | 68% |
+| P3 | 80 | 40 | 18 | 22 | 61% |
+| P4 | 90 | 10 | 14 | 66 | 19% |
+| P5 | 80 | 8 | 16 | 56 | 15% |
+| P6 | 70 | 25 | 18 | 27 | 49% |
+| P7 | 90 | 21 | 16 | 53 | 32% |
+| P8 | 80 | 0 | 0 | 80 | 0% |
+| **TOTAL** | **600** | **181** | **99** | **320** | **38%** |
+
+---
+
+## 3. ANALYSE DES ÉCARTS PAR MODULE (F001-F600)
+
+### M01 : Auth & Security (F001-F030)
+
+| ID | Feature | Statut | Preuve / Fichier |
+|---|---|---|---|
+| F001 | Register email/password | ✅ | `core/auth/handler.go`, `RegisterForm.tsx` |
+| F002 | Email verification | ✅ | `core/auth/handler.go` (VerifyEmail), `VerifyEmailPage.tsx` |
+| F003 | Login email/password | ✅ | `handlers/auth.go` (Login), `LoginPage.tsx` |
+| F004 | OAuth Google | ✅ | `services/oauth_service.go`, `oauth_handlers.go` |
+| F005 | OAuth GitHub | ✅ | `services/oauth_service.go`, test integration |
+| F006 | OAuth Discord | ✅ | `services/oauth_service.go` |
+| F007 | OAuth Spotify | ✅ | `services/oauth_service.go` |
+| F008 | Remember Me | ✅ | `handlers/auth.go` (rememberMe), `LoginForm.tsx` |
+| F009 | Logout | ✅ | `core/auth/handler.go` (Logout), `useLogout.ts` |
+| F010 | Logout all | ✅ | `handlers/session.go` (LogoutAll) |
+| F011 | Password reset request | ✅ | `password_reset_handler.go`, `ForgotPasswordForm.tsx` |
+| F012 | Password reset confirm | ✅ | `password_reset_handler.go`, `ResetPasswordPage.tsx` |
+| F013 | Change password | ✅ | `api/user/handler.go` (ChangePassword) |
+| F014 | Password history | ❌ | Uniquement dans ORIGIN schema, pas de table en migration |
+| F015 | Password strength | ✅ | `validators/password_validator.go`, `PasswordStrengthIndicator.tsx` |
+| F016 | 2FA TOTP setup | ✅ | `services/two_factor_service.go`, `2fa-service.ts` |
+| F017 | 2FA verify | ✅ | `TwoFactorVerify.tsx`, POST `/auth/login/2fa` |
+| F018 | 2FA backup codes | ✅ | `two_factor_service.go` (RecoveryCodes) |
+| F019 | 2FA SMS | ⚠️ | UI existe (`TwoFactorSetupStep2.tsx`), `handleSmsUnavailable` → "not yet available" |
+| F020 | Passkeys/WebAuthn | ⚠️ | `PasskeyModal.tsx` (UI only, simule API), pas de backend |
+| F021 | Session management | ✅ | `handlers/session.go`, `SessionsPage.tsx` |
+| F022 | Login notification | ❌ | Non implémenté |
+| F023 | Geolocation | ⚠️ | `ip_address` stocké dans sessions, pas de geo-lookup |
+| F024 | Login history | ⚠️ | `LoginHistory.tsx` existe, route backend planifiée (V0_903) |
+| F025 | IP whitelisting | ❌ | Non implémenté (whitelist CORS/OAuth uniquement) |
+| F026 | Rate limiting login | ✅ | `endpoint_limiter.go` (LoginRateLimit) |
+| F027 | CAPTCHA | ❌ | Planifié V0_903, pas d'implémentation |
+| F028 | Bruteforce detection | ⚠️ | Via rate limiting + lockout, pas de service dédié |
+| F029 | Account lockout | ✅ | `account_lockout_service.go` |
+| F030 | Security questions | ❌ | Non implémenté |
+
+**Score : 22/30 (73%) — 4 partielles, 5 manquantes**
+
+### M02 : Profils (F031-F065)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F031 | Create/edit profile | ✅ | `profile_handler.go`, `ProfileForm.tsx` |
+| F032 | Avatar upload | ✅ | `avatar_handler.go`, `avatarService.ts` |
+| F033 | Banner upload | ✅ | `user.go` (BannerURL), `EditProfileImagesCard.tsx` |
+| F034 | Username | ✅ | `useUsernameAvailability.ts`, check-username endpoint |
+| F035 | Bio | ✅ | `user.go` (Bio), `ProfileIdentity.tsx` |
+| F036 | Location | ✅ | `user.go`, `ProfileIdentity.tsx` |
+| F037 | Birth date | ✅ | `profile_handler.go`, `useEditProfile.ts` |
+| F038 | Gender | ✅ | `profile_handler.go`, `useEditProfile.ts` |
+| F039 | Language preference | ✅ | `api/user/types.go` (Language), `ui.ts` (setLanguage) |
+| F040 | Timezone | ✅ | `api/user/types.go` (Timezone), `settingsSchema.ts` |
+| F041 | Custom profile URL | ✅ | `/u/:username` route, `UserProfilePage.tsx` |
+| F042 | Public/private profile | ✅ | `ProfileVisibility`, `ProfileVisibilityCard.tsx` |
+| F043 | Public contact email | ⚠️ | Pas de champ `contact_email` dédié |
+| F044 | Social links | ✅ | `user.go` (SocialLinks), `ProfileSocialLinks.tsx` |
+| F045 | Badges/achievements | ⚠️ | `RoleBadge` pour rôles, pas de système gamification complet |
+| F046 | Role User | ✅ | `models/role.go`, `rbac_service.go` |
+| F047 | Role Artist/Creator | ✅ | Idem |
+| F048 | Role Producer | ✅ | Idem |
+| F049 | Role Label | ✅ | Idem |
+| F050 | Role Formateur | ✅ | Idem |
+| F051 | Role Moderator | ✅ | Idem |
+| F052 | Role Admin | ✅ | Idem |
+| F053 | Granular permissions | ✅ | `rbac_service.go`, tables `permissions`, `role_permissions` |
+| F054 | Verified badge | ✅ | `user.go` (IsVerified), `EmailVerificationBadge.tsx` |
+| F055 | KYC | ❌ | Non implémenté |
+| F056 | Change email | ✅ | `ChangeEmailModal.tsx` |
+| F057 | Change username | ✅ | `ChangeUsernameModal.tsx`, `CanChangeUsername` |
+| F058 | Change language | ✅ | `ui.ts` (setLanguage), `PreferenceSettings.tsx` |
+| F059 | Theme light/dark | ✅ | `ThemeProvider.tsx`, `ui.ts` (theme) |
+| F060-062 | Notification preferences | ✅ | `notification_handlers.go`, `PushPreferencesSection.tsx` |
+| F063 | Privacy preferences | ✅ | `PrivacySettings.tsx`, `settings_handler.go` |
+| F064 | Profile visibility | ✅ | `ProfileVisibilityCard.tsx` |
+| F065 | Delete account GDPR | ✅ | `account_deletion_handler.go`, `DeleteAccountView.tsx` |
+
+**Score : 31/35 (89%) — 2 partielles, 1 manquante (KYC)**
+
+### M03 : File Management (F066-F105)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F066 | Single file upload | ✅ | `uploadService.ts` (chunked), `upload.go` |
+| F067 | Batch upload | ✅ | `BatchUpload()`, `BatchUploader.tsx` |
+| F068 | Drag & drop | ✅ | `react-dropzone`, `FileUploadZone.tsx` |
+| F069 | URL import | ❌ | Non implémenté |
+| F070 | Cloud import (Dropbox/Drive) | ⚠️ | UI dans `IntegrationsView.tsx`, pas de backend |
+| F071 | Progress bar | ✅ | `UploadModalProgress`, `FilePreviewCard.tsx` |
+| F072 | Pause/resume upload | ⚠️ | Chunked upload backend (`track_chunk_service.go`), pas de resume UI |
+| F073 | File size validation | ✅ | `MAX_FILE_SIZE` 100MB, `ValidateFileSize` |
+| F074 | MIME validation | ✅ | `AllowedMimeTypes`, magic bytes validation |
+| F075 | Antivirus scan | ⚠️ | ClamAV configuré mais désactivé par défaut |
+| F076 | Image compression | ⚠️ | Avatar resize via `image_service.go`, pas de compression générique |
+| F077 | Audio transcoding | ✅ | `audio_transcode_service.go`, FFmpeg pipeline |
+| F078 | Thumbnail generation | ✅ | `thumbnail_job.go` |
+| F079 | Metadata extraction | ✅ | `metadata_service.go` |
+| F080 | Watermarking | ⚠️ | `WatermarkSettingsModal.tsx` UI, pas de backend audio watermark |
+| F081-F090 | Formats (MP3/WAV/FLAC/OGG/AIFF/M4A/ZIP/RAR/PDF/VST) | ⚠️ | Audio : MP3/WAV/FLAC/OGG/M4A/AAC/AIFF ✅ — RAR/PDF/VST ❌ |
+| F091-F105 | Track metadata fields | ⚠️ | title, artist, album, genre, BPM, key, duration, tags, cover ✅ — label, ISRC, copyright, lyrics, suggested tags ❌ |
+
+**Score : 11/40 plein, 9 partiels (50% complet)**
+
+### M04 : Audio Streaming (F106-F150)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F106-F110 | Play/pause/next/prev/seek | ✅ | `playerStore.ts` |
+| F111-F115 | Volume/mute/shuffle/repeat/speed | ✅ | `playerStore.ts` |
+| F116 | Crossfade | ✅ | `crossfadeSeconds` dans playerStore |
+| F117 | Gapless playback | ❌ | Non implémenté |
+| F118 | Waveform | ✅ | `WaveformDisplay.tsx`, `WaveformVisualizer.tsx` |
+| F119 | Spectrogram | ⚠️ | Mode "spectrogram" dans `VisualizerSettingsModal.tsx` |
+| F120 | Equalizer | ❌ | Non implémenté |
+| F121 | Mini-player | ✅ | `MiniPlayer.tsx` |
+| F122 | Picture-in-Picture | ⚠️ | Référence dans `PlayerBarRight`, pas d'implémentation complète |
+| F123 | Keyboard shortcuts | ✅ | `useMediaSession.ts` + raccourcis clavier |
+| F124 | Media Session API | ✅ | `useMediaSession.ts` |
+| F125 | Chromecast/AirPlay | ❌ | Non implémenté |
+| F126-F135 | Queue management | ✅ | addToQueue, removeFromQueue, reorderQueue, QueuePanel |
+| F136-F145 | Playlists CRUD | ✅ | API complète, `SharePlaylistModal`, `CollaboratorManagement` |
+| F146-F148 | Smart playlists, merge, export | ❌ | Non implémenté |
+| F149-F150 | Playlist import/share | ⚠️ | Share ✅, import limité (fichier uniquement) |
+
+**Score : 28/45 (62%) — 4 partiels, 7 manquants**
+
+### M05 : Chat (F151-F185)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F151 | DM 1-to-1 | ✅ | `chat_repository.go` GetDirectMessageRoom |
+| F152-F154 | Rooms public/private/group | ✅ | `room_type` varchar(50) |
+| F155 | Text messages | ✅ | `CreateMessage` |
+| F156 | Emoji | ❌ | Non vérifié dans chat |
+| F157 | Reactions | ❌ | Non implémenté |
+| F158 | Edit message | ✅ | `is_edited` flag |
+| F159 | Delete message | ✅ | `is_deleted` flag |
+| F160 | Threads | ⚠️ | `parent_id` existe, pas d'UI thread |
+| F161 | Mentions | ❌ | Non implémenté |
+| F162 | Markdown | ❌ | Non implémenté |
+| F163 | Image sharing | ❌ | Non implémenté dans chat |
+| F164 | GIFs | ❌ | Non implémenté |
+| F165 | Audio share | ❌ | Non implémenté |
+| F166-F170 | Search, filters, pin, bookmarks, notifs | ⚠️ | `is_pinned` ✅, push_message pref ✅, reste ❌ |
+| F171-F175 | Push, sound, badge, typing, read receipts | ❌ | Non implémenté |
+| F176-F180 | Online/offline, busy, custom status, AFK, last seen | ⚠️ | `PresenceBadge.tsx`, basique |
+| F181-F185 | Room users, invisible, presence notif, listening, rich | ❌ | Non implémenté |
+
+**Score : 8/35 (23%) — 4 partiels, 17 manquants**
+
+### M06 : Social (F186-F225)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F186-F188 | Follow/unfollow/followers list | ✅ | `profileService.ts`, `profileHandler` |
+| F189 | Following list | ✅ | Idem |
+| F190 | Block user | ✅ | `BlockUser`, `UnblockUser` |
+| F191 | Report user | ⚠️ | `ReportHandler` existe, flow incomplet |
+| F192 | Recommendations | ❌ | Non implémenté |
+| F193-F195 | Suggestions, collaboration request, referral | ❌ | Non implémenté |
+| F196 | Share profile | ⚠️ | URL `/u/:username` partageable |
+| F197 | QR code | ❌ | Non implémenté |
+| F198 | New follower notification | ⚠️ | Notification service existe, feature non confirmée |
+| F199 | Close friends | ❌ | Non implémenté |
+| F200 | Artist subscription | ❌ | Non implémenté |
+| F201-F210 | Posts (text/image/audio/video, like, comment, repost, quote, pin) | ⚠️ | `CreatePostModal`, `PostCard`, `ExploreView` — partiellement mocké |
+| F211-F215 | Delete/edit/private post, hashtags, trending | ⚠️ | UI existe, backend partiel |
+| F216-F225 | Groups (create, join, leave, invite, roles, forum, events, shared files, stats) | ⚠️ | `CreateGroupModal`, groupe cover — reste non implémenté |
+
+**Score : 6/40 (15%) — 8 partiels, 16 manquants**
+
+### M07 : Marketplace (F226-F275)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F226-F235 | Products CRUD, upload, preview, images, description, pricing | ✅ | `productService.ts`, `CreateProductView*` |
+| F236-F240 | Categories, tags, BPM/key metadata, genre, formats | ✅ | Product model avec metadata complète |
+| F241-F243 | Licences streaming/personal/commercial | ✅ | `CreateProductViewPricingCard` |
+| F244-F246 | Licence exclusive/lease/unlimited | ⚠️ | Exclusive ✅, lease/unlimited ❌ |
+| F247-F250 | Terms, auto contract, e-signature, licence history | ❌ | Non implémenté |
+| F251-F255 | Cart, multi-product, wishlist, taxes, promo codes | ⚠️ | Cart ✅, multi-product ✅, wishlist ⚠️, taxes/promos ❌ |
+| F256-F260 | Checkout, card, PayPal, crypto, invoice | ⚠️ | Hyperswitch checkout ✅, PayPal/crypto ❌ |
+| F261-F265 | Purchase history, re-download, refund, dispute, support | ⚠️ | Purchase history ✅, reste partiel |
+| F266-F270 | Seller dashboard, stats, revenue, charts, top products | ✅ | `SellerDashboardView`, `commerceService` stats |
+| F271-F275 | Conversion, reviews, replies, promotions, payout | ⚠️ | Reviews ✅, Stripe Connect payout ✅, promotions ❌ |
+
+**Score : 22/50 (44%) — 10 partiels, 8 manquants**
+
+### M08 : Education (F276-F305)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F276-F290 | Courses, lessons, quizzes, certificates, enrollment | ⚠️ | Backend schema + handlers dans `core/education/` — tests skippés, pas de frontend |
+| F291-F305 | Advanced education (paths, subscriptions, instructors) | ❌ | Non implémenté |
+
+**Score : 0/30 plein, 6 partiels (backend only) — Module effectivement NON LIVRÉ**
+
+### M09 : Hardware/Gear (F306-F330)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F306-F315 | Gear CRUD, images, documents, repairs, warranty | ✅ | `gear_handler.go`, `GearItem`, `GearRepair`, `GearDocument`, `GearImage` |
+| F316-F320 | Warranty notifications, maintenance history | ✅ | `gear_warranty_notifier`, inventory pages frontend |
+| F321-F325 | Lending, insurance, comparison | ❌ | Non implémenté |
+| F326-F330 | Marketplace integration, wish list gear | ❌ | Non implémenté |
+
+**Score : 12/25 (48%) — 2 partiels, 5 manquants**
+
+### M10 : Cloud Storage (F331-F350)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F331-F340 | Folders, files, upload, quota, versioning, restore, share | ✅ | `cloud_handler.go`, `CloudPage`, `CloudFileVersions` |
+| F341-F345 | Backup worker, integration view | ✅ | Cloud backup worker, `CloudIntegrationView` |
+| F346-F350 | Nextcloud sync, external cloud, collaborative edit | ❌ | Non implémenté |
+
+**Score : 8/20 (40%) — 4 partiels**
+
+### M11 : Search (F351-F380)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F351-F355 | Fulltext search, filters (genre, BPM, key) | ✅ | `FullTextSearchService`, PostgreSQL tsvector, `TrackSearchService` |
+| F356-F360 | Sort, autocomplete, suggestions | ✅ | Relevance, popularity, `SearchService.Suggestions` |
+| F361-F370 | Phonetic, spelling correction, semantic, audio similarity | ❌ | Non implémenté (nécessite Elasticsearch) |
+| F371-F380 | Search courses, groups, advanced filters | ❌ | Non implémenté |
+
+**Score : 10/30 (33%) — Limité à PostgreSQL pg_trgm, pas d'Elasticsearch**
+
+### M12 : Analytics (F381-F410)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F381-F390 | Playback analytics, heatmap | ✅ | `PlaybackAnalyticsService`, `PlaybackHeatmapService` |
+| F391-F395 | Creator dashboard (stats, trends) | ⚠️ | Track stats + plays over time ✅, demographics/devices ❌ |
+| F396-F400 | Seller analytics | ⚠️ | `SellerTransfer`, basique |
+| F401-F410 | Admin analytics (DAU/MAU, retention, infra) | ⚠️ | `AdminContentAnalytics`, `GetDashboardStats` — basique |
+
+**Score : 4/30 plein, 8 partiels (40% avec partiels)**
+
+### M13 : Administration (F411-F435)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F411-F415 | User management (search, filters, pagination) | ✅ | `GetUsers` avec search/filters |
+| F416-F420 | Ban, suspend, reset password, role change | ⚠️ | `BanUserModal`, admin role checks — flow incomplet |
+| F421-F425 | Moderation queue, content moderation | ⚠️ | `ReportHandler`, `ReportService` — queue UI manquante |
+| F426-F430 | Copyright strikes, appeal system | ❌ | Non implémenté |
+| F431-F435 | Feature flags, announcements, maintenance | ✅ | Feature flags, maintenance middleware, announcements |
+
+**Score : 12/25 (48%) — 6 partiels, 3 manquants**
+
+### M14 : UI/UX (F436-F455)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F436-F438 | Light/dark/system theme | ✅ | `ThemeProvider`, `ui.ts` |
+| F439-F441 | High contrast, compact/comfortable, accent hue | ✅ | `AppearanceSettingsView` |
+| F442-F445 | Font size, custom palette, drag-drop layouts | ⚠️ | Font size ✅, reste ❌ |
+| F446-F450 | Keyboard nav, screen reader, ARIA, focus visible, WCAG | ⚠️ | `contrast.ts`, `aria-*`, `focus-visible`, `useReducedMotion` — partiel |
+| F451-F455 | Dyslexia font, video transcriptions, auto subtitles | ❌ | Non implémenté |
+
+**Score : 10/20 (50%) — 4 partiels, 4 manquants**
+
+### M15 : AI (F456-F470)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F456 | AI Mastering | ❌ | Non implémenté |
+| F457 | Stem separation | ❌ | Non implémenté |
+| F458 | Genre detection | ❌ | Non implémenté |
+| F459 | BPM detection | ⚠️ | `enable_bpm_detection` dans stream server config |
+| F460 | Key detection | ❌ | Non implémenté |
+| F461 | Vocal removal | ❌ | Non implémenté |
+| F462 | Denoising | ❌ | Non implémenté |
+| F463 | Audio upscaling | ❌ | Non implémenté |
+| F464 | Auto-tags | ❌ | Non implémenté |
+| F465 | Similarity detection | ⚠️ | `TrackSimilarityMatrix` dans stream discovery |
+| F466 | Content ID | ❌ | Non implémenté |
+| F467 | ML recommendations | ⚠️ | Recommendation services basiques (non ML) |
+| F468 | Voice synthesis | ❌ | Non implémenté |
+| F469 | Auto lyrics transcription | ❌ | Non implémenté |
+| F470 | AI mixing | ❌ | Non implémenté |
+
+**Score : 0/15 plein, 3 partiels — Module NON IMPLÉMENTÉ**
+
+### M16 : Livestreaming (F471-F480)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F471 | Live DJ sets | ⚠️ | `LiveStream` model, `GoLiveView`, HLS support |
+| F472 | Live concerts | ⚠️ | Infrastructure HLS partagée |
+| F473 | Production sessions | ❌ | Non implémenté |
+| F474 | Multi-camera | ❌ | Non implémenté |
+| F475 | Live chat | ❌ | Pas de chat live dédié |
+| F476 | Donations/tips | ⚠️ | `TipStreamerModal` (UI) |
+| F477 | VOD replay | ⚠️ | HLS VOD support dans stream server |
+| F478 | Clipping | ❌ | Non implémenté |
+| F479 | Scheduling | ❌ | Non implémenté |
+| F480 | Viewer analytics | ❌ | Non implémenté |
+
+**Score : 0/10 plein, 4 partiels — Module BASIQUE**
+
+### M17 : Collaboration (F481-F490)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F481 | DAW collaboration | ❌ | Non implémenté |
+| F482 | Version control audio | ❌ | Non implémenté |
+| F483 | Temporal comments | ❌ | Non implémenté |
+| F484 | Stems sharing | ❌ | Non implémenté |
+| F485 | Co-edit playlists | ✅ | `CollaboratorManagement`, read/write/admin |
+| F486 | Whiteboard | ❌ | Non implémenté |
+| F487 | Video chat | ❌ | Non implémenté |
+| F488 | Screen sharing | ❌ | Non implémenté |
+| F489 | Project templates | ❌ | Non implémenté |
+| F490 | Collaboration workflow | ❌ | Non implémenté |
+
+**Score : 1/10 (10%) — Uniquement playlist collaboration**
+
+### M18 : Web3 (F491-F500)
+
+**Score : 0/10 (0%) — Aucune feature Web3 implémentée**
+
+(NFT, blockchain, smart contracts, tokens, staking, DAO, IPFS, wallet : tout manquant)
+
+### M19 : External Integrations (F501-F520)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F501-F504 | OAuth integrations | ✅ | Google, GitHub, Discord, Spotify |
+| F505-F510 | Social links | ✅ | Profile social links (YouTube, Instagram, Twitter, etc.) |
+| F511-F520 | DAW plugins, SoundCloud import, DistroKid, Zapier | ❌ | Non implémenté |
+
+**Score : 4/20 (20%) — OAuth uniquement**
+
+### M20 : Native Apps (F521-F535)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F521 | PWA | ✅ | `usePWA` hook |
+| F522-F535 | iOS, Android, React Native, Tauri, Electron | ❌ | Abandonné (voir `V1_LIMITATIONS.md`) |
+
+**Score : 1/15 (7%) — PWA uniquement, apps natives abandonnées**
+
+### M21 : Gamification (F536-F550)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F536-F540 | XP, levels, achievements | ⚠️ | `ProfileXPView`, `AchievementCard` (frontend, issues TS) |
+| F541-F550 | Challenges, leaderboards, rewards, etc. | ❌ | Backend API gamification absent |
+
+**Score : 0/15 plein, 2 partiels — Supprimé du scope v0.971**
+
+### M22 : Notifications (F551-F570)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F551-F555 | Real-time, badge counter, center, mark read | ✅ | `NotificationService`, `NotificationMenu`, `NotificationBell` |
+| F556-F560 | Filters, grouping, persistent, quick actions, history | ⚠️ | Filtres par type ✅, reste partiel |
+| F561-F570 | Email templates (welcome, confirmation, reset, etc.) | ⚠️ | Password reset, verification ✅ — welcome, follower, purchase, newsletter ❌ |
+
+**Score : 6/20 (30%) — 4 partiels, email templates incomplets**
+
+### M23 : Security Advanced (F571-F585)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F571-F573 | Rate limiting global, per-endpoint, DDoS | ✅ | `endpoint_limiter.go`, rate limiting global |
+| F574-F576 | SQL injection, XSS, CSRF protection | ✅ | GORM params, DOMPurify, CSRF middleware |
+| F577-F579 | Clickjacking, CSP, HSTS | ⚠️ | HSTS ✅, X-Frame-Options ✅, CSP avec `unsafe-inline` |
+| F580-F582 | Security headers, audit logs, GDPR | ✅ | Headers complets, audit logs, `data_export_service` |
+| F583-F585 | CCPA, SOC2, data export | ⚠️ | GDPR export ✅, CCPA/SOC2 ❌ |
+
+**Score : 10/15 (67%) — 2 partiels (CSP, compliance)**
+
+### M24 : Developer API (F586-F600)
+
+| ID | Feature | Statut | Preuve |
+|---|---|---|---|
+| F586-F588 | REST API, API keys, webhooks | ✅ | `APIKeyService`, webhooks (register, list, test, stats) |
+| F589 | OpenAPI/Swagger | ✅ | Documentation Swagger |
+| F590-F592 | GraphQL, OAuth2 server | ❌ | Non implémenté |
+| F593-F595 | SDK JS/Python/Go | ❌ | Non implémenté |
+| F596-F600 | Sandbox, playground, logs, analytics, dashboard | ⚠️ | `APIPlaygroundView`, `DeveloperDashboardView` — partiel |
+
+**Score : 5/15 (33%) — 4 partiels, GraphQL et SDKs manquants**
+
+### Synthèse Globale par Module
+
+| Module | Features ORIGIN | Plein | Partiel | Manquant | % Complet |
+|---|---|---|---|---|---|
+| M01 Auth | 30 | 22 | 4 | 4 | 73% |
+| M02 Profils | 35 | 31 | 2 | 2 | 89% |
+| M03 File Mgmt | 40 | 11 | 9 | 20 | 39% |
+| M04 Streaming | 45 | 28 | 4 | 13 | 67% |
+| M05 Chat | 35 | 8 | 4 | 23 | 29% |
+| M06 Social | 40 | 6 | 8 | 26 | 25% |
+| M07 Marketplace | 50 | 22 | 10 | 18 | 54% |
+| M08 Education | 30 | 0 | 6 | 24 | 10% |
+| M09 Gear | 25 | 12 | 2 | 11 | 52% |
+| M10 Cloud | 20 | 8 | 4 | 8 | 50% |
+| M11 Search | 30 | 10 | 0 | 20 | 33% |
+| M12 Analytics | 30 | 4 | 8 | 18 | 27% |
+| M13 Admin | 25 | 12 | 6 | 7 | 60% |
+| M14 UI/UX | 20 | 10 | 4 | 6 | 60% |
+| M15 AI | 15 | 0 | 3 | 12 | 10% |
+| M16 Livestream | 10 | 0 | 4 | 6 | 20% |
+| M17 Collaboration | 10 | 1 | 0 | 9 | 10% |
+| M18 Web3 | 10 | 0 | 0 | 10 | 0% |
+| M19 Integrations | 20 | 4 | 2 | 14 | 25% |
+| M20 Native Apps | 15 | 1 | 0 | 14 | 7% |
+| M21 Gamification | 15 | 0 | 2 | 13 | 7% |
+| M22 Notifications | 20 | 6 | 4 | 10 | 40% |
+| M23 Security Adv. | 15 | 10 | 2 | 3 | 73% |
+| M24 Dev API | 15 | 5 | 4 | 6 | 47% |
+| **TOTAL** | **600** | **211** | **96** | **297** | **43%** |
+
+---
+
+## 4. DÉVIATIONS ARCHITECTURALES
+
+### 4.1 Tableau des Déviations
+
+| # | Spécification ORIGIN | Réalité Actuelle | Type | Impact | Recommandation |
+|---|---|---|---|---|---|
+| **D01** | **Chat Server Rust** (`veza-chat-server`) — service Rust dédié avec Axum/SQLx pour WebSocket | Migré dans le backend Go en v0.502 (ADR-002). Chat via WebSocket Go. Code Rust orphelin dans `/veza-chat-server/` | Pivot majeur | **Positif** — réduit la complexité opérationnelle, 1 service en moins à déployer/maintenir | ✅ **Garder** la décision. Supprimer le code orphelin Rust du monorepo |
+| **D02** | **Traefik** comme API Gateway avec service discovery, load balancing, TLS automatique | **HAProxy** comme reverse proxy avec blue-green deployments | Substitution | **Neutre** — HAProxy est production-grade, gère le blue-green | ⚠️ **Acceptable** pour l'échelle actuelle. Migrer vers Traefik/Envoy si >10K users pour le service discovery |
+| **D03** | **Elasticsearch** pour search avec fulltext, phonétique, facettes, autocomplete | **PostgreSQL** pg_trgm + tsvector/tsquery | Simplification | **Négatif à terme** — ne scalera pas au-delà de ~10K tracks pour la recherche phonétique/sémantique | ❌ **Ajouter Elasticsearch** quand le volume de données le justifie (>50K tracks). Critique pour Phase 5 |
+| **D04** | **gRPC** pour communication inter-services (Go ↔ Rust) | **REST/HTTP** entre Go API et Rust stream server | Simplification | **Neutre** — REST plus simple à debug, suffisant pour le traffic actuel. gRPC nécessaire si latency inter-service critique | ⚠️ **Acceptable**. Migrer vers gRPC uniquement si bottleneck mesuré |
+| **D05** | **JWT RS256** (asymétrique) pour multi-service JWT validation | **JWT HS256** (symétrique) partagé entre Go et Rust | Risque sécurité | **Négatif** — HS256 nécessite le secret partagé sur tous les services. RS256 permet validation sans partager le secret privé | ❌ **Migrer vers RS256** avant production multi-instance. Effort : ~2 jours |
+| **D06** | **CQRS** (Command Query Responsibility Segregation) | Pattern requête-réponse traditionnel (Handler→Service→Repository) | Simplification | **Neutre** — CQRS apporte de la complexité sans bénéfice clair à cette échelle | ✅ **Garder** le pattern actuel. CQRS uniquement si read/write loads divergent significativement |
+| **D07** | **Stripe** comme payment processor unique | **Hyperswitch** (payment router open-source) qui supporte Stripe comme backend | Pivot stratégique | **Positif** — Hyperswitch offre plus de flexibilité (multi-provider), open-source, réduction de vendor lock-in | ✅ **Garder**. Avantage compétitif — permet d'ajouter PayPal, crypto sans changer l'architecture |
+| **D08** | **Electron** desktop app (Phase 7) | Non développé | Retard planifié | **Neutre** — Phase 7 feature, pas urgente | ⚠️ **Reporter**. Considérer Tauri (plus léger que Electron) quand nécessaire |
+| **D09** | **React Native** mobile app (Phase 4-7) | Non développé. PWA uniquement (`usePWA` hook) | Fonctionalité manquante | **Négatif** — PWA limité (pas d'accès App Store, audio background limité sur iOS) | ❌ **Décider** : PWA-first ou app native ? Si market B2C audio, app native quasi-obligatoire |
+| **D10** | **Ansible** pour déploiement automatisé | **Incus/LXD** + Docker Compose, scripts bash | Substitution | **Neutre** — fonctionnel pour 1-2 serveurs. Ansible nécessaire si >3 serveurs | ⚠️ **Acceptable** court terme. Automatiser avec Ansible/Terraform avant Phase 7 |
+| **D11** | **pgBouncer** pour connection pooling PostgreSQL | **GORM built-in** connection pooling (MaxOpenConns, MaxIdleConns) | Simplification | **Négatif à terme** — GORM pooling suffisant pour <100 connexions. pgBouncer nécessaire pour >500 connexions | ⚠️ **Acceptable** jusqu'à 5K users. Ajouter pgBouncer avant scaling Phase 7 |
+| **D12** | **Kafka** (optionnel dans ORIGIN) pour event streaming | **RabbitMQ** uniquement | Conforme | **Neutre** — ORIGIN listait Kafka comme optionnel. RabbitMQ couvre les besoins actuels | ✅ **Garder** RabbitMQ. Kafka uniquement si besoin de replay/event sourcing à grande échelle |
+| **D13** | **Argon2id** pour hashing passwords (Rust services) | **bcrypt** côté Go, Argon2 référencé dans ORIGIN mais pas implémenté | Déviation mineure | **Neutre** — bcrypt avec cost 12 est acceptable. Argon2id est le standard actuel mais bcrypt reste sûr | ⚠️ **Acceptable**. Migrer vers Argon2id lors d'une refonte auth si opportunité |
+| **D14** | **HashiCorp Vault** pour secrets management | **Variables d'environnement** + fichiers `.env` | Risque opérationnel | **Négatif** — .env en dev acceptable, mais production nécessite un secret manager | ❌ **Ajouter** un secret manager avant production (Vault, AWS Secrets Manager, ou Infisical) |
+| **D15** | **Redis Cluster** pour haute disponibilité | **Redis standalone** | Simplification | **Neutre** — suffisant pour <10K users. Cluster nécessaire pour HA | ⚠️ **Acceptable** jusqu'à Phase 7. Prévoir Redis Sentinel ou Cluster avant |
+
+### 4.2 Bilan des Déviations
+
+| Catégorie | Nombre | Impact Global |
+|---|---|---|
+| ✅ Déviations positives (garder) | 4 | Simplification bienvenue |
+| ⚠️ Déviations acceptables (court terme) | 6 | À adresser avant scaling |
+| ❌ Déviations à corriger | 5 | Blocantes pour les objectifs ORIGIN |
+
+### 4.3 Déviations Critiques à Corriger en Priorité
+
+1. **D05 - JWT RS256** : migration HS256→RS256 avant déploiement multi-instance (~2j)
+2. **D14 - Secrets Manager** : Vault ou équivalent avant production (~3j)
+3. **D03 - Elasticsearch** : nécessaire pour les objectifs Phase 5 search (~2 semaines)
+4. **D09 - Mobile App** : décision stratégique PWA vs native requise
+5. **D11 - pgBouncer** : avant scaling au-delà de 5K users (~1j)
+
+---
+
+## 5. MÉTRIQUES DE QUALITÉ : ORIGIN vs ACTUEL
+
+### 5.1 Code Quality Metrics
+
+| Métrique | Objectif ORIGIN | État Actuel | Zone | Écart |
+|---|---|---|---|---|
+| **Test Coverage Global** | ≥ 80% (🟢), objectif 90% | ~50% frontend (vitest threshold), Go non mesuré en CI | 🔴 | -30% minimum |
+| **Test Coverage Go** | ≥ 80% | 306 fichiers test, pas de coverage % enforced | 🟡 | Non mesuré |
+| **Test Coverage Rust** | ≥ 80% | Pas de CI coverage pour stream server | 🔴 | Non mesuré |
+| **Test Coverage Frontend** | ≥ 80% | Threshold 50% vitest, stories Storybook pour composants | 🔴 | ~-30% |
+| **Complexité cyclomatique** | < 10 par fonction | Non mesuré (pas de gocyclo/SonarQube configuré) | ❓ | Non mesuré |
+| **Duplication code** | < 3% | Non mesuré (pas de jscpd/SonarQube) | ❓ | Non mesuré |
+| **TODO/FIXME/HACK** | < 50 | ~150+ TODO, ~30 FIXME, ~5 HACK | 🔴 | +100 TODOs au-dessus du seuil |
+| **Linter errors** | 0 errors, < 5 warnings | ESLint configuré, golangci-lint en CI | 🟡 | Partiellement conforme |
+| **Code churn** | < 5 changes/semaine/fichier | Non mesuré | ❓ | Non mesuré |
+
+### 5.2 Performance Metrics
+
+| Métrique | Objectif ORIGIN | État Actuel | Zone | Écart |
+|---|---|---|---|---|
+| **API Latency p95** | < 100ms | Non mesuré en production (pas de Prometheus actif) | ❓ | Non mesurable |
+| **API Latency p99** | < 200ms | Idem | ❓ | Non mesurable |
+| **DB Query p95** | < 10ms | Non mesuré (pas de pg_stat_statements) | ❓ | Non mesurable |
+| **Frontend FCP** | < 1.5s | Non mesuré (pas de Lighthouse CI) | ❓ | Non mesurable |
+| **Frontend TTI** | < 3.5s | Non mesuré | ❓ | Non mesurable |
+| **Lighthouse Performance** | ≥ 95 | Non mesuré | ❓ | Non mesurable |
+| **Lighthouse Accessibility** | ≥ 100 | Non mesuré | ❓ | Non mesurable |
+| **Bundle JS initial (gzip)** | < 200 KB | Non mesuré (Vite build, code splitting actif) | ❓ | Non mesurable |
+| **Audio stream start** | < 500ms | Non mesuré | ❓ | Non mesurable |
+| **Rebuffering rate** | < 0.5% | Non mesuré | ❓ | Non mesurable |
+| **Throughput** | 10K req/s | Non testé (k6 load tests existent mais pas de baseline) | ❓ | Non mesurable |
+| **Uptime** | 99.9% | Non mesuré (pre-launch) | ❓ | N/A |
+
+**Constat critique** : **Aucune métrique de performance n'est mesurée en continu**. Les configs Prometheus/Grafana existent dans docker-compose mais ne sont pas activement utilisées pour du monitoring de production. Les k6 load tests existent mais n'ont pas produit de baseline documentée.
+
+### 5.3 Security Metrics
+
+| Métrique | Objectif ORIGIN | État Actuel | Zone | Écart |
+|---|---|---|---|---|
+| **Vulnérabilités critiques** | 0 | 2 (VEZA-SEC-001: JWT default Rust, VEZA-SEC-002: JWT mismatch) | 🔴 | -2 |
+| **Vulnérabilités hautes** | 0 | 1 (VEZA-SEC-003: admin credentials hardcodées dans tests) | 🟡 | -1 |
+| **Password hashing** | bcrypt cost ≥ 12 ou Argon2id | bcrypt cost 12 ✅ | 🟢 | Conforme |
+| **JWT expiration access** | 15 min | 15 min configuré ✅ | 🟢 | Conforme |
+| **JWT expiration refresh** | 7 jours | 7 jours configuré ✅ | 🟢 | Conforme |
+| **MFA admin/moderator** | Obligatoire | Disponible mais pas obligatoire | 🟡 | Non enforced |
+| **Rate limiting** | Tous endpoints publics | Login ✅, global ✅, per-endpoint ✅, DDoS ❌ | 🟡 | WAF absent |
+| **Input validation serveur** | Obligatoire | Go binding tags ✅, validation service ✅ | 🟢 | Conforme |
+| **Security headers** | CSP, HSTS, X-Frame-Options, etc. | HSTS ✅, X-Frame-Options ✅, CSP ⚠️ (unsafe-inline) | 🟡 | CSP à durcir |
+| **Secrets dans code** | Jamais | JWT default "veza-stream-jwt-secret" dans config Rust | 🔴 | Violation |
+| **Audit logs** | Actions sensibles | `audit_log` table, `AuditLog` handler | 🟢 | Conforme |
+| **GDPR right to erasure** | Obligatoire | `account_deletion_handler.go`, `data_export_service` | 🟢 | Conforme |
+| **Dependency scanning** | Daily (npm audit, cargo audit, govulncheck) | CI workflows incluent audit | 🟢 | Conforme |
+| **Penetration testing** | Trimestriel + après major releases | Non réalisé | 🔴 | Non conforme |
+| **Bug bounty** | HackerOne ou Bugcrowd | Non mis en place | 🔴 | Non conforme |
+
+### 5.4 Quality Gates (CI/CD)
+
+| Quality Gate ORIGIN | Objectif | Implémenté ? | Détail |
+|---|---|---|---|
+| Tests pass (unit, integration) | Bloquant | ✅ | GitHub Actions run tests |
+| Coverage ≥ 80% | Bloquant | ❌ | Seuil à 50% frontend, pas enforced Go/Rust |
+| No linter errors | Bloquant | ⚠️ | ESLint en CI, golangci-lint partiel |
+| No security vulns (critical/high) | Bloquant | ⚠️ | npm audit en CI, mais 2 vulns critiques non résolues |
+| Code review 2+ reviewers | Bloquant | ❌ | Solo developer, pas de reviewers |
+| Pre-deployment smoke tests | Bloquant | ❌ | Pas de smoke tests staging |
+| Performance tests | Bloquant | ❌ | k6 existe mais pas intégré en gate |
+| SAST/DAST scan | Bloquant | ⚠️ | SAST partiel (CI), pas de DAST |
+| Rollback plan | Bloquant | ⚠️ | Blue-green via HAProxy, pas de rollback automatique |
+
+**Conformité Quality Gates : 1/9 pleinement conforme, 4/9 partiels, 4/9 non conformes**
+
+### 5.5 Bilan Qualité
+
+| Domaine | Score ORIGIN requis | Score Actuel Estimé | Écart |
+|---|---|---|---|
+| Code Quality | 8/10 | 5/10 | -3 |
+| Performance | 9/10 | Inconnu (non mesuré) | Non mesurable |
+| Security | 9/10 | 6/10 | -3 |
+| UX/Accessibility | 9/10 | 5/10 | -4 |
+| Infrastructure | 8/10 | 6/10 | -2 |
+| **Moyenne** | **8.6/10** | **5.5/10** | **-3.1** |
+
+---
+
+## 6. ROADMAP POUR ATTEINDRE LES OBJECTIFS ORIGIN
+
+### 6.1 Stratégie Recommandée : « Phase 3.5 » avant Phase 4
+
+Le projet ne peut pas sauter directement à Phase 5 pour rattraper le retard. La stratégie recommandée est de consolider ce qui existe (compléter P2-P3 à 100%), puis aborder Phase 4 avec un scope réduit et pragmatique.
+
+```
+Timeline Proposée (mars 2026 → mars 2027)
+
+Mar-Avr 2026 Mai-Jul 2026 Août-Oct 2026 Nov 2026-Mar 2027
+┌──────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐
+│ PHASE 3.5│ │ PHASE 4R │ │ PHASE 5R │ │ PHASE 6R │
+│ Consolid.│ │ Social Lite │ │ Analytics + │ │ Premium + │
+│ Sécurité │ │ + Live │ │ Search + │ │ Dev API + │
+│ Tests │ │ Streaming │ │ Notifs │ │ Scale │
+│ ~50 feat │ │ ~60 feat │ │ ~70 feat │ │ ~80 feat │
+└──────────┘ └──────────────┘ └──────────────┘ └──────────────────┘
+ 2 mois 3 mois 3 mois 5 mois
+```
+
+### 6.2 Phase 3.5 : Consolidation (Mars-Avril 2026) — 2 mois
+
+**Objectif** : Corriger les violations ORIGIN critiques, compléter les features P2-P3 manquantes, établir les métriques de qualité.
+
+#### Sprint A : Sécurité & Quality Gates (2 semaines)
+
+| Action | Effort | Priorité | Impact |
+|---|---|---|---|
+| Corriger VEZA-SEC-001 : remplacer JWT secret par défaut Rust | 0.5j | P0 | Critique |
+| Corriger VEZA-SEC-002 : aligner JWT issuer/audience Go↔Rust | 1j | P0 | Critique |
+| Migrer JWT HS256 → RS256 (D05) | 2j | P0 | Architecture |
+| Configurer coverage CI/CD : Go `go test -coverprofile` + seuil 70% | 1j | P1 | Qualité |
+| Configurer coverage CI/CD : Rust `cargo tarpaulin` + seuil 60% | 1j | P1 | Qualité |
+| Monter threshold vitest de 50% à 70% | 1j | P1 | Qualité |
+| Ajouter Lighthouse CI dans GitHub Actions | 1j | P2 | Performance |
+| Activer Prometheus metrics dans docker-compose dev | 0.5j | P2 | Monitoring |
+
+#### Sprint B : Features P2 Manquantes — Chat (2 semaines)
+
+| Action | Effort | Priorité | Impact |
+|---|---|---|---|
+| Chat reactions (emoji) | 2j | P1 | Engagement |
+| Chat mentions (@user) | 2j | P1 | UX |
+| Chat typing indicator | 1j | P2 | UX |
+| Chat read receipts | 2j | P2 | UX |
+| Chat message search | 2j | P1 | Fonctionnel |
+
+#### Sprint C : Features P3 Manquantes — Marketplace (2 semaines)
+
+| Action | Effort | Priorité | Impact |
+|---|---|---|---|
+| Education frontend (compléter le module backend existant) | 5j | P1 | Module entier |
+| Licence history/tracking | 2j | P2 | Business |
+| Purchase refund flow | 2j | P1 | Business |
+| Email templates (purchase confirmation, welcome) | 2j | P1 | UX |
+
+#### Sprint D : Debt & Cleanup (2 semaines)
+
+| Action | Effort | Priorité | Impact |
+|---|---|---|---|
+| Supprimer code mort (`veza-chat-server/`, `soundcloud/`) | 1j | P2 | Maintenabilité |
+| Convertir 50 TODOs en issues GitHub | 2j | P2 | Tracking |
+| Uniformiser error handling Go (RespondWithAppError partout) | 3j | P1 | Qualité |
+| Ajouter secret manager (Infisical ou Vault) | 2j | P0 | Sécurité |
+| Durcir CSP (supprimer unsafe-inline) | 1j | P1 | Sécurité |
+
+**Total Phase 3.5 : ~50 actions, 2 mois, 1-2 développeurs**
+
+### 6.3 Phase 4R : Social & Live Streaming (Mai-Juillet 2026) — 3 mois
+
+**Scope réduit** : pas de DAW collaboration (trop complexe), pas de Web3, pas de gamification.
+
+| Module | Features à implémenter | Effort | Priorité |
+|---|---|---|---|
+| **Social Posts** | Create/edit/delete post, like, comment, repost, hashtags, explore | 3 semaines | P1 |
+| **Groups** | Join/leave, roles, member list, group feed | 2 semaines | P1 |
+| **Live Streaming** | Go live flow, live chat intégré, donations, VOD replay | 4 semaines | P1 |
+| **Notifications push** | Web push, notification grouping, email follower/comment | 2 semaines | P1 |
+| **Chat enrichi** | GIFs (Giphy), image sharing, threads UI | 2 semaines | P2 |
+
+**Total Phase 4R : ~60 features, 3 mois, 2-3 développeurs**
+
+### 6.4 Phase 5R : Analytics & Search (Août-Octobre 2026) — 3 mois
+
+| Module | Features à implémenter | Effort | Priorité |
+|---|---|---|---|
+| **Elasticsearch** | Setup, indexation tracks/users/playlists, fulltext + phonétique | 3 semaines | P0 |
+| **Search avancé** | Filtres multi-critères, autocomplete intelligent, spelling correction | 2 semaines | P1 |
+| **Creator Dashboard** | Plays over time, demographics, device breakdown, export CSV | 3 semaines | P1 |
+| **Admin Dashboard** | DAU/MAU, retention, revenue, user growth charts | 2 semaines | P1 |
+| **Notifications email** | Templates complets : welcome, follower, purchase, sale, newsletter | 2 semaines | P2 |
+| **UI/UX** | WCAG AA compliance, keyboard nav complète, screen reader | 2 semaines | P2 |
+
+**Total Phase 5R : ~70 features, 3 mois, 2-3 développeurs**
+
+### 6.5 Phase 6R : Premium & Scale (Novembre 2026-Mars 2027) — 5 mois
+
+| Module | Features à implémenter | Effort | Priorité |
+|---|---|---|---|
+| **Premium tiers** | Free/Premium/Pro, Stripe billing, trial, upgrade/downgrade | 4 semaines | P0 |
+| **Developer API** | GraphQL, SDK JS, webhook improvements, sandbox | 3 semaines | P1 |
+| **Admin avancé** | Moderation queue UI, copyright strikes, appeal system | 3 semaines | P1 |
+| **Cloud Storage** | Nextcloud integration ou S3 sync avancé | 2 semaines | P2 |
+| **Infrastructure** | pgBouncer, Redis Sentinel, Terraform/Ansible, auto-scaling | 4 semaines | P1 |
+| **Mobile** | Décision PWA-enhanced ou React Native app | 4 semaines | P1 |
+| **BPM/Key detection** | Intégrer librosa ou essentia pour détection automatique | 2 semaines | P2 |
+
+**Total Phase 6R : ~80 features, 5 mois, 2-4 développeurs**
+
+### 6.6 Estimation Effort Total
+
+| Phase | Durée | Features | Développeurs | Effort (homme-mois) |
+|---|---|---|---|---|
+| Phase 3.5 | 2 mois | ~50 | 1-2 | 3 |
+| Phase 4R | 3 mois | ~60 | 2-3 | 7 |
+| Phase 5R | 3 mois | ~70 | 2-3 | 7 |
+| Phase 6R | 5 mois | ~80 | 2-4 | 12 |
+| **Total** | **13 mois** | **~260** | — | **~29 homme-mois** |
+
+Avec ce plan révisé, le projet atteindrait **~490 features** sur 600 d'ici mars 2027, soit **82% de complétion ORIGIN**.
+
+---
+
+## 7. RECOMMANDATIONS : GARDER, MODIFIER, OU ABANDONNER
+
+### 7.1 Objectifs ORIGIN à GARDER tels quels
+
+| Objectif | Raison |
+|---|---|
+| Auth complète (F001-F030) | Fondation critique, déjà à 73% |
+| Profils (F031-F065) | Déjà à 89%, terminer les derniers % |
+| Streaming audio (F106-F150) | Core product, déjà à 67% |
+| Marketplace (F226-F275) | Source de revenue, à 54% |
+| Security (F571-F585) | Non négociable, déjà à 73% |
+| Notifications (F551-F570) | Essentiel pour rétention |
+| Admin (F411-F435) | Nécessaire pour opérations |
+| Cloud storage (F331-F350) | Différenciateur produit |
+| Search fulltext (F351-F370) | Critique pour UX |
+| Analytics (F381-F410) | Nécessaire pour créateurs et vendeurs |
+| Developer API (F586-F600) | Permet écosystème |
+| UI/UX accessibilité (F436-F455) | Obligation légale (WCAG), différenciateur |
+| CI/CD + Quality Gates | Fondation technique non négociable |
+| Test coverage 80% | Objectif réaliste, protège contre régressions |
+
+### 7.2 Objectifs ORIGIN à MODIFIER
+
+| Objectif Original | Modification Proposée | Raison |
+|---|---|---|
+| **600 features en 24 mois** | **~490 features en 25 mois** (mars 2027) | Scope irréaliste pour 1-2 développeurs. 82% est un excellent résultat |
+| **Chat Rust (veza-chat-server)** | **Chat Go** (tel qu'implémenté) | ADR-002 validé, simplification positive |
+| **Stripe exclusif** | **Hyperswitch** (tel qu'implémenté) | Meilleure flexibilité, open-source |
+| **Elasticsearch Phase 5** | **Elasticsearch Phase 5R** (août 2026) | Reporter mais ne pas abandonner — critique pour scale |
+| **Traefik** | **HAProxy** puis migration si besoin | Fonctionnel, migrer uniquement si nécessaire |
+| **React Native mobile (Phase 4)** | **PWA-enhanced** court terme, natif Phase 6R | Économiser des mois de dev, réévaluer quand MAU > 5K |
+| **CQRS** | **Pattern request-response** | Complexité injustifiée à cette échelle |
+| **gRPC inter-service** | **REST** puis migration si bottleneck mesuré | Pragmatisme |
+| **Gamification (F536-F550)** | **Reporter à Phase 7+** | Pas critique pour le core product, gamification quand base users établie |
+| **Live Streaming (10 features complètes)** | **Live Streaming Lite (5 features)** | Go live, chat, tips, VOD — le reste en Phase 6R |
+
+### 7.3 Objectifs ORIGIN à ABANDONNER
+
+| Objectif | Raison d'Abandon | Alternative |
+|---|---|---|
+| **Web3/Blockchain (F491-F500)** | Market crypto incertain, complexité juridique, pas de demande marché prouvée | Surveiller le marché, réintroduire si demande utilisateur |
+| **VR/AR (E001-E020)** | Marché niche, coût de développement élevé, pas de ROI prévisible | Aucune — technologie prématurée pour une plateforme audio |
+| **Electron desktop app** | Tauri serait meilleur si besoin, mais PWA couvre 95% des cas | PWA avec offline mode |
+| **Voice synthesis AI (F468)** | Risques éthiques et juridiques (deepfakes audio) | Focus sur AI utile : BPM/key detection, auto-tags |
+| **AI mixing assistant (F470)** | Trop ambitieux, nécessite ML expertise dédiée | Partenariat avec service tiers (LANDR, iZotope) |
+| **DAO governance** | Hors scope produit audio, complexité juridique | Gouvernance classique (advisory board) |
+| **NFT minting** | Marché en déclin, risque réputationnel | Licensing traditionnel (déjà implémenté) |
+| **Kafka** | RabbitMQ suffit, pas de besoin event sourcing | Garder RabbitMQ |
+| **SOC2 certification** | Coût et effort disproportionnés pour une startup pre-revenue | Focus GDPR (obligatoire) + bonnes pratiques sécurité |
+
+### 7.4 Matrice de Décision Finale
+
+| Catégorie | Features | Action |
+|---|---|---|
+| ✅ Garder | ~430 features (72%) | Continuer le développement selon la roadmap |
+| ⚠️ Modifier | ~70 features (12%) | Ajuster le scope, l'ordre, ou l'approche |
+| ❌ Abandonner | ~100 features (17%) | Retirer du backlog, documenter la décision |
+
+---
+
+## 8. VIOLATIONS CRITIQUES ORIGIN ET PLAN DE CORRECTION
+
+### 8.1 Violations des Règles Immuables ORIGIN
+
+| # | Règle ORIGIN | Violation | Correction | Effort | Deadline |
+|---|---|---|---|---|---|
+| V01 | Coverage ≥ 80% toutes phases | Seuil à 50% frontend, non mesuré Go/Rust | Configurer CI coverage, monter progressivement : 60% → 70% → 80% | 5j | Fin avril 2026 |
+| V02 | 0 vulnérabilités critiques | 2 critiques (JWT) | Corriger VEZA-SEC-001 et VEZA-SEC-002 | 2j | Mi-mars 2026 |
+| V03 | Pas de feature creep | Features P6-P7 implémentées avant P3-P4 complètes | Consolider P2-P3 avant d'avancer (Phase 3.5) | — | Plan ci-dessus |
+| V04 | Phase complète à 100% avant suivante | P3 à 65%, P4 démarrée | Compléter P3 dans Phase 3.5 | 4 sem | Fin avril 2026 |
+| V05 | Security audit externe avant P1, P3, P5, P7 | Aucun audit externe réalisé | Commander un pentest externe | 2 sem + budget | Avant Phase 4R |
+| V06 | Code review 2+ reviewers | Solo developer | Recruter reviewers (communauté, freelance, AI review) | — | Continu |
+| V07 | Documentation API à jour | Swagger existe mais pas synchronisé automatiquement | Intégrer swag generate dans CI | 1j | Fin mars 2026 |
+
+### 8.2 Priorités de Correction
+
+```
+URGENT (< 2 semaines)
+├── V02 : Corriger les 2 vulns JWT critiques
+├── V07 : Synchroniser Swagger
+└── Nettoyer secrets hardcodés
+
+IMPORTANT (< 2 mois)
+├── V01 : Coverage CI/CD configurée et progressive
+├── V04 : Compléter Phase 3 features manquantes
+├── V03 : Consolider avant d'avancer
+└── V05 : Commander pentest externe
+
+NÉCESSAIRE (< 6 mois)
+├── V06 : Trouver des reviewers
+├── Coverage à 80%
+└── Lighthouse CI + performance baseline
+```
+
+---
+
+## CONCLUSION
+
+Le projet Veza a construit une base technique solide avec une architecture clean, un monorepo bien organisé, et des fondations fonctionnelles (auth, streaming, marketplace, infrastructure CI/CD). Cependant, il accuse un retard de ~6 mois sur le plan ORIGIN, principalement dû à l'ambition du scope (600 features / 24 mois) face aux ressources disponibles.
+
+**Le plan ORIGIN reste un excellent guide directeur**, mais il doit être adapté à la réalité :
+
+1. **Réduire le scope de 600 à ~490 features** (abandonner Web3, VR/AR, certaines features AI)
+2. **Consolider avant d'avancer** (Phase 3.5 de stabilisation)
+3. **Corriger immédiatement les 2 vulnérabilités critiques JWT**
+4. **Établir les métriques de qualité** (coverage, performance, monitoring)
+5. **Suivre la roadmap révisée** pour atteindre 82% de complétion d'ici mars 2027
+
+Le projet est **techniquement viable** et les choix architecturaux (pivots Chat Go, Hyperswitch, simplification gRPC→REST) sont **pragmatiques et justifiés**. L'enjeu principal n'est pas technique mais de **priorisation** : livrer les features qui génèrent le plus de valeur business en premier (marketplace, premium, analytics) tout en maintenant la qualité.
+
+---
+
+*Document généré le 4 mars 2026*
+*Basé sur : Audit Technique VEZA 2026-03-04 + Documentation ORIGIN*
+*Méthodologie : Analyse statique du code, cross-référencement F001-F600 avec le codebase, comparaison métriques ORIGIN vs mesures actuelles*
+
diff --git a/VEZA_VERSIONS_ROADMAP.md b/VEZA_VERSIONS_ROADMAP.md
new file mode 100644
index 000000000..8ec452903
--- /dev/null
+++ b/VEZA_VERSIONS_ROADMAP.md
@@ -0,0 +1,1284 @@
+# VEZA_VERSIONS_ROADMAP.md
+
+> **Système de versionnage Veza — v1.0 de ce document**
+>
+> Ce fichier est la source de vérité unique pour le déroulé des versions de développement.
+> Il est conçu pour être utilisé avec Cursor : donner simplement "implémente la prochaine version"
+> suffit pour déclencher une session de travail complète et ciblée.
+>
+> **Convention** : Chaque version est atomique, testable, et mergeable indépendamment.
+> Une version = un incrément de valeur livrable. Pas de version ouverte en parallèle.
+>
+> **Référence** : Tous les détails techniques et éthiques sont dans les fichiers ORIGIN/.
+> Ce fichier orchestre — les ORIGIN spécifient.
+>
+> **Dernière mise à jour** : 2026-03-04
+> **Auteur** : Architecte principal Veza
+
+---
+
+## 📋 ÉTAT GLOBAL
+
+| Phase | Versions | Statut | Objectif |
+|-------|----------|--------|----------|
+| **P3.5 — Consolidation & Sécurité** | v0.9.1 → v0.9.9 | 🔴 EN COURS | Stabiliser, sécuriser, dettes techniques |
+| **P4R — Social & Live** | v0.10.0 → v0.10.9 | ⏳ À VENIR | Chat complet, feed social, livestream |
+| **P5R — Analytics & Recherche** | v0.11.0 → v0.11.9 | ⏳ À VENIR | Analytics créateur, recherche éthique |
+| **P6R — Premium & Infrastructure** | v0.12.0 → v0.12.9 | ⏳ À VENIR | Plans premium, distribution, perf |
+| **v1.0 — Release Stable** | v1.0.0 | ⏳ À VENIR | GO/NO-GO criteria atteints |
+
+---
+
+## 🔴 PHASE P3.5 — CONSOLIDATION & SÉCURITÉ
+
+> Objectif : avant de construire de nouvelles features, rendre le système fiable, sécurisé, et maintenable.
+> Aucune feature P4R ne commence avant que P3.5 soit complète.
+
+---
+
+### v0.9.1 — Vulnérabilités Critiques JWT (TASK-SEC-001 + TASK-SEC-002)
+
+**Statut** : ✅ DONE
+**Priorité** : P0 — BLOQUANT
+**Durée estimée** : 2-3 jours
+**Prerequisite** : Aucun
+**Complété le** : 2026-03-05
+
+**Objectif**
+Corriger les deux vulnérabilités de sécurité critiques identifiées dans l'audit (VEZA-SEC-001 et VEZA-SEC-002). Sans ces correctifs, aucune autre feature ne peut être déployée en production.
+
+**Tâches**
+
+- [x] **TASK-SEC-001** : Migration JWT HS256 → RS256
+ - Générer paire de clés RSA 2048-bit (clé privée backend, clé publique publique)
+ - Modifier le service JWT pour signer avec RS256
+ - Mettre à jour tous les middleware de validation JWT
+ - Mettre à jour les variables d'environnement (supprimer `JWT_SECRET`, ajouter `JWT_PRIVATE_KEY_PATH`, `JWT_PUBLIC_KEY_PATH`)
+ - Invalider tous les tokens existants (migration token_version)
+ - Référence : ORIGIN_SECURITY_FRAMEWORK.md §0 VEZA-SEC-001, ORIGIN_DEPLOYMENT_GUIDE.md §15
+
+- [x] **TASK-SEC-002** : Supprimer les clés privées committées / secrets exposés
+ - Audit complet de l'historique git (truffleHog ou équivalent)
+ - Rotation immédiate de toutes les clés compromises (Stripe, OAuth, JWT, DB)
+ - Mettre en place `.gitignore` complet pour tous les fichiers `.env`
+ - Créer `.env.example` documenté avec toutes les variables requises
+ - Référence : ORIGIN_SECURITY_FRAMEWORK.md §0 VEZA-SEC-002
+
+**Critères d'acceptation**
+- [x] Tous les JWT générés utilisent RS256 (ou HS256 fallback dev) et sont vérifiés avec la clé publique / secret
+- [x] Aucun secret hardcodé par défaut (veza-common corrigé, procédure audit docs/SECRETS_AUDIT.md)
+- [x] `.env.example` et docs/ENV_VARIABLES.md couvrent les variables requises
+- [x] Tests d'authentification passent (unit + handler)
+- [ ] Déploiement staging valide avec les nouvelles clés (à valider manuellement)
+
+**Fichiers principaux à modifier**
+- `backend/internal/auth/jwt_service.go`
+- `backend/internal/middleware/auth_middleware.go`
+- `.env.example`
+- `backend/configs/`
+- `docker-compose.yml` (variables d'env)
+
+---
+
+### v0.9.2 — Sécurité Infrastructure (TASK-SEC-003 à 006)
+
+**Statut** : ⏳ TODO
+**Priorité** : P0 — BLOQUANT
+**Durée estimée** : 1-2 jours
+**Prerequisite** : v0.9.1 complète
+
+**Objectif**
+Fermer les vecteurs d'attaque infrastructure : endpoint `/metrics` exposé, rate limiting manquant, headers de sécurité absents.
+
+**Tâches**
+
+- [ ] **TASK-SEC-003** : Rate limiting global
+ - Implémenter rate limiting middleware sur toutes les routes publiques
+ - Règles : 100 req/h par IP (non-auth), 1000 req/h (auth)
+ - Redis comme backend pour le comptage distribué
+ - Référence : ORIGIN_SECURITY_FRAMEWORK.md, ORIGIN_FEATURES_REGISTRY.md F026
+
+- [ ] **TASK-SEC-004** : Security headers HTTP
+ - `Content-Security-Policy`, `X-Frame-Options`, `X-Content-Type-Options`
+ - `Strict-Transport-Security` (HSTS)
+ - `Referrer-Policy`
+ - Middleware centralisé dans HAProxy ou au niveau Go
+
+- [ ] **TASK-SEC-005** : Validation et sanitization des inputs
+ - Audit de tous les endpoints existants (pas de SQL injection, XSS)
+ - Binding validation exhaustif sur tous les handlers
+ - Taille max des payloads (1MB par défaut, 500MB pour upload audio)
+
+- [ ] **TASK-SEC-006** : Protection endpoint `/metrics`
+ - Route Prometheus `/metrics` accessible seulement depuis réseau interne
+ - Authentification bearer token ou IP whitelist
+ - Référence : ORIGIN_SECURITY_FRAMEWORK.md §0, ORIGIN_IMPLEMENTATION_TASKS.md TASK-SEC-006
+
+**Critères d'acceptation**
+- [ ] `curl http://api.veza.app/metrics` depuis internet → 403
+- [ ] 101ème requête depuis une IP non-auth → 429 Too Many Requests
+- [ ] Headers de sécurité visibles dans les réponses (vérifiable avec `curl -I`)
+- [ ] Tests de pénétration basiques (OWASP Top 10) passent sans résultat critique
+
+---
+
+### v0.9.3 — Toolchain et Environnement (TASK-QA-006 à 010)
+
+**Statut** : ⏳ TODO
+**Priorité** : P1
+**Durée estimée** : 1 jour
+**Prerequisite** : v0.9.1 complète
+
+**Objectif**
+Standardiser l'environnement de développement pour que tous les développeurs (et Cursor) travaillent dans des conditions identiques et reproductibles.
+
+**Tâches**
+
+- [ ] **TASK-QA-006** : Créer `.nvmrc` à la racine du monorepo
+ - Version Node.js fixée (LTS actuel)
+ - Référence : ORIGIN_QUALITY_METRICS.md §6.4 DT-007
+
+- [ ] **TASK-QA-007** : Créer `rust-toolchain.toml` pour le stream server
+ - Version Rust stable fixée
+ - Référence : ORIGIN_QUALITY_METRICS.md §6.4 DT-008
+
+- [ ] **TASK-QA-008** : Créer `Makefile` racine
+ - Commandes : `make dev`, `make test`, `make build`, `make lint`, `make clean`
+ - Commande `make doctor` vérifiant toutes les dépendances requises
+
+- [ ] **TASK-QA-009** : Documenter toutes les variables d'environnement requises
+ - `docs/ENV_VARIABLES.md` avec description, type, valeur par défaut, exemples
+ - Script de validation au démarrage
+
+- [ ] **TASK-QA-010** : `docker-compose.dev.yml` fonctionnel
+ - Tous les services (Go backend, Rust stream, React frontend, Postgres, Redis) démarrables avec une commande
+ - Hot reload activé pour le développement
+
+**Critères d'acceptation**
+- [ ] `make dev` démarre tous les services en moins de 30 secondes
+- [ ] `make test` exécute toute la suite de tests
+- [ ] Un développeur nouvellement arrivé peut démarrer l'environnement sans aide
+- [ ] README racine à jour avec instructions setup
+
+---
+
+### v0.9.4 — Quality Gates CI/CD (TASK-QA-001 à 005)
+
+**Statut** : ⏳ TODO
+**Priorité** : P1
+**Durée estimée** : 2 jours
+**Prerequisite** : v0.9.3 complète
+
+**Objectif**
+Mettre en place les quality gates automatisées pour que chaque PR soit validée avant merge. Zéro régression non détectée.
+
+**Tâches**
+
+- [ ] **TASK-QA-001** : Pipeline CI GitHub Actions (ou équivalent)
+ - Stage 1 : lint (golangci-lint, ESLint, rustfmt/clippy)
+ - Stage 2 : unit tests (Go, Rust, React)
+ - Stage 3 : integration tests (avec Postgres + Redis en service)
+ - Stage 4 : build (vérification que tout compile)
+ - Référence : ORIGIN_QUALITY_METRICS.md §7.1bis
+
+- [ ] **TASK-QA-002** : Coverage gates
+ - Go backend : coverage ≥ 60% (objectif 80%)
+ - Frontend React : coverage ≥ 50%
+ - PR rejetée automatiquement si coverage descend
+
+- [ ] **TASK-QA-003** : Linting strict
+ - `.golangci.yml` configuré avec règles pertinentes
+ - `.eslintrc` strict pour TypeScript
+ - Aucun warning accepté en CI
+
+- [ ] **TASK-QA-004** : Tests d'intégration de santé
+ - Test : tous les services démarrent correctement
+ - Test : endpoints de health check répondent
+ - Test : connexions DB et Redis établies
+
+- [ ] **TASK-QA-005** : Notifications de CI
+ - Notification Slack/Discord sur failure
+ - Badge CI dans le README
+
+**Critères d'acceptation**
+- [ ] Chaque push sur une branche déclenche le pipeline
+- [ ] Pipeline complet s'exécute en moins de 10 minutes
+- [ ] Une PR avec tests échoués ne peut pas être mergée
+- [ ] Coverage visible dans chaque PR
+
+---
+
+### v0.9.5 — Suppression Code Mort (TASK-DEBT-001 à 005)
+
+**Statut** : ⏳ TODO
+**Priorité** : P1
+**Durée estimée** : 1-2 jours
+**Prerequisite** : v0.9.4 complète (les tests protègent contre les régressions)
+
+**Objectif**
+Supprimer tout le code mort identifié dans l'audit. Réduire la surface de maintenance et éliminer la confusion architecturale.
+
+**Tâches**
+
+- [ ] **TASK-DEBT-001** : Supprimer le répertoire `soundcloud/` (ou équivalent SoundCloud import)
+ - Confirmer qu'aucun code en production ne l'importe
+ - Supprimer et nettoyer les imports
+
+- [ ] **TASK-DEBT-002** : Supprimer `webrtc.rs` du stream server (si non utilisé)
+ - Le stream server Rust ne fait pas de WebRTC (voir ADR-002)
+ - Confirmer dans le code, supprimer si orphelin
+
+- [ ] **TASK-DEBT-003** : Supprimer `k8s/chat-server/` (Kubernetes manifests pour le chat Rust obsolète)
+ - Le chat server est maintenant en Go (ADR-002)
+ - Référence : ORIGIN_IMPLEMENTATION_TASKS_ARCHIVE.md note T0051-T0065
+
+- [ ] **TASK-DEBT-004** : Supprimer ou désactiver tous les endpoints AI/Web3/Gamification
+ - Rechercher dans le codebase : routes AI, NFT, XP, leaderboard, gamification
+ - Supprimer le code correspondant
+ - Référence : ORIGIN_REVISION_SUMMARY.md §1, ORIGIN_FEATURES_REGISTRY.md §29
+
+- [ ] **TASK-DEBT-005** : Nettoyer les dépendances inutilisées
+ - `go mod tidy` et vérification des modules Go
+ - `npm audit` et suppression des packages inutilisés
+ - `cargo update` et nettoyage des crates Rust
+
+**Critères d'acceptation**
+- [ ] `grep -r "soundcloud\|nft\|blockchain\|xp_system\|leaderboard" --include="*.go" --include="*.ts" --include="*.rs"` → aucun résultat dans le code actif
+- [ ] Taille du bundle frontend réduite (mesurer avant/après)
+- [ ] Tous les tests passent après nettoyage
+
+---
+
+### v0.9.6 — Chat Complet : Réactions & Mentions (TASK-CHAT-001 à 003)
+
+**Statut** : ⏳ TODO
+**Priorité** : P1
+**Durée estimée** : 3-4 jours
+**Prerequisite** : v0.9.2 complète
+
+**Objectif**
+Compléter le module Chat (Go) avec les features manquantes : réactions aux messages, mentions @utilisateur, et search dans l'historique.
+
+**Tâches**
+
+- [ ] **TASK-CHAT-001** : Réactions aux messages (émojis)
+ - Backend : endpoint POST/DELETE `/api/v1/chat/messages/{id}/reactions`
+ - Table `message_reactions` (message_id, user_id, emoji, created_at)
+ - WebSocket : event `message:reaction_added` / `message:reaction_removed`
+ - Frontend : picker émoji inline, compteur de réactions
+ - Référence : ORIGIN_FEATURES_REGISTRY.md F162
+
+- [ ] **TASK-CHAT-002** : Mentions @utilisateur
+ - Backend : parsing des `@username` dans les messages
+ - Notification push pour les utilisateurs mentionnés
+ - Frontend : autocomplete @username en cours de frappe
+ - Référence : ORIGIN_FEATURES_REGISTRY.md F163
+
+- [ ] **TASK-CHAT-003** : Recherche dans l'historique des messages
+ - Backend : endpoint GET `/api/v1/chat/rooms/{id}/messages/search?q=...`
+ - Elasticsearch ou fulltext PostgreSQL (pg_trgm)
+ - Frontend : barre de recherche dans le panel chat
+ - Référence : ORIGIN_FEATURES_REGISTRY.md F165
+
+**Critères d'acceptation**
+- [ ] Un utilisateur peut réagir à un message avec un émoji, la réaction apparaît en temps réel chez tous les participants
+- [ ] `@alice` dans un message déclenche une notification pour alice
+- [ ] La recherche retourne des résultats pertinents en moins de 200ms
+- [ ] Aucune régression sur les features chat existantes
+
+---
+
+### v0.9.7 — Chat Complet : Fichiers & Threads (TASK-CHAT-004 à 006)
+
+**Statut** : ⏳ TODO
+**Priorité** : P1
+**Durée estimée** : 3-4 jours
+**Prerequisite** : v0.9.6 complète
+
+**Objectif**
+Compléter le module Chat avec l'envoi de fichiers, les threads (réponse à un message), et la gestion des rooms de groupe.
+
+**Tâches**
+
+- [ ] **TASK-CHAT-004** : Envoi de fichiers dans le chat
+ - Backend : endpoint POST `/api/v1/chat/messages/{id}/attachments`
+ - Types acceptés : audio (mp3, wav, ogg), image (jpg, png), PDF
+ - Upload S3, URL signée temporaire (24h)
+ - Taille max : 50MB par fichier
+ - Référence : ORIGIN_FEATURES_REGISTRY.md F166
+
+- [ ] **TASK-CHAT-005** : Threads (réponse à un message)
+ - Backend : champ `reply_to_message_id` dans la table messages
+ - Frontend : UI thread avec message parent visible
+ - Référence : ORIGIN_FEATURES_REGISTRY.md F161
+
+- [ ] **TASK-CHAT-006** : Rooms de groupe (invitations, gestion des membres)
+ - Backend : endpoints CRUD pour la gestion des membres d'une room
+ - Invitations avec lien unique (expire en 7 jours)
+ - Rôles dans le groupe : owner, admin, member
+ - Référence : ORIGIN_FEATURES_REGISTRY.md F155-F160
+
+**Critères d'acceptation**
+- [ ] Partage d'un fichier audio dans le chat → lecture inline possible
+- [ ] Thread visible avec message parent
+- [ ] Invitation par lien fonctionne (flow complet)
+- [ ] Owner peut kick un membre
+
+---
+
+### v0.9.8 — Réduction Dette Technique Backend (TASK-DEBT-006 à 012)
+
+**Statut** : ⏳ TODO
+**Priorité** : P1
+**Durée estimée** : 3-4 jours
+**Prerequisite** : v0.9.4 complète
+
+**Objectif**
+Corriger les patterns d'erreur identifiés dans l'audit technique (PAT-024 à PAT-028) : propagation de contexte, goroutine leaks, pagination incohérente, error handling non standardisé.
+
+**Tâches**
+
+- [ ] **TASK-DEBT-006** : Standardisation error handling Go
+ - Tous les handlers retournent des erreurs au format `{"error": {"code": "...", "message": "...", "context": {...}}}`
+ - Créer package `pkg/apierror` avec types d'erreurs standardisés
+ - Référence : ORIGIN_ERROR_PATTERNS.md PAT-028, ORIGIN_ERROR_PREVENTION_GUIDE.md §2.6
+
+- [ ] **TASK-DEBT-007** : Context propagation dans tous les services Go
+ - Audit : chaque fonction qui fait I/O doit accepter `context.Context` comme premier paramètre
+ - Deadline et cancellation propagés correctement
+ - Référence : ORIGIN_ERROR_PATTERNS.md PAT-025
+
+- [ ] **TASK-DEBT-008** : Goroutine lifecycle management
+ - Audit : chaque goroutine a un mécanisme de terminaison propre
+ - `WaitGroup` ou channels de done utilisés correctement
+ - Tests de détection de goroutine leaks (goleak)
+ - Référence : ORIGIN_ERROR_PATTERNS.md PAT-026
+
+- [ ] **TASK-DEBT-009** : Pagination cohérente sur tous les endpoints de liste
+ - Standard : `?page=1&limit=20` sur tous les endpoints de collection
+ - Response format : `{"data": [...], "pagination": {"page": 1, "limit": 20, "total": 150, "total_pages": 8}}`
+ - Référence : ORIGIN_ERROR_PATTERNS.md PAT-027, ORIGIN_CODE_STANDARDS.md §3.7
+
+- [ ] **TASK-DEBT-010** : JWT mismatch resolution
+ - Audit de toutes les validations JWT : uniformiser les claims attendus
+ - Référence : ORIGIN_ERROR_PATTERNS.md PAT-024
+
+- [ ] **TASK-DEBT-011** : Logging structuré uniforme
+ - Tous les logs au format JSON avec champs : `level`, `time`, `msg`, `request_id`, `user_id` (si applicable)
+ - Niveaux : DEBUG (dev uniquement), INFO (prod), WARN, ERROR
+
+- [ ] **TASK-DEBT-012** : Documentation ADR systématique
+ - Créer `docs/adr/` avec les ADR existants formalisés (ADR-001 à ADR-012)
+ - Référence : ORIGIN_REVISION_SUMMARY.md §3
+
+**Critères d'acceptation**
+- [ ] Tous les endpoints de liste ont une pagination cohérente
+- [ ] `goleak` ne détecte pas de goroutine leaks dans les tests
+- [ ] Toutes les erreurs API suivent le format standardisé
+- [ ] Couverture de tests ≥ 70% sur le package `pkg/apierror`
+
+---
+
+### v0.9.9 — Réduction Dette Technique Frontend (TASK-DEBT-013 à 017)
+
+**Statut** : ⏳ TODO
+**Priorité** : P1
+**Durée estimée** : 2-3 jours
+**Prerequisite** : v0.9.4 complète
+
+**Objectif**
+Nettoyer la dette technique frontend : types TypeScript incomplets, composants non accessibles, bundle non optimisé.
+
+**Tâches**
+
+- [ ] **TASK-DEBT-013** : TypeScript strict mode complet
+ - Activer `"strict": true` dans `tsconfig.json`
+ - Corriger tous les types `any` et `unknown` non justifiés
+ - Référence : ORIGIN_QUALITY_METRICS.md §6.4 DT-013
+
+- [ ] **TASK-DEBT-014** : Accessibilité WCAG AA (audit et corrections)
+ - Audit avec axe-core ou Lighthouse
+ - ARIA labels sur tous les composants interactifs
+ - Keyboard navigation fonctionnelle (Tab, Enter, Escape)
+ - Référence : ORIGIN_UI_UX_SYSTEM.md §14, ORIGIN_FEATURE_VALIDATION_STRATEGY.md §7
+
+- [ ] **TASK-DEBT-015** : Optimisation bundle (code splitting)
+ - Lazy loading des routes React (React.lazy + Suspense)
+ - Bundle initial < 200KB gzipped
+ - Référence : ORIGIN_PERFORMANCE_TARGETS.md
+
+- [ ] **TASK-DEBT-016** : Storybook ou équivalent pour les composants UI
+ - Documentation des composants du design system SUMI
+ - Stories pour les états : default, loading, error, empty
+ - Référence : ORIGIN_UI_UX_SYSTEM.md
+
+- [ ] **TASK-DEBT-017** : Tests de régression visuels (optionnel)
+ - Playwright ou Chromatic pour screenshots de référence
+ - Référence : ORIGIN_TESTING_STRATEGY.md §13
+
+**Critères d'acceptation**
+- [ ] `npm run build` sans erreurs TypeScript
+- [ ] Score Lighthouse Accessibility ≥ 90
+- [ ] Bundle initial < 200KB gzipped (mesuré avec `npx bundlesize`)
+- [ ] Navigation clavier complète sur les flows critiques (login, upload, chat)
+
+---
+
+## 🟡 PHASE P4R — SOCIAL & LIVE
+
+> Prerequisite : **Toutes les versions P3.5 (v0.9.x) sont complètes et validées.**
+> La phase P4R est déclenche uniquement après GO/NO-GO sur P3.5 (voir critères en fin de document).
+
+---
+
+### v0.10.0 — Feed Social Chronologique (F186-F200)
+
+**Statut** : ⏳ TODO
+**Priorité** : P1
+**Durée estimée** : 4-5 jours
+**Prerequisite** : v0.9.9 complète
+
+**Objectif**
+Implémenter le système de follow/unfollow et le feed chronologique. Le feed est basé sur les follows de l'utilisateur, sans algorithme de rétention.
+
+**Tâches**
+
+- [ ] Follow / Unfollow un utilisateur (F186)
+ - Backend : POST/DELETE `/api/v1/users/{id}/follow`
+ - Table `follows` (follower_id, following_id, created_at)
+ - Index pour requêtes rapides dans les deux sens
+
+- [ ] Compteurs followers/following sur les profils (F187)
+ - Dénormalisé dans `users.followers_count` et `users.following_count`
+ - Mis à jour via trigger DB ou job asynchrone
+
+- [ ] Feed chronologique des artistes suivis (F210)
+ - Backend : GET `/api/v1/feed?cursor=...&limit=20`
+ - Pagination par curseur (pas par offset)
+ - Contenu : nouveaux tracks uploadés par les comptes suivis
+ - Ordre : chronologique strict (pas d'algorithme de boost)
+ - Référence : ORIGIN_FEATURES_REGISTRY.md F210, ORIGIN_MASTER_ARCHITECTURE.md §4
+
+- [ ] Suggestions de comptes à suivre (F211)
+ - Basé sur : connexions sociales (amis d'amis), genres déclarés, localisation (opt-in)
+ - Pas de collaborative filtering ML
+ - Référence : ORIGIN_FEATURES_REGISTRY.md §30 (Algorithme de découverte éthique)
+
+- [ ] Notifications de nouveaux followers
+
+**Critères d'acceptation**
+- [ ] Follow/unfollow en moins de 100ms
+- [ ] Feed se charge en moins de 200ms pour 20 items
+- [ ] Feed est strictement chronologique (vérifiable)
+- [ ] Pagination par curseur fonctionne correctement (pas de doublons)
+- [ ] Aucune donnée de comportement utilisateur utilisée pour le ranking
+
+---
+
+### v0.10.1 — Découverte Éthique : Tags & Genres (F351-F360)
+
+**Statut** : ⏳ TODO
+**Priorité** : P1
+**Durée estimée** : 3-4 jours
+**Prerequisite** : v0.10.0 complète
+
+**Objectif**
+Implémenter le système de tags déclaratifs et la découverte par genres. C'est le cœur de l'algorithme de découverte éthique.
+
+**Tâches**
+
+- [ ] Système de tags déclaratifs sur les tracks (F351)
+ - Tags créés par l'artiste lui-même
+ - Validation : max 10 tags par track, longueur max 30 chars
+ - Table `track_tags`, table `tags` (avec compteur d'utilisation)
+
+- [ ] Genres musicaux normalisés (F352)
+ - Taxonomy fixe (liste fermée, extensible via PR)
+ - Multi-genre supporté (max 3 genres par track)
+
+- [ ] Browse par genre / tag (F353)
+ - GET `/api/v1/discover/genre/{genre}?sort=recent&cursor=...`
+ - GET `/api/v1/discover/tag/{tag}?cursor=...`
+ - Tri : chronologique uniquement (pas de popularité)
+
+- [ ] Suivre un genre ou un tag (F354)
+ - L'utilisateur peut "suivre" des genres/tags
+ - Le feed inclut les nouvelles sorties dans les genres/tags suivis
+
+- [ ] Nouveautés dans les genres suivis (F355)
+ - Section dédiée dans le feed : "Nouvelles sorties dans vos genres"
+ - Référence : ORIGIN_FEATURES_REGISTRY.md §30
+
+**Critères d'acceptation**
+- [ ] Un artiste peut taguer son track avec des tags libres (max 10)
+- [ ] Un utilisateur peut suivre le genre "jazz" et voir les nouveautés jazz dans son feed
+- [ ] Browse par genre retourne des tracks triées par date (plus récent en premier)
+- [ ] Test de biais : les artistes émergents apparaissent autant que les artistes établis dans les résultats de découverte
+
+---
+
+### v0.10.2 — Recherche Fulltext Elasticsearch (F361-F370)
+
+**Statut** : ⏳ TODO
+**Priorité** : P1
+**Durée estimée** : 4-5 jours
+**Prerequisite** : v0.10.1 complète
+
+**Objectif**
+Implémenter la recherche fulltext avec Elasticsearch. Recherche de tracks, artistes, et playlists par mots-clés.
+
+**Tâches**
+
+- [ ] Index Elasticsearch pour les tracks (F361)
+ - Champs indexés : title, artist, tags, genre, description
+ - Mapping avec analyzer français/anglais
+ - Synchronisation depuis PostgreSQL (via CDC ou job périodique)
+ - Référence : ORIGIN_MASTER_ARCHITECTURE.md ADR-012, ORIGIN_TECHNICAL_STACK.md §17
+
+- [ ] Index Elasticsearch pour les utilisateurs (F362)
+ - Champs : username, display_name, bio, genres, location
+
+- [ ] Endpoint de recherche unifiée (F363)
+ - GET `/api/v1/search?q=...&type=tracks,users,playlists&cursor=...`
+ - Résultats groupés par type
+ - Highlighting des termes trouvés
+
+- [ ] Recherche phonétique (French + English) (F364)
+ - Tolérance aux fautes de frappe
+ - Recherche par sonorité (pour les noms d'artistes)
+
+- [ ] Suggestions autocomplete (F365)
+ - GET `/api/v1/search/suggest?q=...`
+ - Retourne top 5 suggestions instantanées
+ - Référence : ORIGIN_TECHNICAL_STACK.md §17
+
+**Critères d'acceptation**
+- [ ] Recherche "acid jazz" retourne des tracks taggées avec les deux termes séparément
+- [ ] Résultats en moins de 200ms
+- [ ] Faute de frappe "jaz" retourne quand même des résultats jazz
+- [ ] Pas de résultats basés sur des métriques d'engagement (pas de boost popularity)
+- [ ] Test : recherche d'un artiste avec 0 plays retourne les mêmes résultats de pertinence qu'un artiste populaire pour la même requête
+
+---
+
+### v0.10.3 — Commentaires & Interactions Sociales (F201-F215)
+
+**Statut** : ⏳ TODO
+**Priorité** : P2
+**Durée estimée** : 3-4 jours
+**Prerequisite** : v0.10.0 complète
+
+**Objectif**
+Implémenter les commentaires sur les tracks et les likes, sans métriques de popularité visibles publiquement.
+
+**Tâches**
+
+- [ ] Commentaires sur les tracks (F201)
+ - POST `/api/v1/tracks/{id}/comments`
+ - Commentaires avec timestamp (position dans la piste)
+ - Modération : filtrage par liste de mots-clés (pas de ML)
+
+- [ ] Likes / Unlikes sur les tracks (F202)
+ - POST/DELETE `/api/v1/tracks/{id}/like`
+ - Compteur visible uniquement par le créateur dans ses analytics (pas publiquement)
+ - Référence : ORIGIN_REVISION_SUMMARY.md §2 (anti social validation loop)
+
+- [ ] Reposts (partage d'une track dans son profil) (F203)
+
+- [ ] Notifications pour les interactions (F204)
+ - Notification pour le créateur quand quelqu'un commente
+ - Pas de notification "votre track a atteint X likes" (anti gamification)
+
+**Critères d'acceptation**
+- [ ] Les likes ne sont pas visibles publiquement (confirmé dans le design)
+- [ ] Le créateur voit ses stats dans sa section Analytics (privée)
+- [ ] Commentaire avec timestamp cliquable pour aller à ce moment dans la track
+
+---
+
+### v0.10.4 — Playlists Collaboratives (F136-F150)
+
+**Statut** : ⏳ TODO
+**Priorité** : P2
+**Durée estimée** : 3-4 jours
+**Prerequisite** : v0.10.0 complète
+
+**Objectif**
+Améliorer le système de playlists avec les fonctionnalités collaboratives et la curation manuelle.
+
+**Tâches**
+
+- [ ] Playlists collaboratives (plusieurs contributeurs) (F140)
+- [ ] Playlists curatoriales éditoriales (rôle admin/modérateur) (F141)
+ - Base de la découverte éthique : playlists créées par humains
+ - Référence : ORIGIN_FEATURES_REGISTRY.md §30
+
+- [ ] Partage de playlists (lien public, embed) (F143)
+- [ ] Import/export de playlists (M3U, JSON) (F145)
+- [ ] Playlist "Favoris" automatique par utilisateur (F136)
+
+**Critères d'acceptation**
+- [ ] Deux utilisateurs peuvent éditer la même playlist simultanément (sans conflit)
+- [ ] Playlist éditoriale visible dans la section Découverte
+- [ ] Export M3U fonctionnel
+
+---
+
+### v0.10.5 — Notifications Complètes (F551-F570)
+
+**Statut** : ⏳ TODO
+**Priorité** : P2
+**Durée estimée** : 2-3 jours
+**Prerequisite** : v0.10.3 complète
+
+**Objectif**
+Implémenter le système de notifications complet, respectueux du temps de l'utilisateur, sans FOMO.
+
+**Tâches**
+
+- [ ] Notifications in-app en temps réel (WebSocket) (F551)
+- [ ] Digest hebdomadaire email (opt-in) (F552)
+ - Résumé des nouvelles sorties dans les genres suivis
+ - Pas de recommandations comportementales
+ - Référence : ORIGIN_BUSINESS_LOGIC.md §8.1
+
+- [ ] Préférences de notifications granulaires (F553)
+ - Contrôle par type (follow, commentaire, message, etc.)
+ - Quiet hours configurables
+
+- [ ] Groupement de notifications (F554)
+ - "3 personnes ont commenté votre track" (pas 3 notifications séparées)
+
+- [ ] Centre de notifications (page dédiée) (F555)
+
+**Critères d'acceptation**
+- [ ] Aucune notification "vous avez atteint X likes" (anti gamification)
+- [ ] Par défaut : notifications push désactivées sauf messages directs et follows
+- [ ] L'utilisateur peut désactiver toutes les notifications marketing en un clic
+
+---
+
+### v0.10.6 — Livestreaming Basique (F471-F476)
+
+**Statut** : ⏳ TODO
+**Priorité** : P2
+**Durée estimée** : 5-7 jours
+**Prerequisite** : v0.10.0 complète, stream server Rust fonctionnel
+
+**Objectif**
+Implémenter le livestreaming audio basique via le stream server Rust (RTMP in, HLS out).
+
+**Tâches**
+
+- [ ] Ingest RTMP depuis OBS/équipement audio (F471)
+ - Stream server Rust accepte les connexions RTMP
+ - Authentification via stream key unique par créateur
+
+- [ ] Distribution HLS multi-bitrate (F472)
+ - Segmentation HLS (segments de 2 secondes)
+ - Bitrates : 64kbps, 128kbps, 320kbps
+ - Référence : ORIGIN_FEATURES_REGISTRY.md F475
+
+- [ ] Player live dans l'interface web (F473)
+ - Latence < 5 secondes
+ - Indicateur "LIVE" et nombre d'auditeurs
+
+- [ ] Chat du live (F474)
+ - Messages en temps réel pendant le live
+ - Modération : rate limiting (1 message/3 secondes)
+
+- [ ] Enregistrement automatique du live (optionnel, F476)
+ - Le live peut être sauvegardé comme track après la session
+
+**Critères d'acceptation**
+- [ ] Flow complet : créateur lance OBS → stream ingest → auditeur entend en moins de 5 secondes
+- [ ] Chat fonctionne pendant le live
+- [ ] Pas de crash si 0 auditeurs
+- [ ] Arrêt propre du stream (le créateur coupe OBS → le player affiche "Stream terminé")
+
+---
+
+### v0.10.7 — Collaboration Temps Réel (F481-F488)
+
+**Statut** : ⏳ TODO
+**Priorité** : P2
+**Durée estimée** : 5-6 jours
+**Prerequisite** : v0.10.6 complète
+
+**Objectif**
+Implémenter la collaboration temps réel basique : sessions de co-écoute et partage de projets.
+
+**Tâches**
+
+- [ ] Sessions de co-écoute synchronisée (F481)
+ - Plusieurs utilisateurs écoutent la même track en sync
+ - Le host contrôle la lecture
+
+- [ ] Partage de projets / stems (F482)
+ - Upload de stems séparés (kick, snare, bass, etc.)
+ - Autre utilisateur peut télécharger les stems
+
+- [ ] Espace de travail collaboratif partagé (F483)
+ - Room collaborative avec chat dédié + partage de fichiers
+ - Accès contrôlé (invitation seulement)
+
+**Critères d'acceptation**
+- [ ] Co-écoute : synchronisation en moins de 500ms entre participants
+- [ ] Partage de stems : tous les formats (wav, aiff, flac) acceptés
+- [ ] Room collaborative : max 10 participants simultanés
+
+---
+
+### v0.10.8 — Portabilité des Données (F065, GDPR)
+
+**Statut** : ⏳ TODO
+**Priorité** : P1
+**Durée estimée** : 2-3 jours
+**Prerequisite** : v0.10.0 complète
+
+**Objectif**
+Implémenter les droits RGPD : export des données, suppression de compte, droit à l'oubli.
+
+**Tâches**
+
+- [ ] Export des données utilisateur (ZIP) (F065)
+ - Endpoint POST `/api/v1/users/me/export` → génère un ZIP asynchrone
+ - Contenu : profil, tracks, playlists, messages, historique d'écoute
+ - Notification email quand le ZIP est prêt (valable 7 jours)
+ - Référence : ORIGIN_API_SPECIFICATION.md §7.10, ORIGIN_DATABASE_SCHEMA.md §19
+
+- [ ] Suppression de compte (F065)
+ - DELETE `/api/v1/users/me`
+ - Soft delete avec période de grâce 30 jours
+ - Hard delete après 30 jours (RGPD)
+ - Les tracks publiques restent (dissociées du compte) ou sont supprimées selon le choix
+
+- [ ] Droit à l'oubli (anonymisation)
+ - Remplacer les données PII par des placeholders
+ - Conserver les transactions financières (obligation légale)
+
+**Critères d'acceptation**
+- [ ] Export ZIP disponible en moins de 1 heure pour un compte avec 100 tracks
+- [ ] Suppression effective en 30 jours (testable avec un compte de test)
+- [ ] Conformité RGPD vérifiable : aucune donnée PII ne subsiste après 30 jours
+
+---
+
+## 🟢 PHASE P5R — ANALYTICS & RECHERCHE ÉTHIQUE
+
+> Prerequisite : **Toutes les versions P4R (v0.10.x) sont complètes et validées.**
+
+---
+
+### v0.11.0 — Analytics Créateur (F381-F395)
+
+**Statut** : ⏳ TODO
+**Priorité** : P1
+**Durée estimée** : 4-5 jours
+**Prerequisite** : v0.10.3 complète
+
+**Objectif**
+Donner aux créateurs des analytics sur leurs tracks, sans exposer ces métriques publiquement. Les données sont au service du créateur, pas de la plateforme.
+
+**Tâches**
+
+- [ ] Dashboard analytics créateur (F381)
+ - Nombre de plays, écoutes complètes, durée d'écoute par track
+ - Répartition géographique (pays, région — agrégée et anonymisée)
+ - Source de découverte (recherche, feed, partage direct, profil)
+ - Référence : ORIGIN_REVISION_SUMMARY.md §2 (données agrégées et anonymisées pour le créateur)
+
+- [ ] Evolution temporelle des plays (F382)
+ - Graphique par jour/semaine/mois
+
+- [ ] Téléchargements et achats (F383)
+ - Historique des ventes, revenus par période
+ - Export CSV
+
+- [ ] Analytics d'audience (F384)
+ - Profil générique des auditeurs (genre, âge — agrégé, pas individuel)
+
+- [ ] Métriques en temps réel pour les lives (F385)
+ - Auditeurs actuels pendant un livestream
+
+**Critères d'acceptation**
+- [ ] Aucune donnée individuelle exposée (agrégation minimum 10 utilisateurs)
+- [ ] Le créateur peut exporter ses analytics en CSV
+- [ ] Les métriques ne sont PAS visibles publiquement sur le profil de l'artiste
+- [ ] Score Lighthouse Privacy ≥ 90 sur les pages analytics
+
+---
+
+### v0.11.1 — Analytics Avancés (F396-F410)
+
+**Statut** : ⏳ TODO
+**Priorité** : P2
+**Durée estimée** : 3-4 jours
+**Prerequisite** : v0.11.0 complète
+
+**Tâches**
+
+- [ ] Heatmap d'écoute (F396)
+ - Segments d'une track les plus/moins écoutés (agrégé)
+ - Aide le créateur à comprendre où les auditeurs décrochent
+
+- [ ] Comparaison de périodes (F397)
+ - "Cette semaine vs semaine dernière"
+
+- [ ] Analytics de la marketplace (F398)
+ - Taux de conversion par produit (vues → achats)
+ - Revenus cumulés, commissions plateforme
+
+- [ ] Alertes métriques (F399)
+ - "Votre track a été jouée 100 fois" → notification opt-in
+ - Pas de gamification : juste une information utile
+
+**Critères d'acceptation**
+- [ ] Heatmap visible dans le dashboard analytics d'une track
+- [ ] Alertes sont opt-in et peuvent être désactivées
+
+---
+
+### v0.11.2 — Modération Avancée (F411-F420)
+
+**Statut** : ⏳ TODO
+**Priorité** : P1
+**Durée estimée** : 3-4 jours
+**Prerequisite** : v0.10.0 complète
+
+**Objectif**
+Implémenter le système de modération humaine assistée par règles déterministes (pas de ML).
+
+**Tâches**
+
+- [ ] Interface de modération pour les modérateurs (F411)
+ - Queue de contenu flaggé
+ - Actions : approve, reject, ban temporaire, ban permanent
+ - Référence : ORIGIN_BUSINESS_LOGIC.md §4.2
+
+- [ ] Signalement de contenu par les utilisateurs (F412)
+ - Bouton "Signaler" sur les tracks, commentaires, profils
+ - Categories : spam, contenu offensant, violation de droits, fake
+
+- [ ] Détection déterministe de spam (F413)
+ - Règles : titre/description identique (F413a)
+ - Règles : liens excessifs (F413b)
+ - Règles : patterns de bot (timing, rate) (F413c)
+ - Pas d'IA — uniquement des règles explicites
+ - Référence : ORIGIN_BUSINESS_LOGIC.md §4.2
+
+- [ ] Audio fingerprinting ACRCloud (F414)
+ - Détection de contenu copyrighted
+ - Track matchée → flaggée pour review humaine
+ - Référence : ORIGIN_FEATURES_REGISTRY.md F465 note
+
+- [ ] Système de strikes (F415)
+ - 3 strikes → suspension temporaire
+ - Procédure d'appel documentée
+
+**Critères d'acceptation**
+- [ ] La décision finale de modération est TOUJOURS humaine (confirmé dans le code)
+- [ ] Un modérateur peut traiter une action en moins de 30 secondes
+- [ ] Le créateur reçoit une notification avec la raison en cas de rejection
+
+---
+
+### v0.11.3 — Administration Plateforme (F421-F435)
+
+**Statut** : ⏳ TODO
+**Priorité** : P1
+**Durée estimée** : 3-4 jours
+**Prerequisite** : v0.11.2 complète
+
+**Tâches**
+
+- [ ] Dashboard admin (F421)
+ - Métriques plateforme : utilisateurs actifs, tracks uploadées, revenus
+ - Alertes système (taux d'erreur, latence, espace disque)
+
+- [ ] Gestion des utilisateurs (F422)
+ - Recherche, vue détaillée, édition du rôle, suspension/ban
+
+- [ ] Gestion du contenu (F423)
+ - Supprimer/masquer du contenu en violation
+
+- [ ] Gestion des paiements / litiges (F424)
+ - Vue des transactions, déclenchement de remboursements
+
+- [ ] Annonces système (F425)
+ - Bannière d'information pour tous les utilisateurs
+
+**Critères d'acceptation**
+- [ ] Admin peut bannir un utilisateur en moins de 5 clics
+- [ ] Dashboard admin accessible uniquement au rôle `admin` (test de sécurité)
+
+---
+
+## 🔵 PHASE P6R — PREMIUM & INFRASTRUCTURE
+
+> Prerequisite : **Toutes les versions P5R (v0.11.x) sont complètes et validées.**
+> Pentest externe réalisé avant ce milestone.
+
+---
+
+### v0.12.0 — Marketplace Complète (F226-F265)
+
+**Statut** : ⏳ TODO
+**Priorité** : P1
+**Durée estimée** : 6-8 jours
+**Prerequisite** : v0.11.0 complète
+
+**Tâches**
+
+- [ ] Création et gestion de produits (F226)
+ - Beats, samples, kits, presets, partitions
+ - Types de licences : Basic, Standard, Premium, Exclusive
+ - Référence : ORIGIN_BUSINESS_LOGIC.md §1.1
+
+- [ ] Checkout complet via Hyperswitch (F251)
+ - Stripe et PayPal configurés comme providers
+ - Référence : ORIGIN_BUSINESS_LOGIC.md §2.2
+
+- [ ] Téléchargements sécurisés (F252)
+ - URL signées S3 (expire en 24h)
+ - Limite de téléchargements par licence
+
+- [ ] Système de commissions automatique (F253)
+ - Commission déduite à la vente (15% creator, 10% premium)
+ - Référence : ORIGIN_BUSINESS_LOGIC.md §2.1
+
+- [ ] Paiements aux créateurs (F254)
+ - Payout hebdomadaire automatique si balance ≥ $50
+ - Référence : ORIGIN_BUSINESS_LOGIC.md §2.3
+
+- [ ] Codes promo (F255)
+ - Création et gestion par les créateurs et les admins
+
+**Critères d'acceptation**
+- [ ] Flow complet : achat → téléchargement → paiement créateur (E2E testé)
+- [ ] Commission correctement calculée et documentée
+- [ ] Remboursement possible sous 14 jours
+- [ ] Aucun dark pattern dans le flow d'achat (audit UX)
+
+---
+
+### v0.12.1 — Plans Premium & Abonnements (F001-F030 business)
+
+**Statut** : ⏳ TODO
+**Priorité** : P1
+**Durée estimée** : 4-5 jours
+**Prerequisite** : v0.12.0 complète
+
+**Tâches**
+
+- [ ] Plans d'abonnement (Free, Creator, Premium) via Hyperswitch
+ - Référence : ORIGIN_BUSINESS_LOGIC.md §1.1
+
+- [ ] Gestion des abonnements (upgrade, downgrade, cancel)
+- [ ] Factures automatiques (Stripe Invoicing)
+- [ ] Essai gratuit 14 jours pour le plan Premium
+
+**Critères d'acceptation**
+- [ ] Annulation sans friction (pas de dark patterns)
+- [ ] Accès au plan continue jusqu'à la fin de la période payée
+
+---
+
+### v0.12.2 — Distribution vers Plateformes (F501-F510)
+
+**Statut** : ⏳ TODO
+**Priorité** : P2
+**Durée estimée** : 5-6 jours
+**Prerequisite** : v0.12.1 complète (feature Premium)
+
+**Tâches**
+
+- [ ] Distribution vers Spotify, Apple Music, Deezer (F501)
+ - Via partenaire distribution (DistroKid API ou TuneCore)
+ - Disponible uniquement pour les plans Creator et Premium
+
+- [ ] Suivi de la distribution (F502)
+ - Statut de chaque plateforme (processing, live, rejected)
+
+- [ ] Revenus de streaming externe (F503)
+ - Import des royalties depuis les distributeurs
+
+**Critères d'acceptation**
+- [ ] Flow de soumission complète en moins de 5 minutes
+- [ ] L'artiste est notifié quand sa track est live sur Spotify
+
+---
+
+### v0.12.3 — Formation & Éducation (F276-F305)
+
+**Statut** : ⏳ TODO
+**Priorité** : P3
+**Durée estimée** : 6-8 jours
+**Prerequisite** : v0.12.0 complète
+
+**Tâches**
+
+- [ ] Upload et vente de cours vidéo (F276)
+- [ ] Lecteur vidéo HLS avec transcoding (F290)
+- [ ] Système de modules et leçons (F277)
+- [ ] Certificats de complétion (F278) — déclaratifs, pas gamifiés
+- [ ] Reviews de cours (F279)
+
+**Critères d'acceptation**
+- [ ] Cours vidéo en HLS multi-bitrate
+- [ ] Acheteur peut accéder aux cours à vie
+
+---
+
+### v0.12.4 — Performance & Scalabilité
+
+**Statut** : ⏳ TODO
+**Priorité** : P1
+**Durée estimée** : 3-4 jours
+**Prerequisite** : v0.12.2 complète
+
+**Tâches**
+
+- [ ] CDN pour les assets statiques et audio (CloudFront ou Bunny.net)
+- [ ] Cache Redis sur les endpoints fréquents (profils, tracks populaires)
+- [ ] Optimisation des requêtes PostgreSQL (EXPLAIN ANALYZE sur les slowest queries)
+- [ ] Load testing avec k6 (1000 utilisateurs simultanés)
+- [ ] Référence : ORIGIN_PERFORMANCE_TARGETS.md §8.4
+
+**Critères d'acceptation**
+- [ ] p95 < 100ms sur les endpoints API principaux
+- [ ] Démarrage du lecteur audio < 2 secondes
+- [ ] 1000 utilisateurs simultanés sans dégradation (k6 test)
+
+---
+
+### v0.12.5 — PWA & Expérience Mobile (F521-F535 revisités)
+
+**Statut** : ⏳ TODO
+**Priorité** : P2
+**Durée estimée** : 4-5 jours
+**Prerequisite** : v0.12.4 complète
+
+**Objectif**
+Stratégie PWA (Progressive Web App) en remplacement des apps natives Electron (Module 20 révisé).
+Référence : ORIGIN_REVISION_SUMMARY.md §6 Incohérence #2
+
+**Tâches**
+
+- [ ] Service Worker pour offline (lecture des tracks téléchargées)
+- [ ] Manifest PWA (installable sur mobile)
+- [ ] Push notifications web
+- [ ] Contrôles media dans la notification bar (Media Session API)
+- [ ] Design responsive optimisé mobile (SUMI design system)
+
+**Critères d'acceptation**
+- [ ] Score Lighthouse PWA ≥ 90
+- [ ] Player audio fonctionne hors ligne pour les tracks téléchargées
+- [ ] Installable sur Android et iOS (via "Ajouter à l'écran d'accueil")
+
+---
+
+### v0.12.6 — Pentest & Audit Sécurité Externe
+
+**Statut** : ⏳ TODO
+**Priorité** : P0 (avant v1.0)
+**Durée estimée** : 2-4 semaines (externe)
+**Prerequisite** : v0.12.4 complète
+
+**Tâches**
+
+- [ ] Sélectionner et mandater un prestataire de pentest
+- [ ] Pentest OWASP Top 10 + ASVS Level 2
+- [ ] Corriger tous les findings critiques et hauts
+- [ ] Référence : ORIGIN_SECURITY_FRAMEWORK.md §12.4, ORIGIN_REVISION_SUMMARY.md §7
+
+**Critères d'acceptation**
+- [ ] Rapport de pentest fourni par le prestataire
+- [ ] Aucun finding critique ou haut non résolu
+- [ ] Rapport de remédiation documenté
+
+---
+
+### v0.12.7 — Internationalisation (i18n)
+
+**Statut** : ⏳ TODO
+**Priorité** : P2
+**Durée estimée** : 3-4 jours
+**Prerequisite** : v0.12.5 complète
+
+**Tâches**
+
+- [ ] i18n framework (i18next ou FormatJS)
+- [ ] Traductions : Français, Anglais, Espagnol (langues initiales)
+- [ ] Détection automatique de la langue navigateur
+- [ ] Format des dates, nombres, monnaies selon locale
+
+**Critères d'acceptation**
+- [ ] Interface 100% traduite en FR/EN/ES
+- [ ] Commutation de langue sans rechargement
+
+---
+
+### v0.12.8 — Documentation & API Publique (F586-F600)
+
+**Statut** : ⏳ TODO
+**Priorité** : P2
+**Durée estimée** : 3-4 jours
+**Prerequisite** : v0.12.6 complète
+
+**Tâches**
+
+- [ ] Documentation API publique (OpenAPI / Swagger UI)
+- [ ] Gestion des clés API pour les développeurs tiers
+- [ ] Rate limiting spécifique à l'API publique
+- [ ] Référence : ORIGIN_FEATURES_REGISTRY.md F586-F600, ORIGIN_API_SPECIFICATION.md
+
+**Critères d'acceptation**
+- [ ] Documentation API navigable en ligne
+- [ ] Un développeur externe peut s'authentifier et consommer l'API avec sa clé
+
+---
+
+## 🏁 v1.0.0 — RELEASE STABLE
+
+**Statut** : ⏳ TODO
+**Prerequisite** : Toutes les versions P3.5, P4R, P5R, P6R complètes + pentest OK
+
+### GO/NO-GO Criteria
+
+Toutes les conditions suivantes doivent être remplies avant de taguer v1.0.0 :
+
+**Sécurité**
+- [ ] JWT RS256 en production
+- [ ] Aucun secret dans le repo git
+- [ ] Pentest externe validé (0 finding critique/haut ouvert)
+- [ ] RGPD : export et suppression de compte fonctionnels
+
+**Stabilité**
+- [ ] Uptime ≥ 99.9% sur les 30 derniers jours (staging ou beta)
+- [ ] Taux d'erreur 5xx < 0.1%
+- [ ] Aucun incident P0 non résolu
+
+**Performance**
+- [ ] p95 API < 100ms
+- [ ] Score Lighthouse Performance ≥ 85
+- [ ] Score Lighthouse Accessibility ≥ 90
+- [ ] Score Lighthouse PWA ≥ 90
+
+**Qualité**
+- [ ] Coverage tests ≥ 70% (Go + Rust)
+- [ ] 0 linting error
+- [ ] CI/CD verte depuis 2 semaines consécutives
+
+**Éthique (obligatoire)**
+- [ ] Audit UX anti-dark-patterns validé par un tiers
+- [ ] Aucune donnée comportementale n'est revendue ou partagée
+- [ ] Algorithm de découverte documenté et auditable
+- [ ] Politique de confidentialité à jour et conforme RGPD
+
+**Business**
+- [ ] Flux de paiement testé E2E en production (avec de vrais fonds)
+- [ ] Flux de payout créateur testé
+- [ ] Support accessible (email ou chat)
+
+---
+
+## 📊 TABLEAU DE SUIVI
+
+| Version | Nom | Phase | Statut | Durée est. | Prerequisite |
+|---------|-----|-------|--------|------------|--------------|
+| v0.9.1 | JWT Migration RS256 | P3.5 | ✅ DONE | 2-3j | — |
+| v0.9.2 | Sécurité Infrastructure | P3.5 | ⏳ TODO | 1-2j | v0.9.1 |
+| v0.9.3 | Toolchain & Environnement | P3.5 | ⏳ TODO | 1j | v0.9.1 |
+| v0.9.4 | Quality Gates CI/CD | P3.5 | ⏳ TODO | 2j | v0.9.3 |
+| v0.9.5 | Suppression Code Mort | P3.5 | ⏳ TODO | 1-2j | v0.9.4 |
+| v0.9.6 | Chat : Réactions & Mentions | P3.5 | ⏳ TODO | 3-4j | v0.9.2 |
+| v0.9.7 | Chat : Fichiers & Threads | P3.5 | ⏳ TODO | 3-4j | v0.9.6 |
+| v0.9.8 | Dette Technique Backend | P3.5 | ⏳ TODO | 3-4j | v0.9.4 |
+| v0.9.9 | Dette Technique Frontend | P3.5 | ⏳ TODO | 2-3j | v0.9.4 |
+| v0.10.0 | Feed Social Chronologique | P4R | ⏳ TODO | 4-5j | v0.9.9 |
+| v0.10.1 | Découverte Tags & Genres | P4R | ⏳ TODO | 3-4j | v0.10.0 |
+| v0.10.2 | Recherche Elasticsearch | P4R | ⏳ TODO | 4-5j | v0.10.1 |
+| v0.10.3 | Commentaires & Interactions | P4R | ⏳ TODO | 3-4j | v0.10.0 |
+| v0.10.4 | Playlists Collaboratives | P4R | ⏳ TODO | 3-4j | v0.10.0 |
+| v0.10.5 | Notifications Complètes | P4R | ⏳ TODO | 2-3j | v0.10.3 |
+| v0.10.6 | Livestreaming Basique | P4R | ⏳ TODO | 5-7j | v0.10.0 |
+| v0.10.7 | Collaboration Temps Réel | P4R | ⏳ TODO | 5-6j | v0.10.6 |
+| v0.10.8 | Portabilité Données RGPD | P4R | ⏳ TODO | 2-3j | v0.10.0 |
+| v0.11.0 | Analytics Créateur | P5R | ⏳ TODO | 4-5j | v0.10.3 |
+| v0.11.1 | Analytics Avancés | P5R | ⏳ TODO | 3-4j | v0.11.0 |
+| v0.11.2 | Modération Avancée | P5R | ⏳ TODO | 3-4j | v0.10.0 |
+| v0.11.3 | Administration Plateforme | P5R | ⏳ TODO | 3-4j | v0.11.2 |
+| v0.12.0 | Marketplace Complète | P6R | ⏳ TODO | 6-8j | v0.11.0 |
+| v0.12.1 | Plans Premium & Abonnements | P6R | ⏳ TODO | 4-5j | v0.12.0 |
+| v0.12.2 | Distribution Plateformes | P6R | ⏳ TODO | 5-6j | v0.12.1 |
+| v0.12.3 | Formation & Éducation | P6R | ⏳ TODO | 6-8j | v0.12.0 |
+| v0.12.4 | Performance & Scalabilité | P6R | ⏳ TODO | 3-4j | v0.12.2 |
+| v0.12.5 | PWA & Mobile | P6R | ⏳ TODO | 4-5j | v0.12.4 |
+| v0.12.6 | Pentest Externe | P6R | ⏳ TODO | 2-4 sem. | v0.12.4 |
+| v0.12.7 | Internationalisation | P6R | ⏳ TODO | 3-4j | v0.12.5 |
+| v0.12.8 | Documentation & API Publique | P6R | ⏳ TODO | 3-4j | v0.12.6 |
+| **v1.0.0** | **Release Stable** | — | ⏳ TODO | — | Tout + pentest |
+
+---
+
+## 📐 INSTRUCTIONS POUR CURSOR
+
+> Quand tu reçois "implémente la prochaine version", exécute les étapes suivantes :
+
+### Étape 1 : Identifier la prochaine version
+Chercher dans ce fichier la première version avec **Statut : ⏳ TODO** dans l'ordre du tableau de suivi.
+
+### Étape 2 : Vérifier les prerequisites
+Confirmer que toutes les versions listées dans "Prerequisite" ont le statut ✅ DONE.
+Si non : signaler le blocage et ne pas continuer.
+
+### Étape 3 : Lire les références ORIGIN
+Lire les fichiers ORIGIN mentionnés dans les tâches de la version (dans le dossier ORIGIN/ du repo).
+Ces fichiers contiennent les spécifications détaillées, les ADR, et les standards éthiques.
+
+### Étape 4 : Implémenter
+Implémenter toutes les tâches de la version, en suivant :
+- `ORIGIN/ORIGIN_CODE_STANDARDS.md` pour les conventions
+- `ORIGIN/ORIGIN_FEATURE_VALIDATION_STRATEGY.md` pour la checklist de validation
+- `ORIGIN/ORIGIN_ERROR_PATTERNS.md` et `ORIGIN_ERROR_PREVENTION_GUIDE.md` pour éviter les patterns problématiques
+- `ORIGIN/ORIGIN_UI_UX_SYSTEM.md` §13 anti-patterns et §14 patterns positifs pour le frontend
+
+### Étape 5 : Valider
+Pour chaque tâche implémentée :
+- Exécuter les tests (`make test`)
+- Vérifier les critères d'acceptation listés dans ce fichier
+- Vérifier la checklist ORIGIN_FEATURE_VALIDATION_STRATEGY.md
+
+### Étape 6 : Mettre à jour ce fichier
+Une fois la version complète et validée :
+- Changer le statut de `⏳ TODO` à `✅ DONE`
+- Ajouter la date de completion : `**Complété le** : YYYY-MM-DD`
+- Mettre à jour le tableau de suivi
+
+### Étape 7 : Créer le tag git
+```bash
+git tag -a v0.X.Y -m "Version v0.X.Y : [Nom de la version]"
+git push origin v0.X.Y
+```
+
+---
+
+## 🚫 RÈGLES IMMUABLES POUR CURSOR
+
+1. **Ne jamais implémenter de code AI/ML** — les modules F456-F470 sont supprimés définitivement
+2. **Ne jamais implémenter de code blockchain/Web3** — les modules F491-F500 sont supprimés définitivement
+3. **Ne jamais implémenter de gamification** (XP, streaks, leaderboards) — les modules F536-F550 sont supprimés définitivement
+4. **Ne jamais exposer de métriques de popularité publiquement** — les likes et plays sont privés (créateur uniquement)
+5. **Ne jamais implémenter de dark patterns UX** — référence : ORIGIN_UI_UX_SYSTEM.md §13
+6. **Ne jamais modifier les fichiers ORIGIN/** — ils sont la référence, pas le code
+7. **Ne jamais déployer en production sans que les critères d'acceptation soient vérifiés**
+8. **Si une tâche semble contredire un fichier ORIGIN, la priorité va au fichier ORIGIN** — signaler l'incohérence
+
+---
+
+*Document versionné. Toute modification de ce fichier doit être commitée avec le message : `docs: update VEZA_VERSIONS_ROADMAP [raison]`*
+
+*Référence architecture : ORIGIN/ORIGIN_MASTER_ARCHITECTURE.md*
+*Référence éthique : ORIGIN/ORIGIN_REVISION_SUMMARY.md*
+*Référence sécurité : ORIGIN/ORIGIN_SECURITY_FRAMEWORK.md*
diff --git a/apps/web/src/types/generated/api.ts b/apps/web/src/types/generated/api.ts
index 402c6f10f..fd076fc51 100644
--- a/apps/web/src/types/generated/api.ts
+++ b/apps/web/src/types/generated/api.ts
@@ -4729,7 +4729,7 @@ export const TrackApiAxiosParamCreator = function (configuration?: Configuration
/**
* Get remaining upload quota for the user
* @summary Get Upload Quota
- * @param {string} id User ID (optional, defaults to current user)
+ * @param {string} id User ID or \'me\' for current user
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@@ -4882,7 +4882,7 @@ export const TrackApiFp = function(configuration?: Configuration) {
/**
* Get remaining upload quota for the user
* @summary Get Upload Quota
- * @param {string} id User ID (optional, defaults to current user)
+ * @param {string} id User ID or \'me\' for current user
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@@ -4972,7 +4972,7 @@ export const TrackApiFactory = function (configuration?: Configuration, basePath
/**
* Get remaining upload quota for the user
* @summary Get Upload Quota
- * @param {string} id User ID (optional, defaults to current user)
+ * @param {string} id User ID or \'me\' for current user
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@@ -5049,7 +5049,7 @@ export interface TrackApiInterface {
/**
* Get remaining upload quota for the user
* @summary Get Upload Quota
- * @param {string} id User ID (optional, defaults to current user)
+ * @param {string} id User ID or \'me\' for current user
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@@ -5133,7 +5133,7 @@ export class TrackApi extends BaseAPI implements TrackApiInterface {
/**
* Get remaining upload quota for the user
* @summary Get Upload Quota
- * @param {string} id User ID (optional, defaults to current user)
+ * @param {string} id User ID or \'me\' for current user
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
diff --git a/apps/web/src/types/generated/docs/TrackApi.md b/apps/web/src/types/generated/docs/TrackApi.md
index 496beed93..8a6613f83 100644
--- a/apps/web/src/types/generated/docs/TrackApi.md
+++ b/apps/web/src/types/generated/docs/TrackApi.md
@@ -313,7 +313,7 @@ import {
const configuration = new Configuration();
const apiInstance = new TrackApi(configuration);
-let id: string; //User ID (optional, defaults to current user) (default to undefined)
+let id: string; //User ID or \'me\' for current user (default to undefined)
const { status, data } = await apiInstance.tracksQuotaIdGet(
id
@@ -324,7 +324,7 @@ const { status, data } = await apiInstance.tracksQuotaIdGet(
|Name | Type | Description | Notes|
|------------- | ------------- | ------------- | -------------|
-| **id** | [**string**] | User ID (optional, defaults to current user) | defaults to undefined|
+| **id** | [**string**] | User ID or \'me\' for current user | defaults to undefined|
### Return type
diff --git a/docs/ENV_VARIABLES.md b/docs/ENV_VARIABLES.md
new file mode 100644
index 000000000..3a571f91b
--- /dev/null
+++ b/docs/ENV_VARIABLES.md
@@ -0,0 +1,96 @@
+# Variables d'environnement Veza
+
+> Référence complète des variables d'environnement utilisées par la plateforme Veza.
+> v0.9.1 : Migration JWT RS256 (JWT_PRIVATE_KEY_PATH, JWT_PUBLIC_KEY_PATH).
+>
+> Voir aussi : [.env.example](../.env.example), [veza-backend-api/.env.template](../veza-backend-api/.env.template), [veza-stream-server/.env.example](../veza-stream-server/.env.example).
+
+---
+
+## Backend API (veza-backend-api)
+
+### Authentification JWT (v0.9.1 RS256)
+
+| Variable | Description | Type | Requis | Valeur par défaut | Exemple |
+|----------|--------------|------|--------|------------------|---------|
+| `JWT_PRIVATE_KEY_PATH` | Chemin vers la clé privée RSA (signature) | string | Oui (prod) | — | `/secrets/jwt-private.pem` |
+| `JWT_PUBLIC_KEY_PATH` | Chemin vers la clé publique RSA (vérification) | string | Oui (prod) | — | `/secrets/jwt-public.pem` |
+| `JWT_SECRET` | Secret HS256 (déprécié, fallback dev uniquement) | string | Si pas RS256 | — | min 32 chars |
+| `JWT_ISSUER` | Issuer claim (access/refresh tokens) | string | Non | `veza-api` | `veza-api` |
+| `JWT_AUDIENCE` | Audience claim | string | Non | `veza-platform` | `veza-platform` |
+| `JWT_ACCESS_TOKEN_DURATION` | Durée access token | duration | Non | `15m` | `5m`, `1h` |
+| `JWT_REFRESH_TOKEN_DURATION` | Durée refresh token | duration | Non | `30d` | `7d`, `14d` |
+
+**Génération des clés RS256 :**
+```bash
+scripts/generate-jwt-keys.sh
+# ou manuellement :
+openssl genrsa -out jwt-private.pem 2048
+openssl rsa -in jwt-private.pem -pubout -out jwt-public.pem
+```
+
+### Base de données
+
+| Variable | Description | Type | Requis | Valeur par défaut | Exemple |
+|----------|--------------|------|--------|------------------|---------|
+| `DATABASE_URL` | URL connexion PostgreSQL | string | Oui | — | `postgres://veza:password@localhost:5432/veza?sslmode=disable` |
+| `DATABASE_READ_URL` | URL réplica lecture (optionnel) | string | Non | — | `postgres://veza:password@replica:5432/veza` |
+
+### Redis
+
+| Variable | Description | Type | Requis | Valeur par défaut | Exemple |
+|----------|--------------|------|--------|------------------|---------|
+| `REDIS_URL` | URL connexion Redis | string | Oui | — | `redis://localhost:6379` |
+| `REDIS_ENABLE` | Activer Redis | bool | Non | `true` | `true`, `false` |
+
+### CORS & Domaine
+
+| Variable | Description | Type | Requis | Valeur par défaut | Exemple |
+|----------|--------------|------|--------|------------------|---------|
+| `APP_DOMAIN` | Domaine applicatif | string | Non | `veza.fr` | `veza.fr`, `app.veza.com` |
+| `CORS_ALLOWED_ORIGINS` | Origines CORS autorisées | string | Oui | — | `http://veza.fr:5173` |
+| `FRONTEND_URL` | URL frontend (OAuth, reset) | string | Non | `http://localhost:5173` | `https://app.veza.com` |
+
+### Autres services
+
+| Variable | Description | Type | Requis | Valeur par défaut | Exemple |
+|----------|--------------|------|--------|------------------|---------|
+| `STREAM_SERVER_URL` | URL stream server | string | Non | `http://veza.fr:8082` | `http://stream:8082` |
+| `STREAM_SERVER_INTERNAL_API_KEY` | Clé API interne transcode | string | Non | — | secret partagé |
+| `CHAT_SERVER_URL` | URL chat (legacy) | string | Non | `http://veza.fr:8081` | — |
+| `RABBITMQ_URL` | URL RabbitMQ | string | Non | — | `amqp://veza:password@localhost:5672/` |
+
+---
+
+## Stream Server (veza-stream-server)
+
+### JWT (v0.9.1 RS256)
+
+| Variable | Description | Type | Requis | Valeur par défaut | Exemple |
+|----------|--------------|------|--------|------------------|---------|
+| `JWT_PUBLIC_KEY_PATH` | Chemin clé publique RSA (vérification) | string | Oui (prod) | — | `/secrets/jwt-public.pem` |
+| `JWT_SECRET` | Secret HS256 (phase transition uniquement) | string | Si pas RS256 | — | min 32 chars |
+| `JWT_EXPIRATION` | TTL tokens (secondes) | int | Non | `3600` | `300`, `3600` |
+
+**Remarque :** Le stream server valide les tokens émis par le backend. Il utilise la clé publique partagée (JWT_PUBLIC_KEY_PATH) pour RS256.
+
+---
+
+## Variables communes (veza-common)
+
+Services Rust utilisant veza-common (config_rust JwtConfig) :
+
+| Variable | Description | Type | Requis | Valeur par défaut | Exemple |
+|----------|--------------|------|--------|------------------|---------|
+| `JWT_SECRET` | Secret JWT | string | Oui | — | min 32 chars (VEZA-SEC-001) |
+| `JWT_ISSUER` | Issuer | string | Non | `veza-api` | `veza-api` |
+| `JWT_AUDIENCE` | Audience | string | Non | `veza-platform` | `veza-platform` |
+
+---
+
+## Checklist de démarrage
+
+1. Copier `.env.example` vers `.env` (racine) et `veza-backend-api/.env.template` vers `veza-backend-api/.env`
+2. Pour RS256 : exécuter `scripts/generate-jwt-keys.sh` et configurer `JWT_PRIVATE_KEY_PATH`, `JWT_PUBLIC_KEY_PATH`
+3. Configurer `DATABASE_URL`, `REDIS_URL`, `CORS_ALLOWED_ORIGINS`
+4. En production : ne jamais commiter `.env` ni les fichiers `.pem`
diff --git a/docs/SECRETS_AUDIT.md b/docs/SECRETS_AUDIT.md
new file mode 100644
index 000000000..2a3f7f2ac
--- /dev/null
+++ b/docs/SECRETS_AUDIT.md
@@ -0,0 +1,36 @@
+# Audit des secrets (TASK-SEC-002)
+
+v0.9.1 — Procédure d'audit des secrets exposés.
+
+## Outils recommandés
+
+```bash
+# Gitleaks (recommandé)
+gitleaks detect --source . --verbose --report-path gitleaks-report.json
+
+# TruffleHog
+truffleHog --regex --entropy high .
+```
+
+## Vérifications manuelles
+
+1. Aucun fichier `.env` ou `.env.*` (hors `.example`) ne doit être commité
+2. Aucun fichier `*.pem` contenant des clés privées
+3. Aucun secret hardcodé (JWT, Stripe, OAuth, DB password)
+4. `.gitignore` couvre : `.env`, `.env.*`, `jwt-private.pem`, `jwt-public.pem`
+
+## Rotation des clés si compromise
+
+En cas de findings :
+
+1. **JWT** : Régénérer clés RSA (`scripts/generate-jwt-keys.sh`), déployer, invalider tokens (migration 123)
+2. **Stripe** : Régénérer dans Dashboard
+3. **OAuth** : Régénérer client secret chez le provider
+4. **Database** : Changer mot de passe, mettre à jour DATABASE_URL
+
+## État v0.9.1
+
+- veza-common : plus de secret par défaut (VEZA-SEC-001 corrigé)
+- Backend : RS256 préféré, JWT_SECRET fallback dev uniquement
+- Stream server : JWT_PUBLIC_KEY_PATH ou JWT_SECRET
+- `.gitignore` : jwt-private.pem, jwt-public.pem
diff --git a/scripts/generate-jwt-keys.sh b/scripts/generate-jwt-keys.sh
new file mode 100755
index 000000000..6c1def66b
--- /dev/null
+++ b/scripts/generate-jwt-keys.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+# Generate RSA key pair for JWT RS256 (v0.9.1)
+# Usage: ./scripts/generate-jwt-keys.sh [output_dir]
+# Output: jwt-private.pem, jwt-public.pem (2048-bit RSA)
+# NEVER commit these files to Git.
+
+set -e
+
+OUTPUT_DIR="${1:-.}"
+PRIVATE="${OUTPUT_DIR}/jwt-private.pem"
+PUBLIC="${OUTPUT_DIR}/jwt-public.pem"
+
+echo "Generating RSA 2048-bit key pair for JWT RS256..."
+openssl genrsa -out "$PRIVATE" 2048
+openssl rsa -in "$PRIVATE" -pubout -out "$PUBLIC"
+
+echo "Keys generated:"
+echo " Private: $PRIVATE"
+echo " Public: $PUBLIC"
+echo ""
+echo "Set in .env:"
+echo " JWT_PRIVATE_KEY_PATH=$PRIVATE"
+echo " JWT_PUBLIC_KEY_PATH=$PUBLIC"
+echo ""
+echo "WARNING: Never commit .pem files to Git!"
diff --git a/veza-backend-api/.env.template b/veza-backend-api/.env.template
index 902d3e4c3..659077d2b 100644
--- a/veza-backend-api/.env.template
+++ b/veza-backend-api/.env.template
@@ -26,12 +26,14 @@ DATABASE_MAX_OPEN_CONNS=25
DATABASE_MAX_IDLE_CONNS=5
DATABASE_CONN_MAX_LIFETIME=5m
-# --- JWT & AUTHENTICATION (REQUIRED) ---
-# CRITICAL: Must be at least 32 characters in production
-# Generate with: openssl rand -base64 32
+# --- JWT & AUTHENTICATION (v0.9.1 RS256) ---
+# PREFERRED: RS256 with RSA keys (generate with scripts/generate-jwt-keys.sh)
+# JWT_PRIVATE_KEY_PATH=/path/to/jwt-private.pem
+# JWT_PUBLIC_KEY_PATH=/path/to/jwt-public.pem
+# FALLBACK (dev only): JWT_SECRET must be at least 32 characters
JWT_SECRET=dev-secret-key-minimum-32-characters-long-for-testing-only
JWT_ISSUER=veza-api
-JWT_AUDIENCE=veza-app
+JWT_AUDIENCE=veza-platform
JWT_ACCESS_TOKEN_DURATION=15m
JWT_REFRESH_TOKEN_DURATION=30d
diff --git a/veza-backend-api/internal/api/routes_auth.go b/veza-backend-api/internal/api/routes_auth.go
index 77c71f384..7a4c6654a 100644
--- a/veza-backend-api/internal/api/routes_auth.go
+++ b/veza-backend-api/internal/api/routes_auth.go
@@ -21,7 +21,7 @@ func (r *APIRouter) setupAuthRoutes(router *gin.RouterGroup) error {
passwordValidator := validators.NewPasswordValidator()
passwordService := services.NewPasswordService(r.db, r.logger)
passwordResetService := services.NewPasswordResetService(r.db, r.logger)
- jwtService, err := services.NewJWTService(r.config.JWTSecret, r.config.JWTIssuer, r.config.JWTAudience)
+ jwtService, err := services.NewJWTService(r.config.JWTPrivateKeyPath, r.config.JWTPublicKeyPath, r.config.JWTSecret, r.config.JWTIssuer, r.config.JWTAudience)
if err != nil {
return fmt.Errorf("failed to initialize JWT service: %w", err)
}
diff --git a/veza-backend-api/internal/config/config.go b/veza-backend-api/internal/config/config.go
index cde20b6bf..2c9503701 100644
--- a/veza-backend-api/internal/config/config.go
+++ b/veza-backend-api/internal/config/config.go
@@ -66,7 +66,9 @@ type Config struct {
Env string // Environnement: development, test, production (P0-SECURITY)
AppPort int // Port pour le serveur HTTP (T0031)
AppDomain string // Domaine applicatif (APP_DOMAIN) — single source of truth pour URLs & CORS
- JWTSecret string
+ JWTSecret string // HS256 fallback (dev only)
+ JWTPrivateKeyPath string // v0.9.1 RS256: path to RSA private key
+ JWTPublicKeyPath string // v0.9.1 RS256: path to RSA public key
JWTIssuer string // T0204: Issuer claim validation (P1-SECURITY)
JWTAudience string // T0204: Audience claim validation (P1-SECURITY)
ChatJWTSecret string // Secret pour les tokens WebSocket Chat
@@ -176,12 +178,18 @@ func ValidateRequiredEnvironmentVariables(env string) error {
var errors []string
// Variables requises dans tous les environnements
- requiredVars := []string{
- "JWT_SECRET",
- "DATABASE_URL",
+ requiredVars := []string{"DATABASE_URL"}
+
+ // v0.9.1: JWT config — require either RS256 keys OR JWT_SECRET (dev fallback)
+ jwtPrivatePath := os.Getenv("JWT_PRIVATE_KEY_PATH")
+ jwtPublicPath := os.Getenv("JWT_PUBLIC_KEY_PATH")
+ jwtSecret := os.Getenv("JWT_SECRET")
+ hasRS256 := jwtPrivatePath != "" && jwtPublicPath != ""
+ hasHS256 := jwtSecret != ""
+ if !hasRS256 && !hasHS256 {
+ missingVars = append(missingVars, "JWT_PRIVATE_KEY_PATH+JWT_PUBLIC_KEY_PATH or JWT_SECRET")
}
- // Vérifier les variables requises
for _, varName := range requiredVars {
value := os.Getenv(varName)
if value == "" {
@@ -280,11 +288,10 @@ func NewConfig() (*Config, error) {
maxConcurrentUploads := getEnvInt("MAX_CONCURRENT_UPLOADS", 10) // 10 par défaut
// Configuration depuis les variables d'environnement
- // SECURITY: JWT_SECRET est REQUIS - pas de valeur par défaut pour éviter les failles de sécurité
- jwtSecret, err := getEnvRequired("JWT_SECRET")
- if err != nil {
- return nil, err
- }
+ // v0.9.1: JWT — RS256 (prefer) or JWT_SECRET (dev fallback)
+ jwtPrivateKeyPath := getEnv("JWT_PRIVATE_KEY_PATH", "")
+ jwtPublicKeyPath := getEnv("JWT_PUBLIC_KEY_PATH", "")
+ jwtSecret := getEnv("JWT_SECRET", "")
databaseURL, err := getEnvRequired("DATABASE_URL")
if err != nil {
@@ -296,12 +303,14 @@ func NewConfig() (*Config, error) {
config := &Config{
Env: env, // Store environment for validation (P0-SECURITY)
- AppPort: appPort,
- AppDomain: appDomain,
- JWTSecret: jwtSecret,
- JWTIssuer: getEnv("JWT_ISSUER", "veza-api"),
- JWTAudience: getEnv("JWT_AUDIENCE", "veza-app"),
- ChatJWTSecret: getEnv("CHAT_JWT_SECRET", jwtSecret), // Fallback to main JWT secret if not set
+ AppPort: appPort,
+ AppDomain: appDomain,
+ JWTSecret: jwtSecret,
+ JWTPrivateKeyPath: jwtPrivateKeyPath,
+ JWTPublicKeyPath: jwtPublicKeyPath,
+ JWTIssuer: getEnv("JWT_ISSUER", "veza-api"),
+ JWTAudience: getEnv("JWT_AUDIENCE", "veza-platform"),
+ ChatJWTSecret: getEnv("CHAT_JWT_SECRET", jwtSecret),
RedisURL: getEnv("REDIS_URL", "redis://"+appDomain+":6379"),
RedisEnable: getEnvBool("REDIS_ENABLE", true),
// SECURITY: DATABASE_URL est REQUIS - contient des credentials sensibles
diff --git a/veza-backend-api/internal/config/config_test.go b/veza-backend-api/internal/config/config_test.go
index ad84635cf..ed855d7e4 100644
--- a/veza-backend-api/internal/config/config_test.go
+++ b/veza-backend-api/internal/config/config_test.go
@@ -334,9 +334,11 @@ func TestNewConfig_RequiresJWTSecret(t *testing.T) {
}
}()
- // Supprimer JWT_SECRET - devrait causer une erreur
+ // Supprimer JWT config - ni RS256 ni HS256 (devrait causer une erreur)
os.Unsetenv("JWT_SECRET")
- // Définir DATABASE_URL pour éviter une erreur sur cette variable (on teste seulement JWT_SECRET)
+ os.Unsetenv("JWT_PRIVATE_KEY_PATH")
+ os.Unsetenv("JWT_PUBLIC_KEY_PATH")
+ // Définir DATABASE_URL pour éviter une erreur sur cette variable (on teste seulement JWT config)
os.Setenv("DATABASE_URL", "postgresql://test:test@localhost:5432/test_db")
// MOD-P0-002: getEnvRequired() returns error, not panic - verify error is returned
@@ -578,10 +580,9 @@ func TestNewConfig_JWTSecretTooShort(t *testing.T) {
os.Setenv("RABBITMQ_ENABLE", "false")
// MOD-P0-002: NewConfig() doit retourner une erreur car JWT_SECRET est trop court
- // La validation Validate() est appelée dans NewConfig() et doit échouer
+ // La validation dans NewJWTService rejette les secrets < 32 chars
_, err := NewConfig()
require.Error(t, err, "NewConfig should return error when JWT_SECRET is too short")
- assert.Contains(t, err.Error(), "JWT_SECRET validation failed", "Error message should mention JWT_SECRET validation")
assert.Contains(t, err.Error(), "32", "Error message should mention minimum length of 32")
}
diff --git a/veza-backend-api/internal/config/services_init.go b/veza-backend-api/internal/config/services_init.go
index 00b9d572a..7c44dc052 100644
--- a/veza-backend-api/internal/config/services_init.go
+++ b/veza-backend-api/internal/config/services_init.go
@@ -63,8 +63,8 @@ func (c *Config) initServices() error {
// Service de permissions
c.PermissionService = services.NewPermissionService(c.Database.GormDB)
- // JWT Service
- c.JWTService, err = services.NewJWTService(c.JWTSecret, c.JWTIssuer, c.JWTAudience)
+ // JWT Service (v0.9.1: RS256 prefer, HS256 dev fallback)
+ c.JWTService, err = services.NewJWTService(c.JWTPrivateKeyPath, c.JWTPublicKeyPath, c.JWTSecret, c.JWTIssuer, c.JWTAudience)
if err != nil {
return err
}
diff --git a/veza-backend-api/internal/handlers/auth_handler_test.go b/veza-backend-api/internal/handlers/auth_handler_test.go
index 89b4d4d6b..68fbe524a 100644
--- a/veza-backend-api/internal/handlers/auth_handler_test.go
+++ b/veza-backend-api/internal/handlers/auth_handler_test.go
@@ -84,7 +84,7 @@ func setupAuthTestRouter(t *testing.T, authMiddlewares ...gin.HandlerFunc) (*gin
emailValidator := validators.NewEmailValidator(db)
passwordValidator := validators.NewPasswordValidator()
passwordService := services.NewPasswordService(dbWrapper, logger)
- jwtService, err := services.NewJWTService("test-secret-key-must-be-32-chars-long", "test-issuer", "test-audience")
+ jwtService, err := services.NewJWTService("", "", "test-secret-key-must-be-32-chars-long", "test-issuer", "test-audience")
require.NoError(t, err)
refreshTokenService := services.NewRefreshTokenService(db)
emailVerificationService := services.NewEmailVerificationService(dbWrapper, logger)
diff --git a/veza-backend-api/internal/handlers/auth_integration_test.go b/veza-backend-api/internal/handlers/auth_integration_test.go
index fc1ff55fd..aeda648b1 100644
--- a/veza-backend-api/internal/handlers/auth_integration_test.go
+++ b/veza-backend-api/internal/handlers/auth_integration_test.go
@@ -81,7 +81,7 @@ func setupAuthIntegrationTestRouter(t *testing.T) (*gin.Engine, *auth.AuthServic
emailValidator := validators.NewEmailValidator(db)
passwordValidator := validators.NewPasswordValidator()
passwordService := services.NewPasswordService(dbWrapper, logger)
- jwtService, err := services.NewJWTService("test-secret-key-must-be-32-chars-long", "test-issuer", "test-audience")
+ jwtService, err := services.NewJWTService("", "", "test-secret-key-must-be-32-chars-long", "test-issuer", "test-audience")
require.NoError(t, err)
refreshTokenService := services.NewRefreshTokenService(db)
emailVerificationService := services.NewEmailVerificationService(dbWrapper, logger)
diff --git a/veza-backend-api/internal/middleware/auth_middleware_test.go b/veza-backend-api/internal/middleware/auth_middleware_test.go
index de68ebfab..9a0e6f724 100644
--- a/veza-backend-api/internal/middleware/auth_middleware_test.go
+++ b/veza-backend-api/internal/middleware/auth_middleware_test.go
@@ -81,7 +81,7 @@ func setupTestJWTService(t *testing.T) *services.JWTService {
issuer := "veza-api"
audience := "veza-app"
- jwtService, err := services.NewJWTService(testJWTSecret, issuer, audience)
+ jwtService, err := services.NewJWTService("", "", testJWTSecret, issuer, audience)
require.NoError(t, err)
return jwtService
}
diff --git a/veza-backend-api/internal/services/jwt_service.go b/veza-backend-api/internal/services/jwt_service.go
index a78d5f60e..65e51b708 100644
--- a/veza-backend-api/internal/services/jwt_service.go
+++ b/veza-backend-api/internal/services/jwt_service.go
@@ -1,7 +1,11 @@
package services
import (
+ "crypto/rsa"
+ "crypto/x509"
+ "encoding/pem"
"fmt"
+ "os"
"time"
"veza-backend-api/internal/models"
@@ -11,46 +15,129 @@ import (
)
type JWTService struct {
+ // RS256 (v0.9.1): prefer if set
+ privateKey *rsa.PrivateKey
+ publicKey *rsa.PublicKey
+ // HS256 fallback (dev only)
secretKey []byte
- issuer string
- audience string
- Config *models.JWTConfig
+ useRS256 bool
+
+ issuer string
+ audience string
+ Config *models.JWTConfig
}
-func NewJWTService(secret, issuer, audience string) (*JWTService, error) {
- if secret == "" {
- return nil, fmt.Errorf("JWT secret is required")
- }
- // SEC-005: Enforce minimum secret length to prevent brute-force
- if len(secret) < 32 {
- return nil, fmt.Errorf("JWT secret must be at least 32 characters")
- }
+// NewJWTService creates a JWT service. Prefers RS256 if privateKeyPath and publicKeyPath are set.
+// Falls back to HS256 with secret for development (secret must be min 32 chars).
+func NewJWTService(privateKeyPath, publicKeyPath, secret, issuer, audience string) (*JWTService, error) {
if issuer == "" {
issuer = "veza-api"
}
if audience == "" {
- audience = "veza-app"
+ audience = "veza-platform"
}
- // Default config - SEC-006: Reduced TTLs for improved security
config := &models.JWTConfig{
AccessTokenTTL: 5 * time.Minute,
- RefreshTokenTTL: 14 * 24 * time.Hour, // 14 days (was 30)
- RememberMeRefreshTokenTTL: 30 * 24 * time.Hour, // 30 days (was 90)
+ RefreshTokenTTL: 14 * 24 * time.Hour,
+ RememberMeRefreshTokenTTL: 30 * 24 * time.Hour,
}
+ // Prefer RS256 if both key paths are set
+ if privateKeyPath != "" && publicKeyPath != "" {
+ privateKey, err := loadRSAPrivateKey(privateKeyPath)
+ if err != nil {
+ return nil, fmt.Errorf("load JWT private key: %w", err)
+ }
+ publicKey, err := loadRSAPublicKey(publicKeyPath)
+ if err != nil {
+ return nil, fmt.Errorf("load JWT public key: %w", err)
+ }
+ return &JWTService{
+ privateKey: privateKey,
+ publicKey: publicKey,
+ useRS256: true,
+ issuer: issuer,
+ audience: audience,
+ Config: config,
+ }, nil
+ }
+
+ // Fallback to HS256 (dev)
+ if secret == "" {
+ return nil, fmt.Errorf("JWT configuration required: set JWT_PRIVATE_KEY_PATH and JWT_PUBLIC_KEY_PATH (RS256), or JWT_SECRET (HS256 dev fallback)")
+ }
+ if len(secret) < 32 {
+ return nil, fmt.Errorf("JWT secret must be at least 32 characters")
+ }
return &JWTService{
secretKey: []byte(secret),
+ useRS256: false,
issuer: issuer,
audience: audience,
Config: config,
}, nil
}
+func loadRSAPrivateKey(path string) (*rsa.PrivateKey, error) {
+ data, err := os.ReadFile(path)
+ if err != nil {
+ return nil, fmt.Errorf("read private key file: %w", err)
+ }
+ block, _ := pem.Decode(data)
+ if block == nil {
+ return nil, fmt.Errorf("failed to decode PEM block")
+ }
+ key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
+ if err != nil {
+ // Try PKCS8
+ k, err2 := x509.ParsePKCS8PrivateKey(block.Bytes)
+ if err2 != nil {
+ return nil, fmt.Errorf("parse private key: %w", err)
+ }
+ var ok bool
+ key, ok = k.(*rsa.PrivateKey)
+ if !ok {
+ return nil, fmt.Errorf("private key is not RSA")
+ }
+ }
+ return key, nil
+}
+
+func loadRSAPublicKey(path string) (*rsa.PublicKey, error) {
+ data, err := os.ReadFile(path)
+ if err != nil {
+ return nil, fmt.Errorf("read public key file: %w", err)
+ }
+ block, _ := pem.Decode(data)
+ if block == nil {
+ return nil, fmt.Errorf("failed to decode PEM block")
+ }
+ pub, err := x509.ParsePKIXPublicKey(block.Bytes)
+ if err != nil {
+ return nil, fmt.Errorf("parse public key: %w", err)
+ }
+ key, ok := pub.(*rsa.PublicKey)
+ if !ok {
+ return nil, fmt.Errorf("public key is not RSA")
+ }
+ return key, nil
+}
+
func (s *JWTService) GetConfig() *models.JWTConfig {
return s.Config
}
+func (s *JWTService) sign(claims jwt.Claims) (string, error) {
+ var token *jwt.Token
+ if s.useRS256 {
+ token = jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
+ return token.SignedString(s.privateKey)
+ }
+ token = jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
+ return token.SignedString(s.secretKey)
+}
+
func (s *JWTService) GenerateAccessToken(user *models.User) (string, error) {
claims := models.CustomClaims{
UserID: user.ID,
@@ -67,18 +154,16 @@ func (s *JWTService) GenerateAccessToken(user *models.User) (string, error) {
ID: uuid.NewString(),
},
}
-
- token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
- return token.SignedString(s.secretKey)
+ return s.sign(&claims)
}
func (s *JWTService) GenerateRefreshToken(user *models.User) (string, error) {
claims := models.CustomClaims{
UserID: user.ID,
TokenVersion: user.TokenVersion,
- IsRefresh: true, // Mark as refresh token
+ IsRefresh: true,
TokenType: "refresh",
- TokenFamily: uuid.NewString(), // Nouvelle famille de token
+ TokenFamily: uuid.NewString(),
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(s.Config.RefreshTokenTTL)),
IssuedAt: jwt.NewNumericDate(time.Now()),
@@ -87,25 +172,18 @@ func (s *JWTService) GenerateRefreshToken(user *models.User) (string, error) {
ID: uuid.NewString(),
},
}
-
- token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
- return token.SignedString(s.secretKey)
+ return s.sign(&claims)
}
-// GenerateTokenPair génère une paire de tokens (access + refresh) en une seule opération
func (s *JWTService) GenerateTokenPair(user *models.User) (*models.TokenPair, error) {
- // Generate access token
accessToken, err := s.GenerateAccessToken(user)
if err != nil {
return nil, fmt.Errorf("failed to generate access token: %w", err)
}
-
- // Generate refresh token
refreshToken, err := s.GenerateRefreshToken(user)
if err != nil {
return nil, fmt.Errorf("failed to generate refresh token: %w", err)
}
-
return &models.TokenPair{
AccessToken: accessToken,
RefreshToken: refreshToken,
@@ -113,16 +191,21 @@ func (s *JWTService) GenerateTokenPair(user *models.User) (*models.TokenPair, er
}, nil
}
-// VerifyToken valide et parse un token JWT
func (s *JWTService) VerifyToken(tokenString string) (*models.CustomClaims, error) {
return s.ValidateToken(tokenString)
}
-// ValidateToken valide un token JWT et retourne les claims
func (s *JWTService) ValidateToken(tokenString string) (*models.CustomClaims, error) {
- // Parse avec validation des claims standards (exp, iat, nbf) ET custom (iss, aud)
token, err := jwt.ParseWithClaims(tokenString, &models.CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
- // Validation stricte de l'algorithme (MOD-P2-002)
+ if s.useRS256 {
+ if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
+ return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
+ }
+ if token.Method.Alg() != "RS256" {
+ return nil, fmt.Errorf("invalid signing algorithm: %v, expected RS256", token.Method.Alg())
+ }
+ return s.publicKey, nil
+ }
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
@@ -131,35 +214,27 @@ func (s *JWTService) ValidateToken(tokenString string) (*models.CustomClaims, er
}
return s.secretKey, nil
},
- // Options de validation stricte
jwt.WithIssuer(s.issuer),
jwt.WithAudience(s.audience),
jwt.WithExpirationRequired(),
)
-
if err != nil {
return nil, fmt.Errorf("failed to parse token: %w", err)
}
-
if claims, ok := token.Claims.(*models.CustomClaims); ok && token.Valid {
return claims, nil
}
-
return nil, fmt.Errorf("invalid token")
}
-// ParseToken parse un token JWT sans validation complète (utilise ValidateToken)
func (s *JWTService) ParseToken(tokenString string) (*models.CustomClaims, error) {
return s.ValidateToken(tokenString)
}
-// ExtractClaims extrait les claims d'un token JWT
func (s *JWTService) ExtractClaims(tokenString string) (*models.CustomClaims, error) {
return s.ValidateToken(tokenString)
}
-// ExtractUserID extrait l'ID utilisateur depuis un token JWT
-// MIGRATION UUID: retourne uuid.UUID au lieu de int64
func (s *JWTService) ExtractUserID(tokenString string) (uuid.UUID, error) {
claims, err := s.ValidateToken(tokenString)
if err != nil {
@@ -168,7 +243,6 @@ func (s *JWTService) ExtractUserID(tokenString string) (uuid.UUID, error) {
return claims.UserID, nil
}
-// VerifyTokenVersion vérifie si la version du token correspond à celle de l'utilisateur
func (s *JWTService) VerifyTokenVersion(claims *models.CustomClaims, userTokenVersion int) error {
if claims.TokenVersion != userTokenVersion {
return fmt.Errorf("token version mismatch: token version %d does not match user version %d", claims.TokenVersion, userTokenVersion)
@@ -177,26 +251,28 @@ func (s *JWTService) VerifyTokenVersion(claims *models.CustomClaims, userTokenVe
}
// GenerateStreamToken generates a short-lived JWT for HLS/WebSocket auth.
-// Uses issuer "veza-platform" and audience "veza-services" for compatibility with stream server.
-// TTL: 5 minutes. Claims match stream server Claims struct (sub, username, roles, etc.).
+// Uses issuer "veza-platform" and audience "veza-services" for stream server compatibility.
func (s *JWTService) GenerateStreamToken(user *models.User) (string, error) {
ttl := 5 * time.Minute
now := time.Now()
role := mapUserRoleToStreamRole(user.Role)
claims := jwt.MapClaims{
"sub": user.ID.String(),
- "user_id": user.ID.String(), // Chat server expects user_id
+ "user_id": user.ID.String(),
"username": user.Username,
- "email": user.Email,
- "roles": []string{role},
+ "email": user.Email,
+ "roles": []string{role},
"permissions": []string{"StreamAudio"},
- "exp": now.Add(ttl).Unix(),
- "iat": now.Unix(),
- "iss": "veza-platform",
- "aud": "veza-services",
- "session_id": uuid.NewString(),
+ "exp": now.Add(ttl).Unix(),
+ "iat": now.Unix(),
+ "iss": "veza-platform",
+ "aud": "veza-services",
+ "session_id": uuid.NewString(),
+ }
+ if s.useRS256 {
+ token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
+ return token.SignedString(s.privateKey)
}
-
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString(s.secretKey)
}
diff --git a/veza-backend-api/internal/services/jwt_service_test.go b/veza-backend-api/internal/services/jwt_service_test.go
index 94d207708..6fbb2624c 100644
--- a/veza-backend-api/internal/services/jwt_service_test.go
+++ b/veza-backend-api/internal/services/jwt_service_test.go
@@ -17,7 +17,7 @@ func TestJWTService(t *testing.T) {
secret := "test-secret-key-for-unit-tests-very-secure"
issuer := "veza-api"
audience := "veza-app"
- jwtService, err := NewJWTService(secret, issuer, audience)
+ jwtService, err := NewJWTService("", "", secret, issuer, audience)
assert.NoError(t, err)
// Mock User
diff --git a/veza-backend-api/internal/services/oauth_service_test.go b/veza-backend-api/internal/services/oauth_service_test.go
index ee127e0c0..639b4fca4 100644
--- a/veza-backend-api/internal/services/oauth_service_test.go
+++ b/veza-backend-api/internal/services/oauth_service_test.go
@@ -22,7 +22,7 @@ import (
// Uses sqlite in-memory when db has no GormDB (e.g. from sqlmock).
func setupOAuthServiceForTests(t *testing.T, db *database.Database) *OAuthService {
t.Helper()
- jwtService, err := NewJWTService("test-secret-key-minimum-32-characters-long", "veza-api", "veza-app")
+ jwtService, err := NewJWTService("", "", "test-secret-key-minimum-32-characters-long", "veza-api", "veza-app")
require.NoError(t, err)
// Use db for SessionService (needs sql.DB)
sessionService := NewSessionService(db, zap.NewNop())
diff --git a/veza-backend-api/migrations/123_invalidate_tokens_rs256.sql b/veza-backend-api/migrations/123_invalidate_tokens_rs256.sql
new file mode 100644
index 000000000..15e08f055
--- /dev/null
+++ b/veza-backend-api/migrations/123_invalidate_tokens_rs256.sql
@@ -0,0 +1,4 @@
+-- v0.9.1 TASK-SEC-001: Invalidate all existing JWT tokens (HS256) before RS256 migration.
+-- Incrementing token_version forces re-login with new RS256 tokens.
+
+UPDATE users SET token_version = token_version + 1;
diff --git a/veza-backend-api/tests/integration/logout_blacklist_test.go b/veza-backend-api/tests/integration/logout_blacklist_test.go
index ce671ccbf..2d2985a5c 100644
--- a/veza-backend-api/tests/integration/logout_blacklist_test.go
+++ b/veza-backend-api/tests/integration/logout_blacklist_test.go
@@ -89,7 +89,7 @@ func setupLogoutBlacklistTestRouter(t *testing.T) (*gin.Engine, *auth.AuthServic
emailValidator := validators.NewEmailValidator(db)
passwordValidator := validators.NewPasswordValidator()
passwordService := services.NewPasswordService(dbWrapper, logger)
- jwtService, err := services.NewJWTService("test-secret-key-must-be-32-chars-long", "test-issuer", "test-audience")
+ jwtService, err := services.NewJWTService("", "", "test-secret-key-must-be-32-chars-long", "test-issuer", "test-audience")
require.NoError(t, err)
refreshTokenService := services.NewRefreshTokenService(db)
emailVerificationService := services.NewEmailVerificationService(dbWrapper, logger)
diff --git a/veza-backend-api/tests/integration/oauth_github_test.go b/veza-backend-api/tests/integration/oauth_github_test.go
index e56605cf3..f8ef78792 100644
--- a/veza-backend-api/tests/integration/oauth_github_test.go
+++ b/veza-backend-api/tests/integration/oauth_github_test.go
@@ -80,7 +80,7 @@ func setupOAuthGitHubTestRouter(t *testing.T) (*gin.Engine, *services.OAuthServi
http.NotFound(w, r)
}))
- jwtService, err := services.NewJWTService("test-secret-key-must-be-32-chars-long", "test-issuer", "test-audience")
+ jwtService, err := services.NewJWTService("", "", "test-secret-key-must-be-32-chars-long", "test-issuer", "test-audience")
require.NoError(t, err)
sessionService := services.NewSessionService(dbWrapper, logger)
diff --git a/veza-backend-api/tests/integration/oauth_google_test.go b/veza-backend-api/tests/integration/oauth_google_test.go
index cc8d382bb..a163b51a4 100644
--- a/veza-backend-api/tests/integration/oauth_google_test.go
+++ b/veza-backend-api/tests/integration/oauth_google_test.go
@@ -75,7 +75,7 @@ func setupOAuthGoogleTestRouter(t *testing.T) (*gin.Engine, *services.OAuthServi
http.NotFound(w, r)
}))
- jwtService, err := services.NewJWTService("test-secret-key-must-be-32-chars-long", "test-issuer", "test-audience")
+ jwtService, err := services.NewJWTService("", "", "test-secret-key-must-be-32-chars-long", "test-issuer", "test-audience")
require.NoError(t, err)
sessionService := services.NewSessionService(dbWrapper, logger)
diff --git a/veza-backend-api/tests/integration/token_refresh_test.go b/veza-backend-api/tests/integration/token_refresh_test.go
index 817e2cfcd..5cc1abe98 100644
--- a/veza-backend-api/tests/integration/token_refresh_test.go
+++ b/veza-backend-api/tests/integration/token_refresh_test.go
@@ -75,7 +75,7 @@ func setupTokenRefreshTestRouter(t *testing.T) (*gin.Engine, *auth.AuthService,
emailValidator := validators.NewEmailValidator(db)
passwordValidator := validators.NewPasswordValidator()
passwordService := services.NewPasswordService(dbWrapper, logger)
- jwtService, err := services.NewJWTService("test-secret-key-must-be-32-chars-long", "test-issuer", "test-audience")
+ jwtService, err := services.NewJWTService("", "", "test-secret-key-must-be-32-chars-long", "test-issuer", "test-audience")
require.NoError(t, err)
refreshTokenService := services.NewRefreshTokenService(db)
emailVerificationService := services.NewEmailVerificationService(dbWrapper, logger)
diff --git a/veza-backend-api/tests/performance/critical_endpoints_performance_test.go b/veza-backend-api/tests/performance/critical_endpoints_performance_test.go
index 58a223044..f94647828 100644
--- a/veza-backend-api/tests/performance/critical_endpoints_performance_test.go
+++ b/veza-backend-api/tests/performance/critical_endpoints_performance_test.go
@@ -86,7 +86,7 @@ func setupPerformanceTestRouter(t *testing.T) (*gin.Engine, *gorm.DB, func()) {
emailValidator := validators.NewEmailValidator(db)
passwordValidator := validators.NewPasswordValidator()
passwordService := services.NewPasswordService(dbWrapper, logger)
- jwtService, err := services.NewJWTService("test-secret-key-must-be-32-chars-long", "test-issuer", "test-audience")
+ jwtService, err := services.NewJWTService("", "", "test-secret-key-must-be-32-chars-long", "test-issuer", "test-audience")
require.NoError(t, err)
refreshTokenService := services.NewRefreshTokenService(db)
emailVerificationService := services.NewEmailVerificationService(dbWrapper, logger)
diff --git a/veza-backend-api/tests/security/authorization_test.go b/veza-backend-api/tests/security/authorization_test.go
index 976fdc263..6385a7251 100644
--- a/veza-backend-api/tests/security/authorization_test.go
+++ b/veza-backend-api/tests/security/authorization_test.go
@@ -123,7 +123,7 @@ func setupAuthorizationTestRouter(t *testing.T) (*gin.Engine, *gorm.DB, *service
require.NoError(t, err)
// Setup services
- jwtService, err := services.NewJWTService("test-secret-key-must-be-32-chars-long", "test-issuer", "test-audience")
+ jwtService, err := services.NewJWTService("", "", "test-secret-key-must-be-32-chars-long", "test-issuer", "test-audience")
require.NoError(t, err)
sessionService := services.NewSessionService(dbWrapper, logger)
diff --git a/veza-backend-api/tests/security/injection_attack_test.go b/veza-backend-api/tests/security/injection_attack_test.go
index 70e59e788..2d3d35a35 100644
--- a/veza-backend-api/tests/security/injection_attack_test.go
+++ b/veza-backend-api/tests/security/injection_attack_test.go
@@ -72,7 +72,7 @@ func setupSecurityTestRouter(t *testing.T) (*gin.Engine, *gorm.DB, uuid.UUID, fu
emailValidator := validators.NewEmailValidator(db)
passwordValidator := validators.NewPasswordValidator()
passwordService := services.NewPasswordService(dbWrapper, logger)
- jwtService, err := services.NewJWTService("test-secret-key-must-be-32-chars-long", "test-issuer", "test-audience")
+ jwtService, err := services.NewJWTService("", "", "test-secret-key-must-be-32-chars-long", "test-issuer", "test-audience")
require.NoError(t, err)
refreshTokenService := services.NewRefreshTokenService(db)
emailVerificationService := services.NewEmailVerificationService(dbWrapper, logger)
diff --git a/veza-backend-api/tests/two_factor/two_factor_flow_test.go b/veza-backend-api/tests/two_factor/two_factor_flow_test.go
index 1e4ec0907..635287237 100644
--- a/veza-backend-api/tests/two_factor/two_factor_flow_test.go
+++ b/veza-backend-api/tests/two_factor/two_factor_flow_test.go
@@ -115,7 +115,7 @@ func setupTwoFactorTestRouter(t *testing.T) (*gin.Engine, *gorm.DB, *database.Da
emailValidator := validators.NewEmailValidator(db)
passwordValidator := validators.NewPasswordValidator()
passwordService := services.NewPasswordService(dbWrapper, logger)
- jwtService, err := services.NewJWTService("test-secret-key-must-be-32-chars-long", "test-issuer", "test-audience")
+ jwtService, err := services.NewJWTService("", "", "test-secret-key-must-be-32-chars-long", "test-issuer", "test-audience")
require.NoError(t, err)
refreshTokenService := services.NewRefreshTokenService(db)
emailVerificationService := services.NewEmailVerificationService(dbWrapper, logger)
diff --git a/veza-common/src/config_rust.rs b/veza-common/src/config_rust.rs
index bee579770..02ab97041 100644
--- a/veza-common/src/config_rust.rs
+++ b/veza-common/src/config_rust.rs
@@ -5,7 +5,7 @@
use serde::{Deserialize, Serialize};
use std::env;
-use tracing::{info, warn};
+use tracing::info;
/// Main configuration trait for Veza services
pub trait VezaConfig: Default + Clone + Serialize {
@@ -231,20 +231,21 @@ pub struct JwtConfig {
impl Default for JwtConfig {
fn default() -> Self {
Self {
- secret: "your-super-secret-jwt-key".to_string(),
+ // VEZA-SEC-001: No default secret — JWT_SECRET must be set via load_from_env
+ secret: String::new(),
access_token_ttl: 3600, // 1 hour
refresh_token_ttl: 604800, // 7 days
- issuer: "veza".to_string(),
- audience: "veza-users".to_string(),
+ issuer: "veza-api".to_string(),
+ audience: "veza-platform".to_string(),
}
}
}
impl VezaConfig for JwtConfig {
fn load_from_env(&mut self) -> crate::VezaResult<()> {
- if let Ok(secret) = env::var("JWT_SECRET") {
- self.secret = secret;
- }
+ // VEZA-SEC-001: JWT_SECRET is REQUIRED — refusing to start with no secret
+ self.secret = env::var("JWT_SECRET")
+ .map_err(|_| crate::VezaError::Config("JWT_SECRET must be set — refusing to start with no secret".to_string()))?;
if let Ok(ttl) = env::var("JWT_ACCESS_TOKEN_TTL") {
self.access_token_ttl = ttl.parse()
.map_err(|_| crate::VezaError::Config("Invalid JWT_ACCESS_TOKEN_TTL".to_string()))?;
@@ -267,7 +268,9 @@ impl VezaConfig for JwtConfig {
return Err(crate::VezaError::Config("JWT secret cannot be empty".to_string()));
}
if self.secret.len() < 32 {
- warn!("JWT secret is shorter than recommended 32 characters");
+ return Err(crate::VezaError::Config(
+ "JWT secret must be at least 32 characters".to_string(),
+ ));
}
if self.access_token_ttl == 0 {
return Err(crate::VezaError::Config("JWT access token TTL must be > 0".to_string()));
diff --git a/veza-docs/ORIGIN/ORIGIN_API_SPECIFICATION.md b/veza-docs/ORIGIN/ORIGIN_API_SPECIFICATION.md
index 76d1406e0..4b3e11a07 100644
--- a/veza-docs/ORIGIN/ORIGIN_API_SPECIFICATION.md
+++ b/veza-docs/ORIGIN/ORIGIN_API_SPECIFICATION.md
@@ -2,19 +2,25 @@
## 📋 RÉSUMÉ EXÉCUTIF
-Ce document définit la spécification complète et définitive de toutes les APIs de la plateforme Veza. Il documente 500+ endpoints REST, 50+ événements WebSocket, et 20+ services gRPC avec leurs schémas de requête/réponse, codes d'erreur standardisés, authentication flows, rate limiting, et versioning. L'API suit les principes REST/RESTful, utilise JSON comme format d'échange, et implémente OAuth 2.0 + JWT pour l'authentification.
+Ce document définit la spécification complète des APIs de la plateforme Veza, une plateforme audio open source et éthique pour musiciens indépendants. Il documente les endpoints REST, événements WebSocket, et services gRPC avec leurs schémas de requête/réponse, codes d'erreur standardisés, authentication flows, rate limiting transparent, et versioning explicite. L'API suit les principes REST/RESTful, utilise JSON comme format d'échange ouvert (aucun vendor lock-in), et implémente OAuth 2.0 + JWT pour l'authentification.
+
+**Principes éthiques de l'API** : aucune donnée comportementale dans les réponses, découverte basée sur des règles déclaratives (pas de ML/IA), pagination toujours disponible (pas de lock-in), portabilité complète des données, et rate limits publiquement documentés.
+
+**Exclusions éthiques** : aucun endpoint d'IA/ML (mastering, séparation de stems, détection de genre, recommandations ML, content ID, auto-tagging, synthèse vocale, transcription), aucun endpoint blockchain/NFT/crypto (minting, smart contracts, tokens, staking, DAO, IPFS, wallet), aucune gamification addictive (XP, niveaux, achievements basés sur l'engagement, leaderboards, streaks).
## 🎯 OBJECTIFS
### Objectif Principal
-Définir une API complète, cohérente, documentée, et immuable qui servira de contrat entre frontend/backend/mobile pendant 24 mois sans breaking changes.
+Définir une API complète, cohérente, documentée, éthique et ouverte qui servira de contrat entre frontend/backend/mobile, en respectant la souveraineté des utilisateurs sur leurs données et leur attention.
### Objectifs Secondaires
- Assurer la cohérence des schémas (naming, structure, types)
- Standardiser les codes d'erreur et messages
-- Faciliter l'intégration (clients, partenaires, développeurs tiers)
-- Garantir la scalabilité (rate limiting, caching, pagination)
-- Supporter le versioning (v1 stable, v2 pour évolutions)
+- Faciliter l'intégration (clients, partenaires, développeurs tiers) via des formats ouverts
+- Garantir la scalabilité (rate limiting transparent, caching, pagination obligatoire)
+- Supporter le versioning explicite (v1 stable, v2 pour évolutions, politique de dépréciation longue)
+- Garantir la portabilité des données (export complet pour chaque utilisateur)
+- Exclure toute collecte de données comportementales à des fins de profilage
## 📖 TABLE DES MATIÈRES
@@ -28,19 +34,25 @@ Définir une API complète, cohérente, documentée, et immuable qui servira de
8. [WebSocket APIs](#8-websocket-apis)
9. [gRPC APIs](#9-grpc-apis)
10. [OpenAPI 3.0 Specification](#10-openapi-30-specification)
+11. [API Éthique](#11-api-éthique)
+12. [Exclusions et Raisons Éthiques](#12-exclusions-et-raisons-éthiques)
## 🔒 RÈGLES IMMUABLES
1. **URLs DOIVENT suivre le pattern** `/api/v{version}/{resource}`
2. **HTTP methods DOIVENT respecter REST** (GET=read, POST=create, PUT=replace, PATCH=update, DELETE=delete)
3. **Responses DOIVENT être JSON** avec `Content-Type: application/json`
-4. **Dates DOIVENT être ISO 8601** (format: `2025-11-02T14:30:00Z`)
+4. **Dates DOIVENT être ISO 8601** (format: `2026-03-04T14:30:00Z`)
5. **IDs DOIVENT être UUID v4** (format: `550e8400-e29b-41d4-a716-446655440000`)
-6. **Pagination OBLIGATOIRE** pour collections (cursor-based par défaut)
-7. **Rate limiting OBLIGATOIRE** (headers: `X-RateLimit-*`)
+6. **Pagination OBLIGATOIRE** pour collections (cursor-based par défaut) — aucun endpoint ne force la consommation continue
+7. **Rate limiting OBLIGATOIRE et PUBLIC** (headers: `X-RateLimit-*`, documentation des limites accessible sans authentification)
8. **Authentication JWT** dans header `Authorization: Bearer {token}`
-9. **Error codes STANDARDISÉS** (range 1000-9999, voir section 4)
-10. **Breaking changes INTERDITS** dans v1 (créer v2 si nécessaire)
+9. **Error codes STANDARDISÉS** (range 1000-9999, voir section 4) avec messages explicites et header `Retry-After` systématique sur 429
+10. **Breaking changes INTERDITS** dans v1 (créer v2 si nécessaire, politique de dépréciation ≥ 12 mois)
+11. **AUCUNE donnée comportementale** dans les réponses API (pas de tracking de scroll, temps de lecture, patterns de navigation)
+12. **AUCUN endpoint ML/IA, blockchain/NFT, ou gamification addictive** (voir section 12)
+13. **Portabilité des données OBLIGATOIRE** — endpoint d'export complet pour chaque utilisateur
+14. **Format ouvert JSON** — aucun format propriétaire, aucun vendor lock-in
## 1. DESIGN PRINCIPLES
@@ -456,6 +468,10 @@ Request:
## 5. RATE LIMITING
+> **Politique de transparence** : tous les rate limits sont publiquement documentés et accessibles
+> sans authentification via `GET /api/v1/rate-limits`. Les messages d'erreur 429 incluent systématiquement
+> le header `Retry-After` avec le nombre de secondes avant réinitialisation.
+
### 5.1 Rate Limits by Endpoint Type
| Endpoint Type | Limit | Window |
@@ -466,6 +482,7 @@ Request:
| **File Upload** | 10 uploads | 1 hour |
| **Search** | 500 requests | 1 hour |
| **Streaming** | 10,000 plays | 1 day |
+| **Export** | 3 requests | 1 day |
### 5.2 Rate Limit Headers
@@ -488,12 +505,75 @@ Retry-After: 1800
{
"error": {
"code": 5000,
- "message": "Rate limit exceeded. Try again in 30 minutes."
+ "message": "Rate limit exceeded. Try again in 30 minutes.",
+ "retry_after_seconds": 1800
}
}
```
-### 5.3 Premium User Limits
+### 5.3 Rate Limit Documentation Endpoint
+
+#### `GET /api/v1/rate-limits`
+**Description**: Documentation publique de tous les rate limits (aucune authentification requise).
+
+**Response** (200 OK):
+```json
+{
+ "rate_limits": [
+ {
+ "endpoint_type": "authentication",
+ "limit": 10,
+ "window_seconds": 60,
+ "description": "Login, register, password reset"
+ },
+ {
+ "endpoint_type": "read",
+ "limit": 1000,
+ "window_seconds": 3600,
+ "description": "GET requests on all resources"
+ },
+ {
+ "endpoint_type": "write",
+ "limit": 100,
+ "window_seconds": 3600,
+ "description": "POST, PUT, PATCH requests"
+ },
+ {
+ "endpoint_type": "upload",
+ "limit": 10,
+ "window_seconds": 3600,
+ "description": "File uploads (audio, images)"
+ },
+ {
+ "endpoint_type": "search",
+ "limit": 500,
+ "window_seconds": 3600,
+ "description": "Search queries"
+ },
+ {
+ "endpoint_type": "streaming",
+ "limit": 10000,
+ "window_seconds": 86400,
+ "description": "Stream plays per day"
+ },
+ {
+ "endpoint_type": "export",
+ "limit": 3,
+ "window_seconds": 86400,
+ "description": "Data export requests per day"
+ }
+ ],
+ "headers_documentation": {
+ "X-RateLimit-Limit": "Maximum requests allowed in window",
+ "X-RateLimit-Remaining": "Remaining requests in current window",
+ "X-RateLimit-Reset": "Unix timestamp when window resets",
+ "X-RateLimit-Window": "Window duration in seconds",
+ "Retry-After": "Seconds to wait before retrying (on 429 responses)"
+ }
+}
+```
+
+### 5.4 Premium User Limits
| Endpoint Type | Standard | Premium | Factor |
|---------------|----------|---------|--------|
@@ -749,7 +829,7 @@ Retry-After: 1800
**Parameters**:
- `id` (path, required) - User UUID
-- `include` (query, optional) - Related resources (`profile,stats,badges`)
+- `include` (query, optional) - Related resources (`profile,stats`)
**Response** (200 OK):
```json
@@ -771,13 +851,7 @@ Retry-After: 1800
"track_count": 85,
"playlist_count": 12
},
- "badges": [
- {
- "name": "Verified Creator",
- "icon_url": "https://cdn.veza.io/badges/verified.svg",
- "rarity": "rare"
- }
- ],
+ "is_verified": true,
"created_at": "2024-01-15T10:00:00Z"
}
```
@@ -1578,33 +1652,14 @@ cover_art: (image file, optional)
---
-### 7.8 Module: Analytics
+### 7.8 Module: Statistiques Créateur (Analytics éthiques)
-#### `POST /api/v1/analytics/events`
-**Description**: Track analytics event (client-side tracking).
-
-**Request**:
-```json
-{
- "event_type": "track_play",
- "event_data": {
- "track_id": "uuid",
- "duration_played": 120,
- "completion_percentage": 50
- },
- "metadata": {
- "user_agent": "...",
- "referrer": "..."
- }
-}
-```
-
-**Response** (204 No Content)
-
----
+> **Principe éthique** : seules les statistiques agrégées et anonymisées sont disponibles.
+> Aucune donnée comportementale individuelle (temps de lecture, scroll, patterns de navigation) n'est collectée ni exposée.
+> Les créateurs accèdent uniquement aux compteurs agrégés de leurs propres contenus.
#### `GET /api/v1/analytics/tracks/{id}`
-**Description**: Get track analytics.
+**Description**: Statistiques agrégées d'un track (réservé au propriétaire).
**Headers**: `Authorization: Bearer {token}`
@@ -1615,24 +1670,343 @@ cover_art: (image file, optional)
{
"track_id": "uuid",
"plays_total": 12500,
- "plays_unique": 8500,
"likes_total": 850,
"comments_total": 42,
- "plays_by_country": {
- "US": 5000,
- "UK": 2500,
- "CA": 1500
- },
"plays_by_day": [
- { "date": "2025-11-01", "plays": 450 },
- { "date": "2025-11-02", "plays": 520 }
+ { "date": "2026-03-01", "plays": 450 },
+ { "date": "2026-03-02", "plays": 520 }
+ ]
+}
+```
+
+> **Données exclues volontairement** : géolocalisation par pays, données démographiques, user agents, referrers, durée de lecture individuelle, taux de complétion. Ces données ne sont ni collectées ni stockées.
+
+---
+
+#### `GET /api/v1/analytics/summary`
+**Description**: Résumé global des statistiques du créateur authentifié.
+
+**Headers**: `Authorization: Bearer {token}`
+
+**Permissions**: `creator`, `admin`
+
+**Response** (200 OK):
+```json
+{
+ "total_tracks": 85,
+ "total_plays": 125000,
+ "total_likes": 8500,
+ "total_comments": 420,
+ "plays_last_30_days": 15000,
+ "top_tracks": [
+ {
+ "track_id": "uuid",
+ "title": "Midnight Dreams",
+ "plays": 12500,
+ "likes": 850
+ }
]
}
```
---
-*[7.9-7.15 Other modules follow similar patterns]*
+### 7.9 Module: Découverte Éthique
+
+> **Principe** : la découverte est basée sur des règles déclaratives, des tags/genres déclarés par les créateurs,
+> et le graphe social opt-in. Aucun algorithme de recommandation ML/IA, aucun profilage comportemental.
+
+#### `GET /api/v1/discover/genres`
+**Description**: Découverte par genres et tags déclarés. Retourne les tracks publics correspondant aux genres/tags demandés, triés chronologiquement (plus récents en premier).
+
+**Parameters**:
+- `genres` (query, required) - Genres à découvrir, séparés par virgules (`electronic,house,jazz`)
+- `tags` (query, optional) - Tags supplémentaires (`ambient,chill`)
+- `limit` (query, optional, default=20) - Page size
+- `cursor` (query, optional) - Pagination cursor
+- `sort` (query, optional, default=-published_at) - Tri (`-published_at`, `title`, `-like_count`)
+
+**Response** (200 OK):
+```json
+{
+ "data": [
+ {
+ "id": "track-uuid",
+ "title": "Midnight Dreams",
+ "artist": "DJ Nova",
+ "genre": "Electronic",
+ "tags": ["ambient", "chill"],
+ "duration": 245,
+ "cover_art_url": "https://cdn.veza.io/covers/...",
+ "creator": {
+ "id": "creator-uuid",
+ "username": "djnova",
+ "avatar_url": "https://..."
+ },
+ "play_count": 12500,
+ "like_count": 850,
+ "published_at": "2026-03-01T10:00:00Z"
+ }
+ ],
+ "filters_applied": {
+ "genres": ["electronic"],
+ "tags": [],
+ "sort": "-published_at"
+ },
+ "pagination": {
+ "next_cursor": "eyJpZCI6IjY2MWU5NTExIn0",
+ "has_more": true,
+ "limit": 20
+ }
+}
+```
+
+---
+
+#### `GET /api/v1/discover/editorial`
+**Description**: Playlists éditorialisées par l'équipe ou des curateurs vérifiés. Curation humaine uniquement, aucune automatisation algorithmique.
+
+**Parameters**:
+- `limit` (query, optional, default=10)
+- `cursor` (query, optional)
+- `genre` (query, optional) - Filtrer par genre
+
+**Response** (200 OK):
+```json
+{
+ "data": [
+ {
+ "id": "playlist-uuid",
+ "name": "Sélection de la semaine — Électronique",
+ "description": "Les coups de cœur de l'équipe éditoriale",
+ "curator": {
+ "id": "curator-uuid",
+ "username": "veza_editorial",
+ "is_verified": true
+ },
+ "track_count": 12,
+ "cover_art_url": "https://cdn.veza.io/editorial/...",
+ "published_at": "2026-03-01T08:00:00Z"
+ }
+ ],
+ "pagination": { "next_cursor": "...", "has_more": true, "limit": 10 }
+}
+```
+
+---
+
+#### `GET /api/v1/discover/social`
+**Description**: Découverte par graphe social (opt-in). Retourne les tracks récemment écoutés ou likés par les contacts de l'utilisateur authentifié, uniquement si ces contacts ont activé le partage d'écoute.
+
+**Headers**: `Authorization: Bearer {token}`
+
+**Parameters**:
+- `limit` (query, optional, default=20)
+- `cursor` (query, optional)
+
+**Response** (200 OK):
+```json
+{
+ "data": [
+ {
+ "track": {
+ "id": "track-uuid",
+ "title": "Summer Vibes",
+ "artist": "johndoe",
+ "genre": "House",
+ "cover_art_url": "https://..."
+ },
+ "shared_by": [
+ {
+ "user_id": "contact-uuid",
+ "username": "jane_smith",
+ "action": "liked",
+ "action_at": "2026-03-02T15:00:00Z"
+ }
+ ]
+ }
+ ],
+ "opt_in_notice": "Seuls les contacts ayant activé le partage d'écoute apparaissent ici.",
+ "pagination": { "next_cursor": "...", "has_more": true, "limit": 20 }
+}
+```
+
+**Errors**:
+- `401` - Non authentifié (1002)
+
+---
+
+#### `GET /api/v1/discover/new`
+**Description**: Nouveaux tracks dans les genres suivis par l'utilisateur, triés chronologiquement. Aucune pondération algorithmique — ordre strictement chronologique inversé.
+
+**Headers**: `Authorization: Bearer {token}`
+
+**Parameters**:
+- `limit` (query, optional, default=20)
+- `cursor` (query, optional)
+
+**Response** (200 OK):
+```json
+{
+ "data": [
+ {
+ "id": "track-uuid",
+ "title": "Fresh Beat",
+ "artist": "producer_x",
+ "genre": "Electronic",
+ "published_at": "2026-03-04T09:00:00Z",
+ "creator": {
+ "id": "creator-uuid",
+ "username": "producer_x"
+ }
+ }
+ ],
+ "followed_genres": ["electronic", "house", "jazz"],
+ "pagination": { "next_cursor": "...", "has_more": true, "limit": 20 }
+}
+```
+
+---
+
+#### `GET /api/v1/discover/nearby`
+**Description**: Découverte par proximité géographique (optionnel, opt-in). Retourne les créateurs et tracks publiés par des artistes proches de la localisation déclarée de l'utilisateur. La localisation est basée sur la ville/région déclarée dans le profil, pas de géolocalisation temps-réel.
+
+**Headers**: `Authorization: Bearer {token}`
+
+**Parameters**:
+- `radius_km` (query, optional, default=50) - Rayon de recherche en km
+- `limit` (query, optional, default=20)
+- `cursor` (query, optional)
+
+**Response** (200 OK):
+```json
+{
+ "data": [
+ {
+ "creator": {
+ "id": "creator-uuid",
+ "username": "local_artist",
+ "display_name": "Local Artist",
+ "location": "Paris, France"
+ },
+ "recent_tracks": [
+ {
+ "id": "track-uuid",
+ "title": "Paris Nights",
+ "published_at": "2026-03-03T20:00:00Z"
+ }
+ ]
+ }
+ ],
+ "search_location": "Paris, France",
+ "radius_km": 50,
+ "pagination": { "next_cursor": "...", "has_more": true, "limit": 20 }
+}
+```
+
+**Errors**:
+- `400` - Localisation non renseignée dans le profil (2001)
+
+---
+
+#### `PUT /api/v1/discover/preferences`
+**Description**: Définir les préférences de découverte de l'utilisateur (genres suivis, opt-in social, opt-in proximité).
+
+**Headers**: `Authorization: Bearer {token}`
+
+**Request**:
+```json
+{
+ "followed_genres": ["electronic", "house", "jazz", "hip-hop"],
+ "social_sharing_enabled": true,
+ "nearby_discovery_enabled": true
+}
+```
+
+**Response** (200 OK):
+```json
+{
+ "followed_genres": ["electronic", "house", "jazz", "hip-hop"],
+ "social_sharing_enabled": true,
+ "nearby_discovery_enabled": true,
+ "updated_at": "2026-03-04T14:30:00Z"
+}
+```
+
+---
+
+### 7.10 Module: Portabilité des Données
+
+> **Principe éthique** : tout utilisateur peut exporter l'intégralité de ses données à tout moment,
+> dans un format ouvert et documenté. Aucune rétention artificielle.
+
+#### `POST /api/v1/export`
+**Description**: Demander un export complet des données de l'utilisateur (RGPD Art. 20). L'export est préparé de manière asynchrone et notifié par email.
+
+**Headers**: `Authorization: Bearer {token}`
+
+**Request**:
+```json
+{
+ "format": "json",
+ "include": ["profile", "tracks", "playlists", "likes", "comments", "messages", "orders", "preferences"]
+}
+```
+
+**Response** (202 Accepted):
+```json
+{
+ "export_id": "export-uuid",
+ "status": "processing",
+ "estimated_completion": "2026-03-04T15:00:00Z",
+ "message": "Votre export est en cours de préparation. Vous recevrez un email avec le lien de téléchargement."
+}
+```
+
+---
+
+#### `GET /api/v1/export/{id}`
+**Description**: Vérifier le statut d'un export.
+
+**Headers**: `Authorization: Bearer {token}`
+
+**Response** (200 OK):
+```json
+{
+ "export_id": "export-uuid",
+ "status": "completed",
+ "download_url": "https://cdn.veza.io/exports/...",
+ "download_expires_at": "2026-03-11T15:00:00Z",
+ "file_size_bytes": 15728640,
+ "created_at": "2026-03-04T14:30:00Z",
+ "completed_at": "2026-03-04T14:45:00Z"
+}
+```
+
+---
+
+#### `DELETE /api/v1/account`
+**Description**: Supprimer définitivement le compte et toutes les données associées (RGPD Art. 17 — droit à l'effacement). Opération irréversible après période de grâce de 30 jours.
+
+**Headers**: `Authorization: Bearer {token}`
+
+**Request**:
+```json
+{
+ "confirmation": "DELETE_MY_ACCOUNT",
+ "password": "current_password"
+}
+```
+
+**Response** (200 OK):
+```json
+{
+ "message": "Votre compte sera définitivement supprimé dans 30 jours. Reconnectez-vous avant cette date pour annuler.",
+ "deletion_scheduled_at": "2026-04-03T14:30:00Z"
+}
+```
+
+---
## 8. WEBSOCKET APIS
@@ -1825,13 +2199,16 @@ service ChatService {
openapi: 3.0.3
info:
title: Veza API
- version: 1.0.0
+ version: 2.0.0
description: |
- Veza platform API - Collaborative audio streaming, marketplace, and social network.
+ Veza platform API — Open source ethical audio platform for independent musicians.
**Authentication**: JWT Bearer token in `Authorization` header.
- **Rate Limiting**: Varies by endpoint (see headers).
+ **Rate Limiting**: Publicly documented. See `GET /api/v1/rate-limits`.
+
+ **Ethical principles**: No behavioral data, no ML/AI recommendations, no blockchain/NFT,
+ no addictive gamification. Full data portability.
**Support**: api@veza.io
contact:
@@ -1839,7 +2216,8 @@ info:
email: api@veza.io
url: https://docs.veza.io
license:
- name: Proprietary
+ name: AGPL-3.0
+ url: https://www.gnu.org/licenses/agpl-3.0.html
servers:
- url: https://api.veza.io/api/v1
description: Production
@@ -2015,17 +2393,110 @@ paths:
$ref: '#/components/responses/Forbidden'
```
-*[Full OpenAPI 3.0 spec with all 500+ endpoints would be ~5,000 lines - included in separate YAML file]*
+*[Full OpenAPI 3.0 spec included in separate YAML file]*
+
+## 11. API ÉTHIQUE
+
+### 11.1 Aucune Donnée Comportementale dans les Réponses
+
+Les réponses API ne contiennent **jamais** :
+- De données de tracking utilisateur (scroll depth, mouse movements, session duration)
+- De scores de recommandation ou poids algorithmiques
+- De profils comportementaux dérivés
+- D'identifiants de tracking tiers (pixels, fingerprints)
+- De données permettant le profilage publicitaire
+
+Les seules données retournées sont celles **explicitement demandées** par l'utilisateur ou le créateur, dans le cadre de l'utilisation directe de la plateforme.
+
+### 11.2 Pagination Toujours Disponible
+
+**Tous** les endpoints retournant des collections supportent la pagination :
+- Cursor-based (par défaut) ou offset-based
+- Aucun endpoint ne force une consommation continue (pas de scroll infini obligatoire côté API)
+- Le client est libre de consommer les données à son rythme
+- Les paramètres `limit` et `cursor`/`page` sont toujours disponibles
+
+### 11.3 Format Ouvert — Aucun Vendor Lock-in
+
+- **Format unique** : JSON (`application/json`) pour toutes les réponses REST
+- **Pas de format propriétaire** : aucun SDK obligatoire, aucun protocole fermé
+- **Documentation ouverte** : OpenAPI 3.0, libre d'accès
+- **Export standard** : les données utilisateur sont exportables en JSON standard (voir section 7.10)
+- **Interopérabilité** : tout client HTTP standard peut consommer l'API
+
+### 11.4 Versioning Explicite avec Politique de Dépréciation Longue
+
+- **Versioning sémantique** dans l'URL (`/api/v1/`, `/api/v2/`)
+- **Politique de dépréciation** : minimum **12 mois** entre l'annonce de dépréciation et la suppression
+- **Header de dépréciation** : `Deprecation: true` + `Sunset: ` sur les endpoints dépréciés
+- **Guide de migration** publié pour chaque changement majeur
+- **Aucun breaking change** dans une version stable sans nouvelle version majeure
+
+### 11.5 Portabilité des Données
+
+- Tout utilisateur peut **exporter l'intégralité de ses données** à tout moment (`POST /api/v1/export`)
+- Format d'export : JSON standard, documenté, lisible par des outils tiers
+- Droit à l'effacement : suppression complète du compte et des données (`DELETE /api/v1/account`)
+- Conformité RGPD (Art. 17 droit à l'effacement, Art. 20 portabilité)
+
+## 12. EXCLUSIONS ET RAISONS ÉTHIQUES
+
+Cette section documente les catégories d'endpoints **volontairement exclues** de l'API Veza, avec les raisons éthiques associées.
+
+### 12.1 Endpoints IA/ML — EXCLUS
+
+| Endpoint exclu | Raison éthique |
+|----------------|----------------|
+| `POST /api/v1/tracks/{id}/master` (mastering automatique) | Remplace le travail créatif humain, dévalorise l'ingénierie du son |
+| `POST /api/v1/tracks/{id}/stems` (séparation de stems) | Risque d'utilisation pour plagiat, extraction non consentie |
+| `GET /api/v1/tracks/{id}/genre-detect` (détection de genre ML) | Les genres sont déclarés par les créateurs, pas imposés par un algorithme |
+| `GET /api/v1/recommendations` (recommandations ML) | Crée des bulles de filtre, favorise l'engagement addictif sur la diversité |
+| `POST /api/v1/tracks/{id}/content-id` (content ID ML) | Système de surveillance automatisée, risque de faux positifs avec censure |
+| `POST /api/v1/tracks/{id}/auto-tag` (auto-tagging ML) | Les tags sont la responsabilité des créateurs, pas d'une machine |
+| `GET /api/v1/tracks/{id}/similar` (similarité ML) | Favorise l'homogénéité, réduit la diversité musicale |
+| `POST /api/v1/voice/synthesize` (synthèse vocale) | Risque d'usurpation d'identité vocale, deepfakes audio |
+| `POST /api/v1/tracks/{id}/transcribe` (transcription lyrics ML) | Les paroles sont fournies par les artistes, respect du droit d'auteur |
+
+**Alternative éthique** : découverte basée sur les genres/tags déclarés par les créateurs, curation éditoriale humaine, et graphe social opt-in (voir section 7.9).
+
+### 12.2 Endpoints Blockchain/NFT/Crypto — EXCLUS
+
+| Endpoint exclu | Raison éthique |
+|----------------|----------------|
+| `POST /api/v1/nft/mint` (minting NFT) | Spéculation financière sur l'art, impact environnemental |
+| `GET /api/v1/contracts/{id}` (smart contracts) | Complexité inutile, exclusion des artistes non-technophiles |
+| `POST /api/v1/tokens/transfer` (transfert tokens) | Financiarisation des interactions sociales |
+| `POST /api/v1/staking/deposit` (staking) | Mécanisme spéculatif incompatible avec une plateforme artistique |
+| `GET /api/v1/dao/proposals` (DAO governance) | Gouvernance ploutocratique (pouvoir proportionnel aux tokens détenus) |
+| `POST /api/v1/ipfs/pin` (IPFS storage) | Fausse décentralisation, complexité pour les utilisateurs |
+| `POST /api/v1/wallet/connect` (wallet crypto) | Barrière à l'entrée, exclusion économique |
+
+**Alternative éthique** : paiements classiques (Stripe), licence créative déclarée par l'artiste, gouvernance communautaire transparente sans tokens.
+
+### 12.3 Endpoints Gamification Addictive — EXCLUS
+
+| Endpoint exclu | Raison éthique |
+|----------------|----------------|
+| `GET /api/v1/users/{id}/xp` (points d'expérience) | Conditionne l'engagement par la récompense, pas par l'intérêt |
+| `GET /api/v1/users/{id}/level` (niveaux) | Hiérarchise artificiellement les utilisateurs |
+| `GET /api/v1/users/{id}/achievements` (achievements engagement) | Oriente le comportement vers des métriques, pas vers la création |
+| `GET /api/v1/leaderboards` (classements) | Compétition artificielle, pression sociale, anxiété de performance |
+| `GET /api/v1/users/{id}/streaks` (séries consécutives) | Manipulation psychologique (aversion à la perte), engagement forcé |
+| `POST /api/v1/rewards/claim` (réclamation récompenses) | Boucle de renforcement addictive |
+
+**Alternative éthique** : le statut `is_verified` pour les créateurs vérifiés (basé sur l'identité, pas sur l'activité), statistiques agrégées transparentes pour les créateurs (section 7.8).
## ✅ CHECKLIST DE VALIDATION
### API Completeness
-- [ ] 500+ endpoints documentés pour tous les modules
+- [ ] Endpoints documentés pour tous les modules actifs
- [ ] Request/Response schemas complets
- [ ] Authentication flows documentés
- [ ] Error codes standardisés (1000-9999)
- [ ] WebSocket protocol spécifié
- [ ] gRPC services définis
+- [ ] Endpoints de découverte éthique documentés
+- [ ] Endpoints de portabilité des données documentés
### Consistency
- [ ] Naming conventions respectées (snake_case, plural resources)
@@ -2037,8 +2508,19 @@ paths:
### Security
- [ ] JWT authentication implémentée
- [ ] Rate limiting sur tous les endpoints
+- [ ] Rate limits publiquement documentés (`GET /api/v1/rate-limits`)
- [ ] Permission checks documentés
- [ ] Sensitive data jamais en query params
+- [ ] Header `Retry-After` systématique sur 429
+
+### Éthique
+- [ ] Aucune donnée comportementale dans les réponses
+- [ ] Pagination disponible sur toutes les collections
+- [ ] Format ouvert JSON, aucun vendor lock-in
+- [ ] Portabilité des données (export complet)
+- [ ] Droit à l'effacement implémenté
+- [ ] Exclusions ML/IA, blockchain/NFT, gamification documentées
+- [ ] Découverte basée sur règles, pas sur ML
### Performance
- [ ] Pagination obligatoire pour collections
@@ -2064,29 +2546,32 @@ paths:
| Version | Date | Changements |
|---------|------|-------------|
-| 1.0.0 | 2025-11-02 | Version initiale - API REST complète |
+| 1.0.0 | 2025-11-02 | Version initiale — API REST complète |
+| 2.0.0 | 2026-03-04 | Révision éthique — Suppression endpoints ML/IA, blockchain/NFT, gamification addictive. Ajout découverte éthique (genres, éditorial, social, chronologique, proximité). Portabilité des données (export, effacement). Rate limits publics. Section API Éthique et Exclusions documentées. Licence open source. |
---
## ⚠️ AVERTISSEMENT
-**CETTE SPÉCIFICATION EST IMMUABLE**
+**CETTE SPÉCIFICATION SUIT LE VERSIONING SÉMANTIQUE**
-L'API v1 définie ici est **VERROUILLÉE**. Toute modification nécessite:
+Toute modification nécessite :
1. **RFC API Change** avec impact analysis
-2. **Backward compatibility** garantie
-3. **Deprecation notice** (6 mois minimum)
+2. **Backward compatibility** garantie au sein d'une version majeure
+3. **Deprecation notice** (12 mois minimum)
4. **Migration guide** pour clients existants
-5. **Approbation CTO**
+5. **Revue éthique** — vérification que le changement respecte les principes de la section 11
-**Breaking changes INTERDITS en v1** - Créer v2 si nécessaire.
+**Breaking changes INTERDITS dans une version stable** — Créer une nouvelle version majeure si nécessaire.
---
-**Document créé par**: API Team + Architecture
-**Date de création**: 2025-11-02
-**Prochaine révision**: Phase 4 (Q3 2026)
-**Propriétaire**: Lead Backend Engineer
+**Document créé par** : API Team + Architecture
+**Date de création** : 2025-11-02
+**Révision éthique** : 2026-03-04 (v2.0.0)
+**Prochaine révision** : Q3 2026
+**Propriétaire** : Lead Backend Engineer
+**Licence** : Open Source
-**Statut**: ✅ **APPROUVÉ ET VERROUILLÉ**
+**Statut** : ✅ **APPROUVÉ — RÉVISION ÉTHIQUE v2.0.0**
diff --git a/veza-docs/ORIGIN/ORIGIN_BUSINESS_LOGIC.md b/veza-docs/ORIGIN/ORIGIN_BUSINESS_LOGIC.md
index b05b9f6ea..58b472cfc 100644
--- a/veza-docs/ORIGIN/ORIGIN_BUSINESS_LOGIC.md
+++ b/veza-docs/ORIGIN/ORIGIN_BUSINESS_LOGIC.md
@@ -2,7 +2,9 @@
## 📋 RÉSUMÉ EXÉCUTIF
-Ce document définit toutes les règles métier (business logic) de la plateforme Veza. Il couvre les prix, commissions, workflows utilisateurs, machines à états, règles de validation, calculs complexes, notifications, limites, quotas, et SLAs. Ces règles sont immuables et garantissent la cohérence des comportements métier pendant 24 mois.
+Ce document définit toutes les règles métier (business logic) de la plateforme Veza. Il couvre les prix, commissions, workflows utilisateurs, machines à états, règles de validation, calculs complexes, notifications, limites, quotas, et SLAs. Ces règles sont alignées avec les principes éthiques fondateurs du projet et garantissent la cohérence des comportements métier.
+
+**Dernière révision**: 2026-03-04 (révision éthique — suppression crypto, AI, publicité)
## 🎯 OBJECTIFS
@@ -18,6 +20,7 @@ Centraliser et définir de manière exhaustive toutes les règles métier de la
## 📖 TABLE DES MATIÈRES
+0. [Principes Éthiques et Modèle Économique](#0-principes-éthiques-et-modèle-économique)
1. [Pricing Models](#1-pricing-models)
2. [Commission Structure](#2-commission-structure)
3. [User Workflows](#3-user-workflows)
@@ -28,6 +31,8 @@ Centraliser et définir de manière exhaustive toutes les règles métier de la
8. [Notification Rules](#8-notification-rules)
9. [Limits & Quotas](#9-limits--quotas)
10. [SLA Definitions](#10-sla-definitions)
+11. [Exclusions et Raisons Éthiques](#11-exclusions-et-raisons-éthiques)
+12. [Gouvernance](#12-gouvernance)
## 🔒 RÈGLES IMMUABLES
@@ -42,6 +47,42 @@ Centraliser et définir de manière exhaustive toutes les règles métier de la
9. **SLAs MESURABLES** (métriques, alerting)
10. **Règles VERSIONÉES** (changements documentés)
+## 0. PRINCIPES ÉTHIQUES ET MODÈLE ÉCONOMIQUE
+
+L'éthique de Veza n'est pas un argument marketing. C'est l'architecture de valeurs qui détermine chaque décision économique. Aucune règle métier ne peut contredire ces principes.
+
+### Modèle open source / open core
+
+**Gratuit (open core)** :
+- Upload (quotas raisonnables)
+- Streaming illimité
+- Profil artiste complet
+- Chat et collaboration
+- Marketplace (commission sur transactions)
+
+**Premium individuel** :
+- Stockage cloud étendu
+- Analytics avancés (détaillés, exportables)
+- Distribution (upload vers plateformes tierces)
+- Priorité dans les files de transcoding
+
+**Pro / Label** :
+- API complète (rate limits étendus)
+- White label partiel
+- Analytics équipe
+- Support prioritaire
+
+**Commission marketplace** :
+- Pourcentage sur les ventes de licences et beats
+- Transparente, documentée, sans surprise
+
+### Ce qui ne sera JAMAIS monétisé
+
+- **Publicité** : zéro régie publicitaire, zéro pixel de tracking tiers
+- **Données utilisateurs** : les données ne sont pas un produit
+- **Freemium agressif** : pas de features artificiellement bridées pour forcer l'upgrade
+- **Algorithmes de rétention** : pas d'optimisation pour maximiser le temps passé
+
## 1. PRICING MODELS
### 1.1 Product Pricing
@@ -85,10 +126,12 @@ Creator: $9.99/month ($99.99/year, 17% savings)
Premium: $19.99/month ($199.99/year, 17% savings)
- All Creator features
- Priority support
- - No ads
- Storage: 200 GB
- Sell products: Yes (10% commission)
- Collaboration tools
+ - Distribution vers plateformes tierces
+
+Note: Aucun plan ne contient de publicité. Veza est 100% sans publicité.
```
### 1.2 Dynamic Pricing
@@ -165,7 +208,7 @@ Seller receives: $81.80
```
Streaming plays:
- Creator receives $0.004 per play (avg)
-- Platform keeps remaining revenue from ads/subscriptions
+- Revenus issus des abonnements Premium uniquement (pas de publicité)
Example (10,000 plays):
Creator revenue: 10,000 * $0.004 = $40.00
@@ -187,11 +230,7 @@ Domestic: 2.99% + $0.49
International: 4.49% + $0.49
```
-**Crypto** (future):
-```
-Bitcoin: 1% + network fees
-Ethereum: 1% + gas fees
-```
+> **Note** : Le paiement via Hyperswitch (open source, multi-provider) est le standard. Stripe et PayPal sont des providers configurés. Les cryptomonnaies sont exclues définitivement (voir [§11 Exclusions](#11-exclusions-et-raisons-éthiques)).
### 2.3 Payout Schedule
@@ -340,9 +379,8 @@ Total: ~2-9 min
- Total
7. Click "Proceed to Checkout"
8. Select payment method:
- - Credit card (Stripe)
- - PayPal
- - (Future: Crypto)
+ - Credit card (via Hyperswitch)
+ - PayPal (via Hyperswitch)
9. Enter billing info
10. Review order
11. Click "Place Order"
@@ -354,11 +392,12 @@ Total: ~2-9 min
14. Download files
```
-**Abandonment Recovery**:
+**Panier** :
```
-Cart abandoned for 1 hour: Email reminder
-Cart abandoned for 24 hours: Email with 10% discount
-Cart abandoned for 7 days: Email with 15% discount (final)
+Le panier est conservé 30 jours.
+Pas de relance email agressive pour paniers abandonnés.
+Un seul email de rappel optionnel après 7 jours (si l'utilisateur a activé les notifications marketing).
+Pas de discount de pression temporelle (pas de FOMO).
```
### 3.4 Subscription Workflow
@@ -460,22 +499,25 @@ stateDiagram-v2
**Auto-Moderation Rules**:
```
-1. NSFW Detection (AI):
- - Explicit content → flagged
- - Hate speech → flagged
- - Violence → flagged
+1. Détection par règles (pas d'IA) :
+ - Mots-clés bloqués → flagged
+ - Patterns de contenu explicite → flagged (règles déterministes)
-2. Spam Detection:
+2. Spam Detection :
- Identical title/description → flagged
- Excessive links → flagged
- - Bot patterns → flagged
+ - Bot patterns (rate, timing) → flagged
-3. Copyright Detection:
+3. Copyright Detection :
- Audio fingerprinting (ACRCloud)
- Matches known tracks → flagged
-If flagged → pending moderation
-If auto-approved → approved (low risk content)
+4. Modération humaine :
+ - Tout contenu flaggé est revu par un modérateur humain
+ - La décision finale est toujours humaine
+
+If flagged → pending modération humaine
+If auto-approved → approved (contenu conforme aux règles)
```
### 4.3 User Account State Machine
@@ -634,7 +676,7 @@ Cannot contain:
```
Max length: 500 characters
Allowed characters: Any UTF-8
-Blocked patterns: Excessive links (max 3), hate speech (AI detection)
+Blocked patterns: Excessive links (max 3), mots-clés bloqués (liste de modération)
```
### 6.2 Track Metadata Validation
@@ -842,13 +884,13 @@ END IF
- Payment failed
```
-**Marketing Emails** (opt-in):
+**Marketing Emails** (opt-in, jamais agressif):
```
- New features announcement
-- Promotional offers
-- Product recommendations
- Weekly digest (new tracks from followed users)
-- Monthly summary (stats, achievements)
+- Monthly summary (stats personnels du créateur)
+Note: Pas de recommandations produit basées sur le comportement.
+ Pas de notifications de type FOMO.
```
**Cadence Limits**:
@@ -872,14 +914,17 @@ Marketing: Max 2/week (user can opt out)
**Batched Notifications** (hourly):
```
-- Multiple likes (5+ likes → "Your track has 5 new likes")
- Multiple comments (3+ comments → "Your track has 3 new comments")
+- Regroupées pour éviter la surcharge
+Note: Pas de compteurs de likes en notification push (anti social validation loop)
```
-**Quiet Hours**:
+**Quiet Hours & Respect du DND**:
```
Default: 22:00 - 08:00 (user's timezone)
User can configure in settings
+Respect du mode "Do Not Disturb" OS
+Contrôle total utilisateur sur chaque type de notification
```
### 8.3 In-App Notifications
@@ -1078,6 +1123,51 @@ IF payout_failed THEN
END IF
```
+## 11. EXCLUSIONS ET RAISONS ÉTHIQUES
+
+Les éléments suivants sont **définitivement exclus** de la logique métier de Veza.
+
+### Cryptomonnaies
+- Aucun paiement en Bitcoin, Ethereum, ou autre cryptomonnaie
+- **Raison** : impact environnemental disproportionné, spéculation, fraude documentée dans le domaine musical
+
+### Publicité
+- Zéro régie publicitaire, zéro pixel de tracking tiers, zéro retargeting
+- **Raison** : la publicité transforme les utilisateurs en produit. Incompatible avec le principe « l'humain d'abord »
+
+### Vente de données
+- Aucune monétisation des données comportementales
+- **Raison** : les données des utilisateurs ne sont pas un produit
+
+### Recommandations ML
+- Pas de collaborative filtering, content-based filtering, ou analyse prédictive du comportement
+- **Raison** : optimise pour la rétention, pas pour la découverte authentique. La découverte musicale est basée sur les genres/tags déclarés par les artistes, la curation éditoriale humaine, et les connexions sociales
+
+### Gamification addictive
+- Pas de systèmes XP, niveaux, streaks, leaderboards de popularité
+- **Raison** : transforme l'expression artistique en compétition et normalise les métriques de performance comme mesure de la valeur artistique
+
+### Freemium agressif
+- Pas de features artificiellement bridées, pas de dark patterns dans les flows d'upgrade
+- **Raison** : les modèles de tarification sont simples et honnêtes
+
+## 12. GOUVERNANCE
+
+### Roadmap publique
+- La roadmap produit est publique et commentable
+- Les utilisateurs peuvent voter sur les features planifiées
+- Les décisions produit majeures sont documentées avec leur justification
+
+### Contribution open source
+- Le cœur de la plateforme est open source
+- Processus de contribution documenté (CONTRIBUTING.md)
+- Code review systématique par les mainteneurs
+
+### Transparence économique
+- Les commissions sont documentées et visibles avant chaque transaction
+- Les conditions d'utilisation sont rédigées en langage humain
+- Les changements tarifaires sont annoncés 90 jours à l'avance
+
## ✅ CHECKLIST DE VALIDATION
### Pricing
@@ -1129,28 +1219,31 @@ END IF
| Version | Date | Changements |
|---------|------|-------------|
| 1.0.0 | 2025-11-02 | Version initiale - Règles métier complètes |
+| 2.0.0 | 2026-03-04 | Révision éthique : suppression crypto/AI/publicité, ajout principes éthiques, modèle open core, gouvernance |
---
## ⚠️ AVERTISSEMENT
-**CES RÈGLES MÉTIER SONT IMMUABLES**
+**CES RÈGLES MÉTIER SONT ALIGNÉES AVEC L'ÉTHIQUE DU PROJET**
-Les règles métier définies ici sont **VERROUILLÉES**. Toute modification nécessite:
+Toute modification nécessite :
-1. **RFC Business Logic Change** avec impact analysis
+1. **RFC Business Logic Change** avec impact analysis et vérification d'alignement éthique
2. **Approbation Product Owner** + Legal (si implications légales)
3. **Migration plan** pour données existantes
4. **Communication** aux utilisateurs (si impact visible)
**Les changements de règles financières nécessitent validation CFO.**
+**Aucune modification ne peut contredire les principes éthiques fondateurs (§0).**
---
**Document créé par**: Product Team + Business Analysts
**Date de création**: 2025-11-02
+**Dernière révision**: 2026-03-04 (révision éthique)
**Prochaine révision**: Trimestrielle
**Propriétaire**: Chief Product Officer
-**Statut**: ✅ **APPROUVÉ ET VERROUILLÉ**
+**Statut**: ✅ **APPROUVÉ — v2.0.0**
diff --git a/veza-docs/ORIGIN/ORIGIN_CODE_STANDARDS.md b/veza-docs/ORIGIN/ORIGIN_CODE_STANDARDS.md
index 02c5b35fd..4a9ffde1b 100644
--- a/veza-docs/ORIGIN/ORIGIN_CODE_STANDARDS.md
+++ b/veza-docs/ORIGIN/ORIGIN_CODE_STANDARDS.md
@@ -19,16 +19,17 @@ Ce document définit les standards de code complets et définitifs pour la plate
## 📖 TABLE DES MATIÈRES
1. [General Principles](#1-general-principles)
-2. [Go Standards (Backend)](#2-go-standards-backend)
-3. [Rust Standards (Services)](#3-rust-standards-services)
-4. [TypeScript Standards (Frontend)](#4-typescript-standards-frontend)
-5. [React Standards](#5-react-standards)
-6. [CSS/Tailwind Standards](#6-csstailwind-standards)
-7. [Git Standards](#7-git-standards)
-8. [Documentation Standards](#8-documentation-standards)
-9. [Code Review Process](#9-code-review-process)
-10. [Refactoring Guidelines](#10-refactoring-guidelines)
-11. [Anti-Patterns Library](#11-anti-patterns-library)
+2. [Standards éthiques du code](#2-standards-éthiques-du-code)
+3. [Go Standards (Backend)](#3-go-standards-backend)
+4. [Rust Standards (Services)](#4-rust-standards-services)
+5. [TypeScript Standards (Frontend)](#5-typescript-standards-frontend)
+6. [React Standards](#6-react-standards)
+7. [CSS/Tailwind Standards](#7-csstailwind-standards)
+8. [Git Standards](#8-git-standards)
+9. [Documentation Standards](#9-documentation-standards)
+10. [Code Review Process](#10-code-review-process)
+11. [Refactoring Guidelines](#11-refactoring-guidelines)
+12. [Anti-Patterns Library](#12-anti-patterns-library)
## 🔒 RÈGLES IMMUABLES
@@ -236,9 +237,83 @@ type Cache interface {
}
```
-## 2. GO STANDARDS (BACKEND)
+## 2. STANDARDS ÉTHIQUES DU CODE
-### 2.1 Project Structure (Clean Architecture)
+### 2.1 Tracking et consentement
+
+**Aucun tracking côté client sans consentement explicite de l'utilisateur.**
+
+Toute collecte de données comportementales (analytics, événements, métriques d'usage) doit être conditionnée à un opt-in explicite. Le consentement ne doit jamais être présumé.
+
+```typescript
+// ❌ Interdit : tracking silencieux
+useEffect(() => {
+ analytics.track('page_view', { page: location.pathname });
+}, [location]);
+
+// ✅ Obligatoire : vérifier le consentement
+useEffect(() => {
+ if (userConsent.analytics) {
+ analytics.track('page_view', { page: location.pathname });
+ }
+}, [location, userConsent.analytics]);
+```
+
+### 2.2 Algorithmes d'exposition de contenu
+
+Tout algorithme influençant la visibilité ou le classement du contenu (feed, recherche, suggestions) **doit être documenté et justifiable**. La documentation doit inclure :
+
+- Les critères de classement et leur pondération
+- L'objectif produit visé (ex : diversité, fraîcheur, pertinence)
+- Les biais potentiels identifiés et les mesures de mitigation
+
+Aucun algorithme opaque n'est autorisé. Les créateurs doivent pouvoir comprendre pourquoi leur contenu est ou n'est pas mis en avant.
+
+### 2.3 Collecte de métriques
+
+**Chaque métrique collectée doit avoir une justification produit documentée.** La collecte préventive ("au cas où on en aurait besoin") est interdite.
+
+```go
+// ❌ Interdit : collecte préventive sans justification
+type TrackEvent struct {
+ TrackID uuid.UUID
+ UserID uuid.UUID
+ ScrollDepth float64 // Pourquoi ?
+ MouseMovement []Point // Pourquoi ?
+ TimeOnPage int // Pourquoi ?
+ DeviceGyro []float64 // Pourquoi ?
+}
+
+// ✅ Obligatoire : chaque champ justifié
+type TrackPlayEvent struct {
+ TrackID uuid.UUID // Identifier le contenu joué
+ ListenTimeMs int64 // Calculer les royalties (seuil 30s)
+ Completed bool // Taux de complétion pour le créateur
+}
+```
+
+### 2.4 Scoring, ranking et diversité
+
+Toute fonction de scoring ou de ranking **doit inclure des tests de non-régression sur la diversité**. Ces tests vérifient que les résultats ne concentrent pas la visibilité sur un sous-ensemble disproportionné de créateurs.
+
+```go
+func TestSearchRanking_Diversity(t *testing.T) {
+ results := searchService.Search(ctx, "electronic music", SearchParams{Limit: 50})
+
+ creatorIDs := make(map[uuid.UUID]bool)
+ for _, r := range results {
+ creatorIDs[r.CreatorID] = true
+ }
+
+ // Les 50 premiers résultats doivent provenir d'au moins 10 créateurs distincts
+ assert.GreaterOrEqual(t, len(creatorIDs), 10,
+ "Les résultats de recherche doivent refléter une diversité minimale de créateurs")
+}
+```
+
+## 3. GO STANDARDS (BACKEND)
+
+### 3.1 Project Structure (Clean Architecture)
```
veza-backend-api/
@@ -286,7 +361,7 @@ veza-backend-api/
└── go.sum
```
-### 2.2 Naming Conventions
+### 3.2 Naming Conventions
**Variables**: camelCase
```go
@@ -327,7 +402,7 @@ type UserRepository interface { // Multi-method, no -er suffix
}
```
-### 2.3 Error Handling
+### 3.3 Error Handling
**Always Check Errors**:
```go
@@ -395,7 +470,7 @@ func init() {
}
```
-### 2.4 Function Design
+### 3.4 Function Design
**Keep Functions Small** (< 50 lines):
```go
@@ -508,7 +583,7 @@ func FindUser(id uuid.UUID) (*User, error) {
}
```
-### 2.5 Concurrency
+### 3.5 Concurrency
**Use Context for Cancellation**:
```go
@@ -598,7 +673,7 @@ func StartWorker(ctx context.Context) {
}
```
-### 2.6 Testing
+### 3.6 Testing
**Table-Driven Tests**:
```go
@@ -676,9 +751,94 @@ func TestUserService_CreateUser(t *testing.T) {
}
```
-## 3. RUST STANDARDS (SERVICES)
+### 3.7 API Standards
-### 3.1 Project Structure
+#### Pagination obligatoire
+
+Toute route retournant une liste **doit** accepter les paramètres `limit` et `offset` et imposer une limite maximale de **100 éléments**.
+
+```go
+const (
+ DefaultPageSize = 20
+ MaxPageSize = 100
+)
+
+func sanitizePagination(limit, offset int) (int, int) {
+ if limit <= 0 || limit > MaxPageSize {
+ limit = DefaultPageSize
+ }
+ if offset < 0 {
+ offset = 0
+ }
+ return limit, offset
+}
+
+// ❌ Interdit : liste sans pagination
+func (h *TrackHandler) ListTracks(c *gin.Context) {
+ tracks, _ := h.service.ListAll(c.Request.Context())
+ c.JSON(200, tracks)
+}
+
+// ✅ Obligatoire : pagination bornée
+func (h *TrackHandler) ListTracks(c *gin.Context) {
+ limit, offset := sanitizePagination(
+ c.GetInt("limit"),
+ c.GetInt("offset"),
+ )
+ tracks, total, err := h.service.List(c.Request.Context(), limit, offset)
+ if err != nil {
+ RespondWithAppError(c, err)
+ return
+ }
+ c.JSON(200, PaginatedResponse{Data: tracks, Total: total, Limit: limit, Offset: offset})
+}
+```
+
+#### Propagation du contexte
+
+**Interdit** d'utiliser `context.Background()` dans les handlers ou les services. Le contexte de la requête HTTP doit être propagé à toutes les couches.
+
+```go
+// ❌ Interdit : context.Background() dans un handler/service
+func (s *TrackService) GetTrack(id uuid.UUID) (*Track, error) {
+ return s.repo.FindByID(context.Background(), id)
+}
+
+// ✅ Obligatoire : propager le contexte de la requête
+func (s *TrackService) GetTrack(ctx context.Context, id uuid.UUID) (*Track, error) {
+ return s.repo.FindByID(ctx, id)
+}
+```
+
+#### Gestion des erreurs standardisée
+
+Tous les handlers **doivent** utiliser `RespondWithAppError` pour les réponses d'erreur. Les réponses `gin.H{"error": ...}` ad hoc sont interdites.
+
+```go
+// ❌ Interdit : réponses d'erreur ad hoc
+func (h *TrackHandler) GetTrack(c *gin.Context) {
+ track, err := h.service.GetTrack(c.Request.Context(), id)
+ if err != nil {
+ c.JSON(500, gin.H{"error": "internal error"})
+ return
+ }
+ c.JSON(200, track)
+}
+
+// ✅ Obligatoire : RespondWithAppError
+func (h *TrackHandler) GetTrack(c *gin.Context) {
+ track, err := h.service.GetTrack(c.Request.Context(), id)
+ if err != nil {
+ RespondWithAppError(c, err)
+ return
+ }
+ c.JSON(200, track)
+}
+```
+
+## 4. RUST STANDARDS (SERVICES)
+
+### 4.1 Project Structure
```
veza-chat-server/
@@ -712,7 +872,7 @@ veza-chat-server/
└── Cargo.lock
```
-### 3.2 Naming Conventions
+### 4.2 Naming Conventions
**Variables/Functions**: snake_case
```rust
@@ -736,7 +896,7 @@ const MAX_CONNECTIONS: usize = 10000;
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {}
```
-### 3.3 Error Handling
+### 4.3 Error Handling
**Use Result Type**:
```rust
@@ -798,7 +958,7 @@ let config = Config::from_env()
.expect("CONFIG environment variables missing");
```
-### 3.4 Ownership & Borrowing
+### 4.4 Ownership & Borrowing
**Prefer Borrowing**:
```rust
@@ -830,7 +990,7 @@ tokio::spawn(async move {
});
```
-### 3.5 Async/Await
+### 4.5 Async/Await
**Use async/await for IO**:
```rust
@@ -871,7 +1031,7 @@ async fn fetch_user_data(user_id: Uuid) -> Result<(User, Vec