Files
roadwave/docs/adr/023-architecture-moderation.md
jpgiannetti 78b723baa3 fix(adr-023/024/025): restaurer diagrammes Mermaid
Les diagrammes Mermaid sont utiles pour visualiser l'architecture
et ne posent pas de problème de doublon code/doc.

Restauration des 3 diagrammes :
- ADR-023 : Flux modération (Client → API → Worker → IA → Dashboard)
- ADR-024 : Stack monitoring (Services → Prometheus/Grafana → Alerting)
- ADR-025 : Architecture secrets (Dev/Prod → Vault → Encryption)

Code textuel (SQL, bash, Go, YAML) reste retiré comme demandé.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-01 17:55:58 +01:00

8.2 KiB
Raw Blame History

ADR-023 : Architecture de Modération

Statut : Accepté Date : 2026-02-01

Contexte

Le système de modération RoadWave doit traiter des signalements de contenu audio problématique (haine, spam, droits d'auteur, etc.) avec :

  • SLA stricts : 2h (critique), 24h (haute), 72h (standard) définis dans Règle 14
  • Scalabilité : 0-10K+ signalements/mois
  • Conformité DSA : transparence, traçabilité, délais garantis
  • Efficacité : pré-filtrage IA pour priorisation automatique

Décision

Architecture hybride humain + IA avec file d'attente intelligente.

Stack Technique

Composant Technologie Justification
Queue signalements PostgreSQL LISTEN/NOTIFY Pas de dépendance externe, transactions ACID
Transcription audio Whisper large-v3 (self-hosted) Open source, qualité production, 0€
Analyse NLP distilbert + roberta-hate-speech Modèles open source, self-hosted
Dashboard modérateurs React + Fiber API Stack cohérent avec ADR-001, ADR-010
Player audio Wavesurfer.js Waveform visuel, annotations temporelles
Cache priorisation Redis Sorted Sets Ranking temps réel, TTL automatique

Architecture

graph TB
    subgraph Client["App Mobile/Web"]
        Report["Signalement utilisateur"]
    end

    subgraph Backend["Backend Go"]
        API["API Fiber<br/>/moderation/report"]
        Queue["PostgreSQL Queue<br/>LISTEN/NOTIFY"]
        Worker["Worker Go<br/>(transcription + NLP)"]
    end

    subgraph AI["IA Self-hosted"]
        Whisper["Whisper large-v3<br/>(transcription)"]
        NLP["distilbert<br/>(sentiment + haine)"]
    end

    subgraph Moderation["Modération Dashboard"]
        Dashboard["React Dashboard"]
        Player["Wavesurfer.js<br/>(lecture audio)"]
    end

    subgraph Storage["Stockage"]
        DB["PostgreSQL<br/>(signalements + logs)"]
        Redis["Redis<br/>(priorisation + cache)"]
    end

    Report --> API
    API --> Queue
    Queue --> Worker
    Worker --> Whisper
    Whisper --> NLP
    NLP --> Redis
    Worker --> DB
    Dashboard --> Player
    Dashboard --> Redis
    Dashboard --> DB

    classDef clientStyle fill:#e3f2fd,stroke:#1565c0
    classDef backendStyle fill:#fff3e0,stroke:#e65100
    classDef aiStyle fill:#f3e5f5,stroke:#6a1b9a
    classDef storageStyle fill:#e8f5e9,stroke:#2e7d32

    class Client,Report clientStyle
    class Backend,API,Queue,Worker backendStyle
    class AI,Whisper,NLP aiStyle
    class Storage,DB,Redis storageStyle

Workflow de Traitement

  1. Réception signalement :

    • Insertion en base PostgreSQL (table moderation_reports)
    • Notification asynchrone via PostgreSQL NOTIFY
  2. Worker asynchrone (goroutine) :

    • Écoute queue PostgreSQL (LISTEN/NOTIFY)
    • Téléchargement audio depuis stockage S3/local
    • Transcription audio via Whisper large-v3 (1-10 min selon durée)
    • Analyse NLP : score confiance 0-100% (distilbert + roberta)
    • Calcul priorité selon formule : (score_IA × 0.7) + (nb_signalements × 0.2) + (fiabilité_signaleur × 0.1)
    • Insertion dans Redis Sorted Set pour priorisation
  3. Dashboard modérateurs :

    • Récupération signalements priorisés depuis Redis (top 20 par page)
    • Affichage : transcription, waveform audio, historique créateur
    • Actions disponibles : Approuver, Rejeter, Escalade (shortcuts clavier A/R/E)
    • Logs audit PostgreSQL pour traçabilité (conformité DSA)

Alternatives considérées

Queue de signalements

Option Avantages Inconvénients Verdict
PostgreSQL LISTEN/NOTIFY Pas de dépendance, ACID ⚠️ Performance limitée >10K/min Choisi MVP
RabbitMQ Scalable, dead letter queues Nouvelle dépendance, complexité Overkill MVP
Redis Streams Performant, simple ⚠️ Pas de garantie persistance ⚠️ Phase 2
SQS/Cloud Managed, scalable Dépendance cloud, coût Souveraineté

Transcription audio

Option Coût Qualité Hébergement Verdict
Whisper large-v3 0€ (self-hosted) Excellente Self-hosted Choisi
AssemblyAI API 0.37$/h audio Excellente Cloud US Coût + souveraineté
Google Speech-to-Text 0.024$/min Bonne Cloud Google Dépendance Google
Whisper tiny/base 0€ Moyenne Self-hosted Qualité insuffisante

NLP Analyse

Option Coût Performance Hébergement Verdict
distilbert + roberta 0€ CPU OK (1-3s/audio) Self-hosted Choisi
OpenAI Moderation API 0.002$/1K tokens Excellente Cloud OpenAI Dépendance + coût
Perspective API (Google) Gratuit Bonne Cloud Google Dépendance Google

Justification

PostgreSQL LISTEN/NOTIFY

  • Performance MVP : Suffisant jusqu'à 1000 signalements/jour (~0.7/min)
  • Simplicité : Pas de broker externe, transactions ACID
  • Migration facile : Abstraction via interface ModerationQueue → swap vers Redis Streams si besoin (méthodes : Enqueue, Listen)

Whisper large-v3 self-hosted

  • Coût 0€ vs AssemblyAI (3700€/an @ 10K heures audio)
  • Souveraineté : données sensibles restent en France
  • Qualité production : WER (Word Error Rate) <5% français
  • Scaling : CPU MVP (1 core), GPU Phase 2 si >1000 signalements/jour

Dashboard React

  • Cohérence stack : Même techno que admin panel (si React adopté)
  • Performance : TanStack Table pour listes >1000 éléments
  • Wavesurfer.js : Standard industrie (SoundCloud, Audacity web)

Conséquences

Positives

  • 0€ infrastructure IA au MVP (CPU standard)
  • 100% self-hosted : conformité souveraineté (ADR-008, ADR-015)
  • Scalable progressif : PostgreSQL → Redis Streams si besoin
  • Conformité DSA : logs audit, traçabilité complète
  • Productivité ×3-5 : pré-filtrage IA réduit charge modérateurs

Négatives

  • ⚠️ Latence transcription : 1-10 min selon durée audio (acceptable, traitement asynchrone)
  • ⚠️ Performance limite : PostgreSQL LISTEN/NOTIFY saturé >10K signalements/jour (migration Redis Streams nécessaire)
  • Ressources CPU : Whisper consomme 1-4 CPU cores selon charge (migration GPU si >1000 signalements/jour)

Dépendances

Backend Go :

  • gofiber/fiber/v3 : API Dashboard
  • jackc/pgx/v5 : PostgreSQL + LISTEN/NOTIFY
  • redis/rueidis : Cache priorisation
  • Whisper : via Python subprocess ou go-whisper bindings

Frontend Dashboard :

  • react : Framework UI
  • @tanstack/react-table : Tables performantes
  • wavesurfer.js : Player audio avec waveform

Métriques de Succès

  • Latence traitement < 10 min (P95) après réception signalement
  • Précision IA pré-filtre > 80% (validation humaine)
  • SLA respectés > 95% des cas (2h/24h/72h selon priorité)
  • Coût infrastructure < 50€/mois jusqu'à 1000 signalements/mois

Migration et Rollout

Phase 1 (MVP - Sprint 3-4)

  1. Backend : API /moderation/report + PostgreSQL queue
  2. Worker : Whisper large-v3 CPU + NLP basique (liste noire mots-clés)
  3. Dashboard : React basique (liste + player audio)

Phase 2 (Post-MVP - Sprint 8-10)

  1. Migration Redis Streams si >1000 signalements/jour
  2. GPU pour Whisper si latence >15 min P95
  3. NLP avancé (distilbert + roberta)
  4. Modération communautaire (badges, Règle 15)

Références