# Plan d'implémentation v0.601 — Production Readiness & Commerce **Date** : 2026-02-22 **Base** : v0.503 taguée **Durée estimée** : 6 sprints (~30 jours ouvrés) **Référence** : [V0_601_RELEASE_SCOPE.md](V0_601_RELEASE_SCOPE.md) --- ## Vue d'ensemble ``` Sprint 1 (j1-5) → INF1 : Infrastructure Production (blue-green, Grafana, health) Sprint 2 (j6-10) → COM1 : Commerce (reviews, factures, remboursements, Hyperswitch prod) Sprint 3 (j11-15) → AUTH1 : OAuth Discord & Spotify Sprint 4 (j16-22) → CLN1 : Dette technique (découpage handler, interceptors, migrations) Sprint 5 (j23-27) → QA1 : Tests E2E, smoke test, documentation Sprint 6 (j28-30) → QA2 : Rétrospective, tag v0.601 ``` --- ## Diagramme d'architecture cible ```mermaid flowchart TD subgraph LB["Load Balancer"] HAProxy["HAProxy Blue-Green"] end subgraph Blue["Blue Stack"] API1["veza-backend-api"] Stream1["veza-stream-server"] end subgraph Green["Green Stack"] API2["veza-backend-api"] Stream2["veza-stream-server"] end subgraph Monitor["Monitoring"] Prometheus["Prometheus"] Grafana["Grafana Dashboards"] Alertmanager["Alertmanager"] end subgraph Commerce["Commerce"] Reviews["Reviews API"] Invoice["Invoice PDF"] Refund["Refund API"] end HAProxy --> Blue HAProxy --> Green API1 --> Prometheus API2 --> Prometheus Prometheus --> Grafana Prometheus --> Alertmanager API1 --> Reviews API1 --> Invoice API1 --> Refund ``` --- ## Sprint 1 — Infrastructure Production (jours 1-5) > **Objectif** : Blue-green deployment, dashboards Grafana, health check enrichi, graceful shutdown. ### Tâche INF1-01 : Blue-green deployment **Fichiers** : - `config/haproxy/haproxy.cfg` — ajouter backends blue/green, health checks - `config/caddy/Caddyfile.staging` — alternative si Caddy utilisé - `docker-compose.prod.yml` — deux stacks (blue, green) - `scripts/deploy-blue-green.sh` — script bascule manuelle **Exemple HAProxy** : ```haproxy backend api_blue balance roundrobin option httpchk GET /api/v1/health http-check expect status 200 server api1 api-blue:8080 check backend api_green balance roundrobin option httpchk GET /api/v1/health http-check expect status 200 server api1 api-green:8080 check ``` ### Tâche INF1-02 : Dashboards Grafana **Fichiers** : - `config/grafana/dashboards/api-overview.json` — latence, erreurs, throughput - `config/grafana/dashboards/chat-overview.json` — connexions WS, messages/s - `config/grafana/dashboards/commerce-overview.json` — orders, checkout, refunds **Validation** : Dashboards chargent les métriques Prometheus existantes. ### Tâche INF1-03 : Alertmanager **Fichier** : `config/alertmanager/alertmanager.yml` ```yaml route: receiver: 'slack-default' group_by: ['alertname'] receivers: - name: 'slack-default' slack_configs: - api_url: '${SLACK_WEBHOOK_URL}' channel: '#alerts' ``` ### Tâche INF1-04 : Graceful shutdown **Fichier** : `veza-backend-api/cmd/api/main.go` ```go srv := &http.Server{Addr: ":" + port, Handler: router} go func() { if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { log.Fatal(err) } }() quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() if err := srv.Shutdown(ctx); err != nil { log.Fatal("Server forced to shutdown:", err) } ``` **Fichier** : `veza-stream-server/src/main.rs` — gérer SIGTERM, drain connexions. ### Tâche INF1-05 : Health check enrichi **Fichier** : `veza-backend-api/internal/handlers/health.go` ```go type HealthResponse struct { Status string `json:"status"` // "ok" | "degraded" DB string `json:"db"` Redis string `json:"redis"` RabbitMQ string `json:"rabbitmq,omitempty"` Checks map[string]string `json:"checks"` } ``` **Validation Sprint 1** : ```bash cd veza-backend-api && go build ./... curl -s http://localhost:8080/api/v1/health | jq ``` **Commit Sprint 1** : `feat(infra): blue-green deployment, Grafana dashboards, enriched health check, graceful shutdown` --- ## Sprint 2 — Commerce Finalisation (jours 6-10) > **Objectif** : Reviews produits, factures PDF, remboursements, Hyperswitch production. ### Tâche COM1-01 : Reviews produits **Migration** : `veza-backend-api/migrations/114_product_reviews.sql` ```sql CREATE TABLE IF NOT EXISTS product_reviews ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), product_id UUID NOT NULL REFERENCES products(id) ON DELETE CASCADE, user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, rating INT NOT NULL CHECK (rating >= 1 AND rating <= 5), comment TEXT, created_at TIMESTAMPTZ DEFAULT NOW(), UNIQUE(product_id, user_id) ); CREATE INDEX idx_product_reviews_product ON product_reviews(product_id); ``` **Fichiers** : - `internal/models/product_review.go` — modèle GORM - `internal/repositories/product_review_repository.go` — CRUD - `internal/handlers/marketplace_handler.go` — POST/GET reviews, GET moyenne - Frontend : `ProductDetail` — affichage reviews, formulaire ### Tâche COM1-02 : Factures PDF **Fichier** : `veza-backend-api/internal/services/invoice_service.go` - Lib : `github.com/jung-kurt/gofpdf` ou `github.com/signintech/gopdf` - Template : numéro facture, date, items, total, TVA - `GET /api/v1/orders/:id/invoice` — génère et retourne PDF **Frontend** : bouton « Télécharger facture » dans OrdersView. ### Tâche COM1-03 : Remboursements **Fichiers** : - `internal/models/order.go` — champ `refund_status` - `internal/handlers/marketplace_handler.go` — `POST /orders/:id/refund` - `internal/services/hyperswitch_service.go` — appel Hyperswitch refund API - Webhook : traiter `refund.succeeded`, mettre à jour order, révoquer licence ### Tâche COM1-04 : Hyperswitch production **Fichier** : `veza-backend-api/internal/config/config.go` ```go HyperswitchLiveMode bool // HYPERSWITCH_LIVE_MODE HyperswitchSecret string // Webhook secret pour validation ``` ### Tâche COM1-05 : MSW + Stories **Fichiers** : - `apps/web/src/mocks/handlers.ts` — handlers reviews, invoice, refund - `apps/web/src/features/` — stories ProductReviews, InvoiceDownload, RefundButton **Validation Sprint 2** : ```bash cd veza-backend-api && go test ./internal/... -v -count=1 -run Commerce cd apps/web && npm run build ``` **Commit Sprint 2** : `feat(commerce): product reviews, PDF invoices, refunds, Hyperswitch production mode` --- ## Sprint 3 — OAuth Discord & Spotify (jours 11-15) > **Objectif** : Implémenter les providers OAuth manquants. ### Tâche AUTH1-01 : OAuth Discord **Fichier** : `veza-backend-api/internal/services/oauth_service.go` - Config : `DISCORD_CLIENT_ID`, `DISCORD_CLIENT_SECRET`, `DISCORD_REDIRECT_URI` - Scopes : `identify`, `email` - Callback : `GET /auth/discord/callback` - Mapping : `discord_id` → user, création si nouveau ### Tâche AUTH1-02 : OAuth Spotify **Fichier** : `veza-backend-api/internal/services/oauth_service.go` - Config : `SPOTIFY_CLIENT_ID`, `SPOTIFY_CLIENT_SECRET`, `SPOTIFY_REDIRECT_URI` - Scopes : `user-read-email` - Callback : `GET /auth/spotify/callback` ### Tâche AUTH1-03 : Tests OAuth **Fichiers** : `internal/services/oauth_discord_test.go`, `oauth_spotify_test.go` ### Tâche AUTH1-04 : FEATURE_STATUS **Fichier** : `docs/FEATURE_STATUS.md` — OAuth Discord/Spotify → opérationnel **Validation Sprint 3** : ```bash cd veza-backend-api && go test ./internal/services/... -v -run OAuth ``` **Commit Sprint 3** : `feat(auth): OAuth Discord and Spotify providers` --- ## Sprint 4 — Dette Technique (jours 16-22) > **Objectif** : Découper handler.go, interceptors.ts, consolidation migrations. ### Tâche CLN1-01 : Découper handler.go (track) **Fichier actuel** : `veza-backend-api/internal/core/track/handler.go` (~1463 LOC) **Découpage** : - `track_crud_handler.go` — ListTracks, GetTrack, UpdateTrack, DeleteTrack, BatchDelete, BatchUpdate - `track_social_handler.go` — LikeTrack, UnlikeTrack, GetTrackLikes, GetUserLikedTracks, CreateShare, GetSharedTrack, RevokeShare - `track_search_handler.go` — SearchTracks, GetRecommendations, GetSuggestedTags - `track_analytics_handler.go` — GetTrackStats, GetTrackHistory, RecordPlay - `handler.go` — facade, getUserID, respondWithError, délégation **Objectif** : `handler.go` < 500 LOC. ### Tâche CLN1-02 : Découper interceptors.ts **Fichier actuel** : `apps/web/src/services/api/interceptors.ts` (~1207 LOC) **Découpage** : - `interceptors/auth.ts` — auth interceptor, token refresh - `interceptors/error.ts` — error handling, retry - `interceptors/logging.ts` — request/response logging - `interceptors/index.ts` — re-export, composition **Objectif** : chaque fichier < 400 LOC. ### Tâche CLN1-03 : Consolidation migrations **Fichier** : `scripts/squash_migrations.sh` ```bash #!/bin/bash # Génère une baseline SQL à partir de toutes les migrations OUT=veza-backend-api/migrations/baseline.sql cat veza-backend-api/migrations/*.sql | grep -v '^--' > "$OUT" echo "Baseline: $(wc -l < "$OUT") lines" ``` **Fichier** : `docs/MIGRATIONS.md` — documenter le processus, usage baseline. ### Tâche CLN1-04 : Audit console.log **Commande** : `rg 'console\.log' apps/web/src --type-add 'ts:*.{ts,tsx}' -t ts -l` Remplacer par : `import { logger } from '@/utils/logger'` puis `logger.debug(...)`. **Validation Sprint 4** : ```bash cd veza-backend-api && go test ./internal/core/track/... -v cd apps/web && npm run build ``` **Commit Sprint 4** : `refactor: split track handler and interceptors, add migration baseline script` --- ## Sprint 5 — Tests, Documentation (jours 23-27) ### Tâche QA1-01 : Tests E2E commerce **Fichier** : `veza-backend-api/internal/integration/e2e_commerce_test.go` Flow : upload → achat → review → facture → remboursement (optionnel). ### Tâche QA1-02 : Smoke test v0.601 **Fichier** : `docs/SMOKE_TEST_V0601.md` Checklist : - [ ] Blue-green : bascule manuelle OK - [ ] Health : DB, Redis, RabbitMQ (degraded si un down) - [ ] Grafana : 3 dashboards chargent - [ ] Reviews : création, affichage, moyenne - [ ] Facture : téléchargement PDF - [ ] Remboursement : initiation refund - [ ] OAuth Discord : login - [ ] OAuth Spotify : login - [ ] track handler : < 500 LOC - [ ] interceptors : < 400 LOC par fichier ### Tâche QA1-03 : Mise à jour docs **Fichiers** : - `docs/PROJECT_STATE.md` — section v0.601 livrée - `docs/FEATURE_STATUS.md` — OAuth Discord/Spotify → opérationnel - `CHANGELOG.md` — section v0.601 ### Tâche QA1-04 : Archiver scope, placeholder v0.602 - Déplacer `V0_601_RELEASE_SCOPE.md` → `docs/archive/` - Créer placeholder `V0_602_RELEASE_SCOPE.md` ### Tâche QA1-05 : Rétrospective **Fichier** : `docs/RETROSPECTIVE_V0601.md` **Commit Sprint 5** : `docs(v0.601): smoke test, changelog, retrospective` --- ## Sprint 6 — Tag v0.601 (jours 28-30) ### Tâche QA2-01 : Tag ```bash git tag -a v0.601 -m "v0.601 — Production Readiness & Commerce" ``` ### Tâche QA2-02 : Mise à jour SCOPE_CONTROL **Fichier** : `docs/SCOPE_CONTROL.md` — référence active → V0_602_RELEASE_SCOPE.md **Commit Sprint 6** : `chore(release): tag v0.601` --- ## Commits récapitulatifs | Sprint | Commit | |--------|--------| | 1 | `feat(infra): blue-green deployment, Grafana dashboards, enriched health check, graceful shutdown` | | 2 | `feat(commerce): product reviews, PDF invoices, refunds, Hyperswitch production mode` | | 3 | `feat(auth): OAuth Discord and Spotify providers` | | 4 | `refactor: split track handler and interceptors, add migration baseline script` | | 5 | `docs(v0.601): smoke test, changelog, retrospective` | | 6 | `chore(release): tag v0.601` | --- ## Dépendances entre lots ``` INF1 (Infra) → indépendant COM1 (Commerce) → indépendant AUTH1 (OAuth) → indépendant CLN1 (Dette) → indépendant (peut être fait en parallèle avec INF1/COM1/AUTH1) QA1 (Tests) → dépend de INF1, COM1, AUTH1, CLN1 QA2 (Tag) → dépend de QA1 ``` --- ## Risques et mitigations | Risque | Mitigation | |--------|------------| | Stripe Connect / Payout complexe | Reporté en v0.602, focus reviews/factures/remboursements | | Génération PDF lourde | Utiliser gofpdf, génération async si besoin | | Blue-green 2x ressources | Documenter option rolling si ressources limitées | | OAuth quotas Discord/Spotify | Documenter limites, rate limiting côté provider |