Suppression de tous les exemples de code pour garder uniquement les descriptions techniques : ADR-023 (Architecture Modération) : - Diagramme Mermaid → description flux textuelle - Exemples SQL/Redis → description workflow - Interface Go → description abstraction - Dépendances → liste concise ADR-024 (Monitoring et Observabilité) : - Diagramme Mermaid → architecture textuelle - Exemples PromQL → description métriques - Config YAML alertes → liste alertes avec seuils - Commandes bash WAL-E → description backup - Runbooks → étapes sans commandes ADR-025 (Sécurité et Secrets) : - Diagramme Mermaid → flux secrets textuel - Commandes bash Vault → description process - Code Go encryption → architecture encryption - Schéma SQL → contraintes textuelles - Config Nginx → configuration TLS - Code Go rate limiting → paramètres middleware ADR restent 100% techniques et complets sans code concret. Cohérence avec ADR-022 (même approche). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
168 lines
7.5 KiB
Markdown
168 lines
7.5 KiB
Markdown
# 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](../regles-metier/14-moderation-flows.md)
|
||
- **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
|
||
|
||
**Flux de traitement** :
|
||
1. **Client** (App Mobile/Web) → Signalement utilisateur
|
||
2. **API Backend** (Fiber) → Endpoint `/moderation/report`
|
||
3. **Queue PostgreSQL** → LISTEN/NOTIFY pour dispatch asynchrone
|
||
4. **Worker Go** → Goroutine de traitement (transcription + analyse)
|
||
5. **IA Self-hosted** → Whisper large-v3 (transcription) + distilbert/roberta (NLP)
|
||
6. **Cache Redis** → Sorted Sets pour priorisation temps réel
|
||
7. **Dashboard React** → Interface modérateurs avec Wavesurfer.js (player audio)
|
||
8. **Stockage** → PostgreSQL (signalements + logs audit) + Redis (cache priorisation)
|
||
|
||
### 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](../regles-metier/15-moderation-communautaire.md))
|
||
|
||
## Références
|
||
|
||
- [Règle 14 : Modération - Flows opérationnels](../regles-metier/14-moderation-flows.md)
|
||
- [Règle 15 : Modération Communautaire](../regles-metier/15-moderation-communautaire.md)
|
||
- [ADR-001 : Langage Backend](001-langage-backend.md) (Go, Fiber)
|
||
- [ADR-005 : Base de données](005-base-de-donnees.md) (PostgreSQL)
|
||
- [ADR-010 : Architecture Backend](010-architecture-backend.md) (Modular monolith)
|
||
- [Whisper large-v3 documentation](https://github.com/openai/whisper)
|
||
- [PostgreSQL LISTEN/NOTIFY](https://www.postgresql.org/docs/current/sql-notify.html)
|