- V0_601_RELEASE_SCOPE.md: lots INF1, COM1, AUTH1, CLN1, QA1 - PLAN_V0_601_IMPLEMENTATION.md: 6 sprints, tâches détaillées, commits - PROJECT_STATE.md: prochaine version v0.601 - FEATURE_STATUS.md: section Prévu en v0.601 - SCOPE_CONTROL.md: référence V0_601_RELEASE_SCOPE
427 lines
12 KiB
Markdown
427 lines
12 KiB
Markdown
# 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 |
|