V0.701 Release Scope — Retry Transfers, Admin Dashboard & Deep Health
Statut : En cours
Phase : 7 (Production Readiness)
Prérequis : v0.603 (taguée)
Date cible : TBD
Estimation : ~3 sprints (15 jours ouvrés)
Précédente : v0.603
1. Objectif
Première version de la Phase 7 (Production Readiness). Comble les lacunes identifiées en v0.603 : retry automatique des transferts échoués (cron + backoff exponentiel), dashboard admin des transferts (visibilité plateforme), deep health checks (validation infrastructure), et documentation API . Absorbe le backlog v0.604 pertinent.
2. État actuel (post-v0.603)
Composant
État
Détail
Transfer automatique Stripe Connect
✅ Livré v0.603
processSellerTransfers dans ProcessPaymentWebhook
seller_transfers
✅ Livré v0.603
Migration 115, modèle SellerTransfer
GET /sell/transfers
✅ Livré v0.603
Historique vendeur de ses transferts
Retry transferts échoués
❌ Absent
Transferts failed restent en DB sans retry
Admin transfers dashboard
❌ Absent
Aucune vue admin des transferts plateforme
Deep health checks
❌ Absent
GET /health basique (DB uniquement), pas de Redis/S3/config
Documentation API
❌ Absent
Aucune spec OpenAPI, endpoints documentés uniquement dans le code
Validation config startup
❌ Absent
Pas de vérification des configs critiques au démarrage
3. Lots
Lot R1 — Retry automatique des transferts échoués
Objectif : Retenter automatiquement les transferts Stripe Connect qui ont échoué, avec backoff exponentiel et limite de tentatives.
#
Tâche
Fichiers impactés
Effort
R1-01
Migration 116_seller_transfers_retry.sql — ajout colonnes retry_count, max_retries, next_retry_at
migrations/116_seller_transfers_retry.sql
S
R1-02
Mise à jour modèle SellerTransfer — ajout champs retry
internal/core/marketplace/models.go
S
R1-03
Config TRANSFER_RETRY_MAX et TRANSFER_RETRY_INTERVAL_MIN
internal/config/config.go, .env.example
S
R1-04
TransferRetryWorker — goroutine background avec ticker, query transfers failed et retry_count < max, calcul backoff exponentiel, appel CreateTransfer, update status
internal/core/marketplace/transfer_retry.go (nouveau)
L
R1-05
Démarrage du worker dans cmd/server/main.go — optionnel via config TRANSFER_RETRY_ENABLED
cmd/server/main.go
S
R1-06
Prometheus metrics — veza_transfer_retry_total, veza_transfer_retry_success, veza_transfer_retry_failures
internal/monitoring/metrics.go
S
R1-07
Tests unitaires retry — retry success, max retries atteint, backoff calculation
internal/core/marketplace/transfer_retry_test.go (nouveau)
M
Lot A1 — Admin Transfers Dashboard
Objectif : Offrir aux administrateurs une vue complète des transferts plateforme (tous vendeurs), avec filtres et action de retry manuel.
#
Tâche
Fichiers impactés
Effort
A1-01
GET /admin/transfers — liste paginée de tous les SellerTransfer (filtres: status, seller_id, date range)
internal/handlers/admin_handler.go (nouveau ou existant), routes
M
A1-02
POST /admin/transfers/:id/retry — retry manuel d'un transfert failed
internal/handlers/admin_handler.go, routes
S
A1-03
Route admin dans routes_core.go — ajout dans le groupe /admin protégé
internal/api/routes_core.go
S
A1-04
Frontend AdminTransfersView — table avec colonnes (seller, order, montant, fee, status, retry_count, date), badge status, bouton Retry
apps/web/src/components/admin/AdminTransfersView.tsx (nouveau)
L
A1-05
Frontend route /admin/transfers — ajout dans routeConfig
apps/web/src/router/routeConfig.tsx
S
A1-06
Service frontend getAdminTransfers, retryAdminTransfer
apps/web/src/services/commerceService.ts
S
A1-07
MSW handlers — mock GET /admin/transfers, POST /admin/transfers/:id/retry
apps/web/src/mocks/handlers-marketplace.ts
S
A1-08
Story AdminTransfersView.stories.tsx — états Loading, Default, Empty, WithFailedTransfers
apps/web/src/components/admin/AdminTransfersView.stories.tsx (nouveau)
M
A1-09
Tests unitaires — admin handler GET + POST retry, authorization check
internal/handlers/admin_handler_test.go (nouveau)
M
Lot H1 — Deep Health Checks & Startup Validation
Objectif : Fournir un endpoint de santé détaillé pour les load balancers et le monitoring, et valider la configuration critique au démarrage.
#
Tâche
Fichiers impactés
Effort
H1-01
GET /health/deep — check DB (ping), Redis (ping), S3 (HEAD bucket), disk space, config validity
internal/api/routes_health.go (nouveau)
M
H1-02
Réponse structurée JSON — status global (healthy/degraded/unhealthy) + status individuel par service
internal/api/routes_health.go
S
H1-03
Startup config validation — vérifier au boot : JWT_SECRET non vide, DATABASE_URL valide, PLATFORM_FEE_RATE dans [0,1], ports non conflictuels
internal/config/validate.go (nouveau)
M
H1-04
Prometheus metrics — veza_health_check_status gauge (1=healthy, 0=unhealthy) par service
internal/monitoring/metrics.go
S
H1-05
Tests unitaires — deep health check avec services mockés (all healthy, partial degradation, all down)
internal/api/routes_health_test.go (nouveau)
M
Lot D1 — Documentation API & Nettoyage
Objectif : Documenter les endpoints API pour faciliter l'intégration et réduire la dette documentaire.
#
Tâche
Fichiers impactés
Effort
D1-01
docs/API_REFERENCE.md — documentation des endpoints clés (auth, marketplace, seller, admin, health) avec exemples curl
docs/API_REFERENCE.md (nouveau)
L
D1-02
Mise à jour docs/MIGRATIONS.md — ajouter migration 116
docs/MIGRATIONS.md
S
D1-03
Archiver V0_604_RELEASE_SCOPE.md — placeholder absorbé par v0.701
docs/V0_604_RELEASE_SCOPE.md → docs/archive/
S
Lot QA1 — Tests & Release
Objectif : Valider les nouveaux composants, documenter, tagger.
#
Tâche
Fichiers impactés
Effort
QA1-01
Test E2E retry — transfer failed → worker retry → status completed
Tests
M
QA1-02
Test admin endpoint — authorization check (non-admin = 403)
Tests
S
QA1-03
Smoke test v0.701 — checklist complète
docs/SMOKE_TEST_V0701.md
S
QA1-04
Mise à jour PROJECT_STATE, FEATURE_STATUS, CHANGELOG
docs/
S
QA1-05
Rétrospective v0.701, archivage scope, placeholder v0.702, tag
docs/, Git
S
4. Hors scope v0.701
Élément
Version cible
Go Live (streaming vidéo)
v0.703
2FA SMS / Passkeys
v0.104
IaC (Terraform/Pulumi)
v0.801
Payout scheduling (cron récurrent)
v0.702
Commission par vendeur/catégorie
v0.702
OpenAPI/Swagger auto-génération (swaggo)
v0.702
Load testing service (k6/vegeta intégré)
v0.703
Frontend E2E test fixes (Playwright)
v0.702
5. Détail technique — Lot R1
5.1 Migration 116_seller_transfers_retry.sql
ALTER TABLE seller_transfers
ADD COLUMN IF NOT EXISTS retry_count INTEGER NOT NULL DEFAULT 0 ,
ADD COLUMN IF NOT EXISTS max_retries INTEGER NOT NULL DEFAULT 3 ,
ADD COLUMN IF NOT EXISTS next_retry_at TIMESTAMPTZ ;
CREATE INDEX IF NOT EXISTS idx_seller_transfers_retry
ON seller_transfers ( status , next_retry_at )
WHERE status = 'failed' AND next_retry_at IS NOT NULL ;
5.2 Modèle SellerTransfer mis à jour
type SellerTransfer struct {
// ... champs existants v0.603 ...
RetryCount int `gorm:"default:0" json:"retry_count"`
MaxRetries int `gorm:"default:3" json:"max_retries"`
NextRetryAt * time . Time `json:"next_retry_at,omitempty"`
}
5.3 TransferRetryWorker
type TransferRetryWorker struct {
db * gorm . DB
transferService TransferService
logger * zap . Logger
interval time . Duration // ticker interval (e.g. 5 min)
maxRetries int
baseDelay time . Duration // base delay for exponential backoff (e.g. 5 min)
}
func ( w * TransferRetryWorker ) Start ( ctx context . Context ) {
ticker := time . NewTicker ( w . interval )
defer ticker . Stop ()
for {
select {
case <- ctx . Done ():
return
case <- ticker . C :
w . processRetries ( ctx )
}
}
}
func ( w * TransferRetryWorker ) processRetries ( ctx context . Context ) {
var transfers [] SellerTransfer
w . db . Where ( "status = ? AND retry_count < max_retries AND (next_retry_at IS NULL OR next_retry_at <= ?)" ,
"failed" , time . Now ()).
Find ( & transfers )
for _ , t := range transfers {
err := w . transferService . CreateTransfer ( ctx , t . SellerID , t . AmountCents , t . Currency , t . OrderID . String ())
if err != nil {
t . RetryCount ++
delay := w . baseDelay * time . Duration ( 1 << uint ( t . RetryCount )) // exponential backoff
nextRetry := time . Now (). Add ( delay )
t . NextRetryAt = & nextRetry
if t . RetryCount >= t . MaxRetries {
t . Status = "permanently_failed"
}
t . ErrorMessage = err . Error ()
} else {
t . Status = "completed"
t . NextRetryAt = nil
}
w . db . Save ( & t )
}
}
5.4 Backoff exponentiel
Retry
Délai (base = 5 min)
1
10 min
2
20 min
3
40 min (max atteint → permanently_failed)
5.5 Statuts des transferts
Status
Description
pending
Transfert en cours de traitement
completed
Transfert Stripe réussi
failed
Transfert échoué, retry possible
permanently_failed
Max retries atteint, intervention manuelle requise
skipped
Vendeur sans compte Connect
6. Détail technique — Lot H1
6.1 GET /health/deep — Réponse
{
"status" : "healthy" ,
"timestamp" : "2026-02-23T12:00:00Z" ,
"services" : {
"database" : { "status" : "healthy" , "latency_ms" : 2 },
"redis" : { "status" : "healthy" , "latency_ms" : 1 },
"s3" : { "status" : "degraded" , "error" : "bucket unreachable" },
"disk" : { "status" : "healthy" , "free_gb" : 42.5 }
},
"config" : {
"jwt_secret_set" : true ,
"stripe_connect_enabled" : true ,
"platform_fee_rate" : 0.10 ,
"transfer_retry_enabled" : true
}
}
6.2 Logique de status global
healthy : tous les services OK
degraded : un ou plusieurs services non-critiques en erreur (S3, Redis)
unhealthy : service critique en erreur (DB)
6.3 Startup validation
Au démarrage du serveur (cmd/server/main.go), avant d'ouvrir les ports :
JWT_SECRET non vide et longueur >= 32 caractères
DATABASE_URL parse OK et ping réussit
PLATFORM_FEE_RATE dans [0, 1]
Si STRIPE_CONNECT_ENABLED=true : STRIPE_SECRET_KEY et STRIPE_CONNECT_CLIENT_ID non vides
Si TRANSFER_RETRY_ENABLED=true : TRANSFER_RETRY_MAX >= 1
En cas d'échec critique (DB, JWT_SECRET) : log fatal + exit. En cas d'échec non-critique : log warning, continuer.
7. Fichiers impactés (récapitulatif)
Backend Go (nouveau)
Fichier
Action
migrations/116_seller_transfers_retry.sql
Nouveau — colonnes retry pour seller_transfers
internal/core/marketplace/transfer_retry.go
Nouveau — TransferRetryWorker goroutine
internal/core/marketplace/transfer_retry_test.go
Nouveau — tests retry
internal/api/routes_health.go
Nouveau — GET /health/deep
internal/api/routes_health_test.go
Nouveau — tests deep health
internal/config/validate.go
Nouveau — startup config validation
internal/handlers/admin_handler.go
Nouveau — GET /admin/transfers, POST retry
internal/handlers/admin_handler_test.go
Nouveau — tests admin handler
Backend Go (modifier)
Fichier
Action
internal/config/config.go
Ajout TransferRetryEnabled, TransferRetryMax, TransferRetryIntervalMin
internal/core/marketplace/models.go
Ajout champs retry à SellerTransfer
internal/api/routes_core.go
Ajout routes admin transfers
internal/monitoring/metrics.go
Ajout métriques retry + health
cmd/server/main.go
Démarrage TransferRetryWorker, startup validation
.env.example
Documenter variables retry
Frontend (nouveau)
Fichier
Action
apps/web/src/components/admin/AdminTransfersView.tsx
Nouveau — dashboard admin transferts
apps/web/src/components/admin/AdminTransfersView.stories.tsx
Nouveau — stories
Frontend (modifier)
Fichier
Action
apps/web/src/services/commerceService.ts
Ajout getAdminTransfers, retryAdminTransfer
apps/web/src/router/routeConfig.tsx
Ajout route /admin/transfers
apps/web/src/mocks/handlers-marketplace.ts
Handlers admin transfers
Documentation
Fichier
Action
docs/API_REFERENCE.md
Nouveau — référence API
docs/SMOKE_TEST_V0701.md
Nouveau — checklist validation
docs/MIGRATIONS.md
Ajout migration 116
docs/PROJECT_STATE.md
Section v0.701
docs/FEATURE_STATUS.md
Mise à jour
CHANGELOG.md
Section v0.701
docs/RETROSPECTIVE_V0701.md
Nouveau (fin de release)
8. Critères d'acceptation globaux
Retry auto : transfer failed → worker retry → status completed après succès
Backoff exponentiel : délai entre retries augmente (5min, 10min, 20min)
Max retries : après 3 échecs → permanently_failed, plus de retry
Admin GET /admin/transfers : liste paginée de tous les transferts, filtres status/seller/date
Admin POST /admin/transfers/:id/retry : retry manuel, 403 si non-admin
Frontend AdminTransfersView : table avec badge status, bouton Retry, états Loading/Empty
Deep health : GET /health/deep retourne status de DB, Redis, S3, disk
Health degraded : S3 down → status degraded (pas unhealthy)
Startup validation : JWT_SECRET vide → exit fatal au boot
Prometheus : métriques retry (total, success, failures) et health exposées
API Reference : documentation des endpoints clés avec exemples curl
Tag v0.701 créé
9. Risques
Risque
Mitigation
Worker retry en conflit avec webhook simultané
Vérifier status avant retry (skip si completed) + row locking
Backoff trop agressif (40 min max)
Configurable via env ; admin retry manuel en fallback
Deep health check lourd (S3 HEAD)
Cache résultat 30s, ne pas appeler à chaque request
Admin endpoint sans pagination
Pagination obligatoire (limit/offset, default 50)
Startup validation trop stricte bloque le dev
Env-dependent : strict en prod, warning en dev
10. Architecture
graph TD
A[ProcessPaymentWebhook] --> B{Transfer Stripe}
B -->|Success| C[SellerTransfer status=completed]
B -->|Failure| D[SellerTransfer status=failed]
D --> E[TransferRetryWorker]
E -->|Ticker 5min| F{Query failed transfers}
F --> G{retry_count < max?}
G -->|Yes| H[CreateTransfer]
H -->|Success| C
H -->|Failure| I[retry_count++, backoff, next_retry_at]
G -->|No| J[status=permanently_failed]
K[Admin] --> L[GET /admin/transfers]
K --> M[POST /admin/transfers/:id/retry]
M --> H
N[Load Balancer] --> O[GET /health/deep]
O --> P{DB ping}
O --> Q{Redis ping}
O --> R{S3 HEAD}
O --> S{Disk space}
11. Références