Réorganise la documentation du projet selon les principes du Domain-Driven Design (DDD) pour améliorer la cohésion, la maintenabilité et l'alignement avec l'architecture modulaire du backend. **Structure cible:** ``` docs/domains/ ├── README.md (Context Map) ├── _shared/ (Core Domain) ├── recommendation/ (Supporting Subdomain) ├── content/ (Supporting Subdomain) ├── moderation/ (Supporting Subdomain) ├── advertising/ (Generic Subdomain) ├── premium/ (Generic Subdomain) └── monetization/ (Generic Subdomain) ``` **Changements effectués:** Phase 1: Création de l'arborescence des 7 bounded contexts Phase 2: Déplacement des règles métier (01-19) vers domains/*/rules/ Phase 3: Déplacement des diagrammes d'entités vers domains/*/entities/ Phase 4: Déplacement des diagrammes flux/états/séquences vers domains/*/ Phase 5: Création des README.md pour chaque domaine Phase 6: Déplacement des features Gherkin vers domains/*/features/ Phase 7: Création du Context Map (domains/README.md) Phase 8: Mise à jour de mkdocs.yml pour la nouvelle navigation Phase 9: Correction automatique des liens internes (script fix-markdown-links.sh) Phase 10: Nettoyage de l'ancienne structure (regles-metier/, diagrammes/, features/) **Configuration des tests:** - Makefile: godog run docs/domains/*/features/ - scripts/generate-bdd-docs.py: features_dir → docs/domains **Avantages:** ✅ Cohésion forte: toute la doc d'un domaine au même endroit ✅ Couplage faible: domaines indépendants, dépendances explicites ✅ Navigabilité améliorée: README par domaine = entrée claire ✅ Alignement code/docs: miroir de backend/internal/ ✅ Onboarding facilité: exploration domaine par domaine ✅ Tests BDD intégrés: features au plus près des règles métier Voir docs/REFACTOR-DDD.md pour le plan complet.
8.2 KiB
8.2 KiB
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
-
Réception signalement :
- Insertion en base PostgreSQL (table
moderation_reports) - Notification asynchrone via PostgreSQL NOTIFY
- Insertion en base PostgreSQL (table
-
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
-
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 Dashboardjackc/pgx/v5: PostgreSQL + LISTEN/NOTIFYredis/rueidis: Cache priorisation- Whisper : via Python subprocess ou go-whisper bindings
Frontend Dashboard :
react: Framework UI@tanstack/react-table: Tables performanteswavesurfer.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)
- Backend : API
/moderation/report+ PostgreSQL queue - Worker : Whisper large-v3 CPU + NLP basique (liste noire mots-clés)
- Dashboard : React basique (liste + player audio)
Phase 2 (Post-MVP - Sprint 8-10)
- Migration Redis Streams si >1000 signalements/jour
- GPU pour Whisper si latence >15 min P95
- NLP avancé (distilbert + roberta)
- Modération communautaire (badges, Règle 15)