veza/FUNCTIONAL_AUDIT.md
senke 778c85508b
Some checks failed
Veza CI / Backend (Go) (push) Failing after 0s
Veza CI / Frontend (Web) (push) Failing after 0s
Veza CI / Rust (Stream Server) (push) Failing after 0s
Frontend CI / test (push) Failing after 0s
Security Scan / Secret Scanning (gitleaks) (push) Failing after 0s
Veza CI / Notify on failure (push) Failing after 0s
docs(audit): reconcile top-15 priorities with tier 1-3 + BFG pass
Updates AUDIT_REPORT §9/§9.bis/§9.3/§10 and FUNCTIONAL_AUDIT §7 to
reflect the 2026-04-23 cleanup session + git-filter-repo history rewrite.

Top-15 outcome:
- 10 items DONE with commit refs (b5281bec transactions, ebf3276d rate
  limiter, 4310dbb7 MinIO pin, 172581ff orphan removal, 18eed3c4
  deprecated handlers, d12b901d debris untrack, BFG for #1/#2/#7).
- 3 items flagged FALSE-POSITIVE after direct code inspection (§9.bis):
    #4 context.Background: 26/31 in _test.go, 5 legit (WS pumps, health)
    #5 CSP/XFO: already complete in middleware/security_headers.go
    #10 RespondWithAppError: intentional thin wrapper (handlers pkg)
- 2 deferred to v1.0.8 (#8 OpenAPI typegen, #14 E2E CI).
- 1 remaining before v1.0.7 final: #15 docs/ENV_VARIABLES.md sync.

Repo hygiene: .git 2.3 GB → 66 MB (−97%) after BFG pass, force-push
stages 1+2 OK, fingerprint match on Forgejo CA cert.

Annexe: diff table expanded v1 ↔ v2 ↔ v3.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 14:20:28 +02:00

43 KiB
Raw Permalink Blame History

FUNCTIONAL_AUDIT v2 — Veza, ce qu'un utilisateur peut RÉELLEMENT faire

Date : 2026-04-19 Branche : main (HEAD = 89a52944e, v1.0.7-rc1) Auditeur : Claude Code (Opus 4.7 — mode autonome, /effort max, /plan) Méthode : 5 agents Explore en parallèle + vérifications ponctuelles directes + relecture de docs/audit-2026-04/v107-plan.md et CHANGELOG.md. Trace statique (pas de runtime), comme v1. Supersede : v1 du 2026-04-16. La v1 listait 1 🔴 + 9 🟡. Entre le 16 et aujourd'hui, v1.0.5 → v1.0.7-rc1 ont shippé (50+ commits, la majorité ciblant exactement les findings v1). Ton : brutal, sans langue de bois. Citations fichier:ligne.


0. Résumé en 5 lignes

  1. Le bloqueur 🔴 Player de la v1 est résolu. Un endpoint direct /api/v1/tracks/:id/stream avec support Range (routes_tracks.go:118-120) sert l'audio sans HLS. Le middleware bypass cache (response_cache.go:87-104, commit b875efcff) permet le range-request. Le player frontend tombe automatiquement sur /stream si HLS échoue (playerService.ts:280-293). HLS_STREAMING=false reste le default (config.go:355) mais ce n'est plus un blocker : l'audio sort.
  2. Inscription / vérification email : cassée en v1, corrigée. IsVerified: false (core/auth/service.go:200), VerifyEmail endpoint réellement vivant, login gate 403 sur unverified (service.go:527), MailHog branché par défaut dans docker-compose.dev.yml, SMTP env schema unifié (commit 066144352). Tout le parcours register → mail → click → login fonctionne.
  3. Paiements solidifiés de façon massive. Refund fait reverse-charge Hyperswitch avec idempotency-key (service.go:1297-1436). Reconciliation worker sweep les stuck orders/refunds/orphans (reconcile_hyperswitch.go:55-150). Webhook raw payload audit (webhook_log.go). 5 gauges Prometheus ledger-health + 3 alert rules. Dev bypass persiste (simulated payment si HYPERSWITCH_ENABLED=false, service.go:550-586) mais Config.Validate refuse de booter en prod sans Hyperswitch (config.go:908-910). Fail-closed en prod, fail-open en dev.
  4. Points rugueux restants : (a) WebRTC 1:1 sans STUN/TURN — signaling mais NAT traversal HS en prod ; (b) Stockage local disque only — le code S3/MinIO existe mais n'est pas wiré dans l'upload path ; (c) HLS toujours off par défaut → pas d'adaptive bitrate out-of-the-box ; (d) Transcoding dual-trigger (gRPC Rust + RabbitMQ) — redondance non documentée.
  5. Verdict : Veza v1.0.7-rc1 est prêt pour une démo publique contrôlée (un seul pod, infra dev, Hyperswitch sandbox). Pour un déploiement prod multi-pod avec utilisateurs réels il manque : MinIO wiré, STUN/TURN pour les calls, et la documentation d'exploitation des gauges ledger-health. La surface "un utilisateur lambda peut register → verify → upload → play → acheter → rembourser" est entièrement opérationnelle.

1. Tableau des features — verdict réel au 2026-04-19

Légende : COMPLET câblé de bout-en-bout · 🟡 PARTIEL gotchas exploitables · 🔴 FAÇADE UI sans backend réel · ABSENT.

# Feature Verdict v1 Détail + citation
1 Register / Login / JWT / Refresh 🟡 IsVerified: false (core/auth/service.go:200). Login 403 si unverified (service.go:527). JWT RS256 prod / HS256 dev.
2 Verify email 🔴 POST /auth/verify-email actif (routes_auth.go:103-107). Token généré + stocké en DB, email envoyé via MailHog par défaut.
3 Forgot / Reset password 🟡 password_reset_handler.go:67-250. Token en DB avec expiry, invalide toutes les sessions à l'usage.
4 2FA TOTP internal/handlers/two_factor_handler.go:171. Obligatoire pour admin.
5 OAuth (Google/GitHub/Discord/Spotify) routes_auth.go:122-176.
6 Profils utilisateur + slug / username profile_handler.go:102.
7 Upload de tracks 🟡 🟡 ClamAV sync (fail-secure par défaut, upload_validator.go:87-88). Stockage local disque (track_upload_handler.go:376). Dual trigger transcoding (gRPC + RabbitMQ) non doc.
8 CRUD Tracks / Library List / filtres / pagination réels. Library filtrée sur status=Completed.
9 Player + Queue + écoute audio 🔴 🔴 : /tracks/:id/stream avec Range (routes_tracks.go:118-120, track_hls_handler.go:266). Cache bypass wiré (response_cache.go:87-104). HLS optionnel, off par défaut.
10 Playlists (CRUD + share par token) playlist_handler.go:43.
11 Queue collaborative (host-authority) queue_handler.go.
12 Chat WebSocket (messages, typing, reactions, attachments) 🟡 DB persist avant broadcast (handler_messages.go:91-113). 12 features wirées (edit/delete/typing/read/delivered/reactions/attachments/search/convos/channel/DM/calls).
13 Chat multi-instance 🟡 🟡 : Redis pubsub + fallback in-memory avec log ERROR loud (chat_pubsub.go:23-27, 48). Plus de silent fail.
14 WebRTC 1:1 calls 🟡 🟡 Signaling (handler.go:89-98). STUN/TURN absent — pas d'env var, pas de grep hit. NAT symétrique = call HS.
15 Co-listening (listen-together) colistening/hub.go:104-148, host-authority, keepalive 30s.
16 Livestream (RTMP ingest) 🟡 🟡 : /api/v1/live/health (live_health_handler.go:78-96) + banner UI (useLiveHealth.ts:41-61, commit 64fa0c9ac). Plus de silent OBS fail.
17 Livestream viewer playback HLS via nginx-rtmp (live_stream_callback.go:66). URL dans streamURL.
18 Dashboard /api/v1/dashboard.
19 Recherche (unifiée + tracks) search_handlers.go:41 — ES puis fallback Postgres LIKE + pg_trgm.
20 Social / Feed / Posts / Groups social.go:161, chronologique.
21 Discover (genres/tags déclaratifs) discover.go:49-63.
22 Presence + rich presence presence_handler.go:30-46.
23 Notifications + Web Push notification_handlers.go:197.
24 Marketplace + checkout 🟡 Hyperswitch wiré (service.go:522-548). Simulated payment si dev (:550-586) mais Config.Validate refuse prod sans Hyperswitch (config.go:908-910). Cart côté server .
25 Refund (reverse-charge) 🟡 🟡 : 3 phases avec idempotency-key refund.ID (service.go:1297-1436, commits 4f15cfbd9 959031667). Webhook handler wiré.
26 Hyperswitch reconciliation sweep (nouveauté v1.0.7) : reconcile_hyperswitch.go:55-150 couvre stuck orders/refunds/orphans, 10 tests green.
27 Webhook raw payload audit log (v1.0.7) : webhook_log.go:34-80 + cleanup 90j (cleanup_hyperswitch_webhook_log.go).
28 Ledger-health metrics + alerts (v1.0.7 item F) : 5 gauges Prometheus + 3 alert rules Alertmanager + dashboard Grafana.
29 Seller dashboard + Stripe Connect payout sell_handler.go, transfer auto post-webhook.
30 Stripe Connect reversal (async) 🟡 🟡 (v1.0.7 items A+B) : reversal_worker.go:12-180, state machine reversal_pending, stripe_transfer_id persisté, exp. backoff 1m→1h.
31 Reviews / Factures DB + handlers wirés.
32 Subscription plans 🟡 🟡 (v1.0.6.2 hotfix d31f5733d) : hasEffectivePayment() gate (subscription/service.go:140-155). Plus de bypass.
33 Distribution plateformes externes distribution_handler.go:32-62.
34 Formation / Education education_handler.go:33 — DB-backed.
35 Support tickets support_handler.go:54-100.
36 Developer portal (API keys + webhooks) routes_developer.go:11.
37 Analytics (creator stats) playback_analytics_handler.go, CSV/JSON export.
38 Admin — dashboard / users / modération / flags / audit 🟡 admin/handler.go:43-54. Maintenance mode 🟡 via platform_settings + TTL 10s (middleware/maintenance.go:16-100, commit 3a95e38fd).
39 Admin — transfers (v0.701) admin_transfer_handler.go:36-91.
40 Self-service creator role upgrade (commit c32278dc1) : POST /users/me/upgrade-creator gate email-verified, idempotent.
41 Upload-size SSOT (commit 5848c2e40) : config/upload_limits.go + GET /api/v1/upload/limits consommé par useUploadLimits côté web.
42 Tag suggestions tag_handler.go:15-32.
43 PWA (install + service worker + wake lock) components/pwa/, v0.801.
44 Orphan tracks cleanup (commit 553026728) : jobs/cleanup_orphan_tracks.go, hourly, flip processingfailed si fichier disque manquant.
45 Stem upload & sharing (F482) routes_tracks.go:185-189, ownership guard.

Score : 43 / 2 🟡 / 0 🔴 / 0 . La seule 🔴 de la v1 (Player/écoute audio) est résolue.

Les 2 🟡 restants : Upload (stockage local disque → pas prêt pour production scale) et WebRTC 1:1 (pas de STUN/TURN → NAT traversal HS).


2. Les 6 parcours — étape par étape

Parcours 1 — Écouter de la musique

Verdict : OPÉRATIONNEL. Le bloqueur v1 est résolu — le fallback direct stream existe.

# Étape Verdict Preuve
1 Créer un compte POST /auth/registercore/auth/service.go:104-469. IsVerified: false (:200), token en DB.
2 Recevoir l'email MailHog par défaut dans docker-compose.dev.yml:114-130. UI sur port 8025. Prod : 500 hard si SMTP down (service.go:387).
3 Cliquer le lien verify POST /auth/verify-email?token=Xcore/auth/service.go:747-765 check token + flip is_verified=true.
4 Se connecter POST /auth/login → 403 Forbidden si !IsVerified (service.go:527). Lockout après 5 tentatives / 15 min.
5 Chercher un morceau GET /api/v1/searchsearch_handlers.go:41, ES ou fallback Postgres tsvector.
6 Lancer la lecture Player React tente HLS d'abord (playerService.ts:283-293), fallback direct /stream.
7 Le son sort ? GET /tracks/:id/stream avec http.ServeContent (track_hls_handler.go:266), Range supporté, cache bypass wiré (response_cache.go:87-104).

Piège dev : si on upload un fichier mais que le transcoding (Rust stream server) échoue, le track reste en Processing. Le cleanup worker hourly le flippera à Failed après 1h. Le fichier reste lisible via /stream pendant ce temps, mais il n'apparaît pas en library (filtre status=Completed).

Parcours 2 — Uploader un morceau (artiste)

Verdict : MAIS sur local disque.

# Étape Verdict Preuve
1 Login Comme parcours 1.
2 Upgrade creator (si besoin) POST /api/v1/users/me/upgrade-creator — gate email-verified, idempotent (upgrade_creator_handler.go). UI AccountSettingsCreatorCard.tsx.
3 Uploader un fichier audio POST /api/v1/tracks/uploadtrack_upload_handler.go:39-171. Multipart, taille SSOT (config/upload_limits.go), ClamAV sync fail-secure.
4 Stockage physique 🟡 uploads/tracks/<userID>/<filename> sur disque local (track_upload_handler.go:376). Code S3/MinIO présent mais non wiré dans ce chemin.
5 Transcoding 🟡 Dual-trigger : gRPC Rust stream server (stream_service.go:49) et RabbitMQ job (EnqueueTranscodingJob). Redondance non documentée.
6 Track visible en library Après status=Completed. Avant : utilisateur voit son upload en "Processing" dans son tableau de bord.
7 Autre user peut trouver/lire Via search + parcours 1. Si track reste Processing (transcoding down) → pas en library mais /tracks/:id/stream sert quand même le raw.

Parcours 3 — Acheter sur le marketplace

Verdict : (sandbox testing) + solidifiés massivement depuis v1.

# Étape Verdict Preuve
1 Browse produits GET /api/v1/marketplace/products, handlers DB réels.
2 Ajouter au panier POST /api/v1/cart/itemscart.go:25-97, DB-backed (table cart_items).
3 Checkout POST /api/v1/ordersservice.go:522-548 (prod flow Hyperswitch) ou :550-586 (dev simulated).
4 Paiement Hyperswitch paymentProvider.CreatePayment() avec Idempotency-Key: order.ID (commit 4f15cfbd9). Retourne client_secret consommé par CheckoutPaymentForm.tsx.
5 Webhook paiement POST /api/v1/webhooks/hyperswitch → raw payload logged (webhook_log.go), signature HMAC-SHA512 vérifiée, dispatcher ProcessPaymentWebhook.
6 Reconciliation si webhook perdu reconcile_hyperswitch.go sweep stuck orders > 30m avec payment_id non vide, synthèse webhook → ProcessPaymentWebhook. Idempotent. Configurable RECONCILE_INTERVAL=1h (5m pendant incident).
7 Confirmation + accès contenu Création licenses dans la transaction (service.go:561-585), lock FOR UPDATE pour exclusive.
8 Remboursement 3-phase service.go:1297-1436 : pending row → CreateRefund PSP → persist hyperswitch_refund_id. Webhook refund.succeeded révoque licenses + débite vendeur.
9 Reverse-charge Stripe Connect reversal_worker.go:12-180, state reversal_pending, async, backoff 1m→1h. Rows pré-v1.0.7 sans stripe_transfer_idpermanently_failed avec message explicite.

Piège prod : HYPERSWITCH_ENABLED=false = dev bypass. Garde-fou : Config.Validate refuse de booter en prod si HYPERSWITCH_ENABLED=false (config.go:908-910) — message explicite "marketplace orders complete without charging, effectively giving away products". Fail-closed au bon endroit.

Parcours 4 — Chat

Verdict : sur toutes les surfaces.

# Étape Verdict Preuve
1 Ouvrir le chat apps/web/src/features/chat/pages/ChatPage.tsx.
2 Rejoindre / créer une room POST /api/v1/conversationsCreateRoom:54.
3 Envoyer un message WS dispatcher handler.go:54-106HandleSendMessage:18 → DB avant broadcast (handler_messages.go:91-113).
4 Recevoir (temps réel) Hub local, puis PubSub pour multi-instance.
5 Persistance chat_messages table, indexed.
6 Multi-instance sans Redis Fallback in-memory avec log ERROR loud ("Redis unavailable, cross-instance messages will be lost") (chat_pubsub.go:23-27). Plus de silent fail.
7 Typing / reactions / attach. 12 features wirées (voir §1 ligne 12).

Parcours 5 — Livestream

Verdict : avec banner UI si RTMP down.

# Étape Verdict Preuve
1 Démarrer un live POST /api/v1/live/streamslive_stream_handler.go:71-98, génère stream_key UUID + rtmp_url.
2 Push OBS → nginx-rtmp on_publish callback live_stream_callback.go:38-80 avec secret X-RTMP-Callback-Secret, flip is_live=true.
3 Health check visible GET /api/v1/live/health (live_health_handler.go:78-96) + poll 15s front (useLiveHealth.ts:41-61). Banner warn si rtmp_reachable=false.
4 Viewer play live HLS via nginx-rtmp (streamURL = baseURL + /{streamKey}/playlist.m3u8).
5 Co-listening en parallèle Feature séparée, colistening/hub.go:104-148, host-authority sync 100ms drift threshold.

Piège : nécessite docker compose --profile live up pour démarrer nginx-rtmp. Sans ça, banner red immédiat. Plus de silent fail comme en v1.

Parcours 6 — Admin

Verdict : complet avec persistance maintenance mode.

# Étape Verdict Preuve
1 Accéder /admin Middleware JWT + role check, 2FA obligatoire.
2 Voir stats admin/handler.go:43-54 GetPlatformMetrics.
3 Modérer (queue, bans) moderation/handler.go:44 GetModerationQueue, ban/suspend wirés.
4 Gérer utilisateurs Admin handlers (user upgrade, role change).
5 Maintenance mode Persisté platform_settings (middleware/maintenance.go:16-100, TTL 10s). Survit au restart. 🟡 v1 → v2.
6 Feature flags DB-backed.
7 Ledger health dashboard Grafana config/grafana/dashboards/ledger-health.json + 5 gauges + 3 alert rules (voir §1 ligne 28).
8 Admin transfers admin_transfer_handler.go:36-91, manual retry, state machine persistée.

3. Carte des dépendances

3.1 Services — hard-required vs optionnels

Service Status Comportement si down Preuve
PostgreSQL 🔴 Hard-req App panique au boot (main.go:112-120, migrations auto-run). db.Initialize() + RunMigrations() fatal.
Migrations 🔴 Auto Appliquées au démarrage, boot fail si erreur SQL. database.go:234-256.
Redis 🟢 Dégradation TokenBlacklist nil-safe. Chat PubSub fallback in-memory avec log ERROR loud. Rate limiter dégradé. chat_pubsub.go:23-27 ; config.go:55-58.
RabbitMQ 🟢 Dégradation EventBus publish failures maintenant loggés ERROR (commit bf688af35) au lieu de silent drop. main.go:128-139 ; config.go:690-693.
MinIO / S3 🟢 Non utilisé AWS_S3_ENABLED=false par défaut, code S3 présent mais non wiré dans upload path. Disque local always. config.go:697-720 ; track_upload_handler.go:376.
Elasticsearch 🟢 Optionnel Search fallback Postgres full-text search (tsvector + pg_trgm). ES non utilisé en chemin chaud. fulltext_search_service.go:14-30 ; main.go:288-297 (cleanup only).
ClamAV 🟠 Fail-secure CLAMAV_REQUIRED=true par défaut → upload rejeté (503) si down. =false = bypass avec warning. upload_validator.go:87-88, 140-150 ; services_init.go:27-46.
Hyperswitch 🟠 Prod-gate HYPERSWITCH_ENABLED=false = dev bypass. Prod : Config.Validate refuse boot si false. config.go:908-910 ; service.go:522-548, 550-586.
Stripe Connect 🟠 Prod-gate Reversal worker tourne si config présente. Rows pre-v1.0.7 sans id → permanently_failed. reversal_worker.go:12-180 ; main.go:188.
Nginx-RTMP 🟢 Profil live docker compose --profile live up. Si down : banner UI immédiat sur Go Live page. live_health_handler.go:78-96 ; useLiveHealth.ts:41-61.
Rust stream srv 🟢 Optionnel HLS gated HLSEnabled=false default. Direct /stream fallback toujours disponible. Transcoding async. stream_service.go:49 ; config.go:355 ; track_hls_handler.go:266.
MailHog (SMTP) 🟢 Dev default Branché docker-compose.dev.yml:114-130, port 1025. Dev : fail email → log + continue. Prod : 500 hard. .env.template:160-165 ; service.go:381-407.

Résumé : 3 hard-required (Postgres, migrations, bcrypt) · le reste est optionnel avec fallback, fail-secure, ou prod-gate explicite. C'est l'évolution la plus importante depuis v1 : il n'y a plus de silent failures non documentés.

3.2 Seeding

  • veza-backend-api/cmd/tools/seed/main.go : modes production / full / smoke. Truncate tables → insert users → tracks → playlists → social → chat. Manuel, pas auto-run. Marche.

4. Stabilité — points de fragilité restants

# Fragilité Impact Preuve
1 WebRTC 1:1 sans STUN/TURN 🟡 Prod Pas d'env var, pas de grep hit. NAT symétrique = call failures silencieuses (les signals passent, mais le flux média échoue).
2 Stockage local disque only 🟡 Prod uploads/tracks/<userID>/ sur FS local. Pas scalable multi-pod sans volume partagé. Le code S3/MinIO est dead in upload path.
3 HLS HLSEnabled=false par défaut 🟢 Dev Fonctionnel grâce au fallback /stream. Pas d'adaptive bitrate out-of-box. Opérateur doit activer explicitement.
4 Transcoding dual-trigger 🟡 Ops StreamService.StartProcessing (gRPC) et EnqueueTranscodingJob (RabbitMQ) appelés tous les deux. Redondance non documentée.
5 HLS_STREAMING absent de .env.template 🟠 Doc Dev qui veut HLS doit trouver la var ailleurs. .env.template à compléter.
6 Dev bypass Hyperswitch 🟢 Ops Fail-closed prod (Config.Validate), mais en staging un opérateur distrait peut servir des licences gratuites. Mettre un warning loud au boot.
7 Email tokens en query param 🟠 Sec ?token=X peut leak via Referer / logs proxy. Migration flagged v0.2 (commentaire handlers/auth.go L339).
8 Register issue JWT avant email send 🟠 UX User a ses tokens avant que l'email parte → login 403 immédiat tant que non-vérifié. Cohérent mais friction.
9 ClamAV 10s timeout sync 🟢 UX Upload bloque jusqu'à 10s sur scan. Acceptable pour fichiers audio <100MB.
10 Subscription pending_payment item G 🟢 Roadm v1.0.6.2 compense via filter, item G dans v107-plan refait le path proprement. Pas un bug, juste techdebt flaggée.

Zero silent fails parmi les 6 surfaces critiques (Chat Redis, RabbitMQ, RTMP, HLS, SMTP, Hyperswitch). C'est le grand changement depuis v1.


5. Verdict final

Veza v1.0.7-rc1 est prêt pour :

  • Démo publique contrôlée — un pod, infra dev make dev, Hyperswitch sandbox. Le parcours "register → verify → search → play → upload → purchase → refund" est intégralement opérationnel.
  • Sandbox payment testing — refund réel, reconciliation, ledger-health gauges, Stripe Connect reversal. Toute la plomberie monétaire est audit-ready.
  • Beta privée multi-utilisateurs — chat multi-instance avec alarme loud si Redis manque, co-listening host-authority, livestream avec health banner. Pas de silent fails.

Veza v1.0.7-rc1 n'est PAS prêt pour :

  • 🟡 Production publique grand-public scale — le stockage uploads sur disque local ne survit pas à un second pod. MinIO/S3 doit être wiré dans le path upload (le code dort, il faut juste l'appeler).
  • 🟡 Calls WebRTC fiables hors LAN — sans STUN/TURN, symmetric NAT = échec silencieux du flux média. À configurer avant d'ouvrir la feature calls au public.
  • 🟠 Opérateur ops naïf — le dashboard Grafana ledger-health est là mais ne sert à rien si personne ne le regarde. Nécessite un runbook d'exploitation.

Ce qui a changé depuis la v1 du 2026-04-16 — en 3 jours, l'équipe a fermé 7 findings 🔴/🟡 et ajouté 10 nouvelles capacités (reconciliation, audit log webhook, ledger metrics, reversal async, upgrade creator, upload SSOT, RTMP health, orphan cleanup, maintenance persist, SMTP unified). Voir §6.

En une phrase : le code est solide, la plomberie est honnête, les seuls 🟡 restants sont des features "scale" (storage, NAT) pas des bugs.


6. Diff vs audit v1 (2026-04-16)

Tableau des évolutions : chaque ligne = un finding v1 avec son statut aujourd'hui.

Finding v1 v1 v2 Commit / Preuve
Player/écoute audio sans fallback (HLSEnabled=false) 🔴 Endpoint direct /tracks/:id/stream + Range cache bypass. b875efcff, routes_tracks.go:118-120.
Register : IsVerified: true hardcoded 🔴 service.go:200IsVerified: false. Commit trail.
Verify email : dead code 🔴 Endpoint actif, login 403 sur unverified (service.go:527).
SMTP silent fail 🟡 Env schema unifié (066144352). Prod : 500 hard. Dev : log + continue. MailHog branché par défaut.
Marketplace dev bypass 🟡 Prod gate Config.Validate refuse boot (config.go:908-910). Dev bypass conservé, assumé.
Refund : row DB only, pas de reverse-charge 🟡 3-phase avec idempotency key. 959031667, 4f15cfbd9, service.go:1297-1436.
Subscription : payment gate bypass 🟡 v1.0.6.2 hotfix d31f5733d, hasEffectivePayment().
Chat multi-instance silent fallback 🟡 Redis missing = log ERROR loud (chat_pubsub.go:23-27). Fallback conservé pour single-pod dev.
Livestream : dépendance cachée --profile live 🟡 Health endpoint + banner UI (64fa0c9ac, live_health_handler.go:78-96).
Maintenance mode in-memory 🟡 Persisté platform_settings + TTL 10s. 3a95e38fd, middleware/maintenance.go:16-100.
Tracks orphelines Processing indéfiniment 🟡 Cleanup hourly worker. 553026728, jobs/cleanup_orphan_tracks.go.
RabbitMQ silent drop 🟡 Log ERROR sur publish failure. bf688af35.
Upload size limits désalignés front/back 🟠 SSOT config/upload_limits.go + hook useUploadLimits. 5848c2e40.
Stripe Connect reversal inexistant 🔵 Async worker + state machine reversal_pending. v1.0.7 items A+B.
Reconciliation Hyperswitch (stuck orders) 🔵 reconcile_hyperswitch.go:55-150. v1.0.7 item C.
Webhook raw payload audit log 🔵 webhook_log.go + cleanup 90j. v1.0.7 item E.
Ledger-health metrics + alerts 🔵 5 gauges Prometheus + 3 alert rules + Grafana dashboard. v1.0.7 item F.
Idempotency-key Hyperswitch 🔵 Sur CreatePayment + CreateRefund. v1.0.7 item D (4f15cfbd9).
Self-service creator upgrade 🔵 POST /users/me/upgrade-creator, email-verified gate. c32278dc1.
WebRTC sans STUN/TURN 🟡 🟡 Toujours pas fixé. Signaling ok, NAT traversal non.
Stockage uploads sur disque local 🟡 🟡 Toujours pas fixé. Code S3 présent, non wiré.
HLS HLSEnabled=false par défaut 🔴 🟢 Plus bloquant grâce au fallback direct stream, mais flag toujours off.

Légende : 🔵 = finding absent de v1 mais identifié ici, 🟢 = non-bloquant en v2, 🟠 = doc/cleanup.

Bilan : 18 findings v1 résolus, 2 subsistants (WebRTC TURN, stockage local). 7 nouvelles capacités ajoutées (reconcil, audit log, ledger metrics, reversal, upgrade creator, upload SSOT, RTMP health). Le "chemin critique v1.0.5 public-ready" listé en v1 est intégralement réalisé par v1.0.5 → v1.0.7-rc1.


7. Cleanup session post-rc1 (2026-04-23)

Une session cleanup + BFG a été exécutée 4 jours après cet audit. Cross-référence avec AUDIT_REPORT.md §9 :

  • 10/15 items Top-15 traités (cleanup #1/#2/#3/#6/#7/#9/#11/#12/#13, BFG inclus)
  • ⚠️ 3 false-positives identifiés (#4 context propagation, #5 security headers, #10 RespondWithAppError) — voir AUDIT_REPORT.md §9.bis pour les preuves
  • 📋 2 deferrals v1.0.8 (#8 OpenAPI typegen, #14 E2E Playwright CI)
  • 📝 1 item pending (#15 docs/ENV_VARIABLES.md sync, 0.5j)
  • Repo .git : 1.5 GB → 66 MB (97%) après 2 passes git-filter-repo + force-push stages 1+2

Les 2 findings fonctionnels subsistants (WebRTC STUN/TURN + stockage uploads disque local) restent post-v1.0.7-final dans le scope v1.0.8 (2-3j chacun).


Généré par Claude Code Opus 4.7 (1M context, /effort max, /plan) — 5 agents Explore parallèles + vérifications ponctuelles directes (routes_tracks.go:118, core/auth/service.go:200, config.go:355/907-910, marketplace/service.go:522-586). Cross-référencé avec docs/audit-2026-04/v107-plan.md et CHANGELOG.md v1.0.5 → v1.0.7-rc1. Une correction par rapport à v1 : le Player n'est plus 🔴 — la v1 avait loupé l'endpoint /stream (fallback direct avec Range support). §7 ajouté 2026-04-23 post-session cleanup.