Résolution des incohérences #10, #11, et #12 de l'analyse d'architecture. ## Phase 1 : Réorganisation Features BDD (Point #10 - RÉSOLU) - Créer structure features/{api,ui,e2e} - Déplacer 83 features en 3 catégories via git mv (historique préservé) - features/api/ : 53 features (tests API backend) - features/ui/ : 22 features (tests UI mobile) - features/e2e/ : 8 features (tests end-to-end) Domaines déplacés : - API : authentication, recommendation, rgpd-compliance, content-creation, moderation, monetisation, premium, radio-live, publicites - UI : audio-guides, navigation, interest-gauges, mode-offline, partage, profil, recherche - E2E : abonnements, error-handling ## Phase 2 : Mise à jour Documentation ### ADR-007 - Tests BDD - Ajouter section "Convention de Catégorisation des Features" - Documenter règles api/ui/e2e avec exemples concrets - Spécifier step definitions (backend Go, mobile Dart) ### ADR-024 - Stratégie CI/CD Monorepo (NOUVEAU) - Créer ADR dédié pour stratégie CI/CD avec path filters - Architecture workflows séparés (backend.yml, mobile.yml, shared.yml) - Configuration path filters détaillée avec exemples YAML - Matrice de déclenchement et optimisations (~70% gain temps CI) - Plan d'implémentation (~2h, reporté jusqu'au développement) ### ADR-016 - Organisation Monorepo - Simplifier en retirant section CI/CD détaillée - Ajouter référence vers ADR-024 pour stratégie CI/CD ### INCONSISTENCIES-ANALYSIS.md - Point #10 (Tests BDD synchronisés) : ✅ RÉSOLU - Catégorisation features implémentée - ADR-007 mis à jour avec convention complète - Point #11 (70/30 Split paiements) : ✅ ANNULÉ (faux problème) - ADR-009 et Règle 18 parfaitement cohérents - Documentation exhaustive existante (formule, SQL, comparaisons) - Point #12 (Monorepo path filters) : ⏸️ DOCUMENTÉ - Architecture CI/CD complète dans ADR-024 - Implémentation reportée (projet en phase documentation) - Métriques mises à jour : - MODERATE : 6/9 traités (4 résolus + 1 annulé + 1 documenté) - ADR à jour : 100% (19/19 avec ADR-024) ## Phase 3 : Validation - Structure features validée (api/ui/e2e, aucun répertoire restant) - Historique Git préservé (git mv, renommages détectés) - 83 features total (API: 53, UI: 22, E2E: 8) Closes: Point #10 (résolu), Point #11 (annulé), Point #12 (documenté) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
328 lines
15 KiB
Gherkin
328 lines
15 KiB
Gherkin
# language: fr
|
||
|
||
@moderation @sanctions
|
||
Fonctionnalité: Sanctions et notifications de modération
|
||
|
||
# 14.3 - Sanctions
|
||
|
||
Contexte:
|
||
Étant donné que je suis un créateur de contenu
|
||
Et que j'ai publié un contenu
|
||
|
||
# 14.3.1 - Notification au créateur (multi-canal)
|
||
|
||
Scénario: Notification multi-canal après sanction
|
||
Étant donné que mon contenu a été modéré
|
||
Quand la sanction est appliquée
|
||
Alors je reçois une notification sur 3 canaux:
|
||
| canal | timing | contenu |
|
||
| Push | Immédiat | "Votre contenu a été modéré" |
|
||
| In-app | Au prochain lancement| Popup détaillée avec bouton "Voir détails" |
|
||
| Email | Dans l'heure | Notification complète avec lien d'appel |
|
||
Et chaque canal contient un lien vers les détails complets
|
||
|
||
Scénario: Notification push immédiate
|
||
Étant donné que mon contenu vient d'être modéré
|
||
Quand la sanction est appliquée
|
||
Alors je reçois une notification push immédiate
|
||
Et le message est court: "⚠️ Votre contenu a été modéré"
|
||
Et je peux cliquer pour voir les détails
|
||
Et la notification utilise Firebase Cloud Messaging (Android) ou APNs (iOS)
|
||
Et le coût est de 0€
|
||
|
||
Scénario: Popup in-app au prochain lancement
|
||
Étant donné que mon contenu a été modéré
|
||
Quand j'ouvre l'application
|
||
Alors une popup détaillée s'affiche automatiquement
|
||
Et la popup contient:
|
||
| élément | description |
|
||
| Titre du contenu | "Mon podcast #42" |
|
||
| Icône d'avertissement | ⚠️ |
|
||
| Catégorie violée | 🚫 Haine & violence |
|
||
| Sanction | Strike 2/4 - Suspension 7 jours |
|
||
| Bouton "Voir détails" | Redirige vers page détaillée |
|
||
| Bouton "Compris" | Ferme la popup |
|
||
Et je ne peux pas fermer la popup sans l'avoir vue
|
||
|
||
Scénario: Email de notification complet dans l'heure
|
||
Étant donné que mon contenu a été modéré à 14:00
|
||
Quand la sanction est appliquée
|
||
Alors je reçois un email avant 15:00 (dans l'heure)
|
||
Et l'objet de l'email est "Modération de votre contenu \"[Titre du contenu]\""
|
||
Et l'email contient toutes les informations détaillées
|
||
Et le coût est d'environ 0.001€ par email (Brevo, Resend)
|
||
|
||
# 14.3.2 - Détail de la sanction
|
||
|
||
Scénario: Email de notification complet et structuré
|
||
Étant donné que mon contenu "Mon podcast #42" a été modéré
|
||
Quand je reçois l'email de notification
|
||
Alors l'email contient la structure suivante:
|
||
"""
|
||
Objet : Modération de votre contenu "Mon podcast #42"
|
||
|
||
Bonjour @mon_pseudo,
|
||
|
||
Votre contenu "Mon podcast #42" publié le 15/01/2026 a été modéré.
|
||
|
||
Catégorie violée : 🚫 Haine & violence (Article 3.2 CGU)
|
||
Raison : Propos discriminatoires envers un groupe de personnes
|
||
|
||
Extrait audio concerné : 3:42-4:15
|
||
Transcription : "[passage problématique surligné en rouge]"
|
||
|
||
Sanction : Strike 2/4
|
||
Conséquence : Suspension de votre compte pendant 7 jours
|
||
|
||
Vous pouvez contester cette décision sous 7 jours :
|
||
[Lien formulaire d'appel]
|
||
|
||
L'équipe RoadWave
|
||
"""
|
||
|
||
Scénario: Page détaillée de la sanction in-app
|
||
Étant donné que je clique sur "Voir détails" dans la notification
|
||
Quand la page détaillée s'affiche
|
||
Alors je vois les 6 éléments obligatoires:
|
||
| élément | contenu |
|
||
| 1. Catégorie violée | 🚫 Haine & violence (Article 3.2 CGU) |
|
||
| 2. Raison détaillée | Explication claire et non juridique |
|
||
| 3. Extrait audio | Timestamp exact: 3:42-4:15 |
|
||
| 4. Transcription | Texte problématique surligné en rouge |
|
||
| 5. Gravité | Strike actuel + conséquences (Strike 2/4, 7j susp) |
|
||
| 6. Recours | Lien formulaire d'appel + délai 7j |
|
||
|
||
Scénario: Affichage du passage problématique avec timestamp
|
||
Étant donné que la page détaillée de la sanction est affichée
|
||
Quand je consulte l'extrait audio concerné
|
||
Alors le timestamp exact est affiché: "3:42-4:15"
|
||
Et je peux écouter uniquement cette portion de l'audio
|
||
Et un player audio intégré permet l'écoute du passage
|
||
Et la transcription correspondante est affichée en dessous
|
||
Et les mots/phrases problématiques sont surlignés en rouge
|
||
|
||
Scénario: Référence précise aux CGU
|
||
Étant donné que la sanction fait référence à l'Article 3.2 des CGU
|
||
Quand je clique sur "Article 3.2"
|
||
Alors je suis redirigé vers la section correspondante des CGU
|
||
Et la section "Haine & violence" est mise en évidence
|
||
Et je peux lire exactement ce qui est interdit
|
||
Et cela m'aide à comprendre mon erreur
|
||
|
||
Scénario: Gravité de la sanction avec système de strikes
|
||
Étant donné que c'est mon 2ème strike
|
||
Quand je consulte les détails de la sanction
|
||
Alors je vois clairement "Strike 2/4"
|
||
Et les conséquences sont explicitées:
|
||
"""
|
||
Strike 2/4 - Suspension 7 jours
|
||
|
||
Que se passe-t-il ensuite?
|
||
- Strike 3: Suspension 30 jours
|
||
- Strike 4: Ban définitif
|
||
|
||
Comment éviter les strikes?
|
||
- Lire et respecter les règles de la communauté
|
||
- Réhabilitation: -1 strike tous les 6 mois sans incident
|
||
"""
|
||
Et je comprends l'escalade des sanctions
|
||
|
||
# 14.3.3 - Processus d'appel
|
||
|
||
Scénario: Accès au formulaire d'appel depuis la notification
|
||
Étant donné que j'ai reçu une notification de modération
|
||
Quand je clique sur "Contester cette décision"
|
||
Alors je suis redirigé vers le formulaire d'appel
|
||
Et le formulaire est pré-rempli avec les informations de la sanction
|
||
Et je peux commencer à rédiger mon appel
|
||
|
||
Scénario: Accès au formulaire d'appel depuis "Mes sanctions"
|
||
Étant donné que j'ai reçu une sanction il y a 2 jours
|
||
Quand j'ouvre "Profil créateur > Mes sanctions"
|
||
Alors je vois la liste de mes sanctions
|
||
Et chaque sanction a un bouton "Faire appel" (si délai <7j)
|
||
Et je peux accéder au formulaire d'appel
|
||
|
||
Scénario: Structure du formulaire d'appel
|
||
Étant donné que j'ouvre le formulaire d'appel
|
||
Quand le formulaire s'affiche
|
||
Alors je vois les champs suivants:
|
||
| champ | type | obligatoire | description |
|
||
| Sanction contestée | Pré-rempli (readonly) | oui | "Strike 2 - Podcast #42" |
|
||
| Raison de l'appel | Texte (50-1000 car) | oui | Explication courte de la contestation |
|
||
| Arguments détaillés | Zone texte enrichie | oui | Arguments complets |
|
||
| Preuves | Upload fichiers | non | Max 5 fichiers, 10 MB total |
|
||
Et tous les champs obligatoires sont marqués d'un astérisque
|
||
|
||
Scénario: Validation du formulaire d'appel
|
||
Étant donné que je remplis le formulaire d'appel
|
||
Quand je clique sur "Soumettre l'appel"
|
||
Alors le système valide les champs obligatoires
|
||
Et si un champ obligatoire est vide, une erreur s'affiche
|
||
Et si la raison fait moins de 50 caractères, une erreur s'affiche
|
||
Et si tout est valide, l'appel est soumis
|
||
|
||
Scénario: Confirmation après soumission de l'appel
|
||
Étant donné que j'ai soumis un appel valide
|
||
Quand l'appel est enregistré
|
||
Alors un numéro de ticket unique est généré: "#MOD-2026-00142"
|
||
Et un email de confirmation est envoyé:
|
||
"""
|
||
Votre appel #MOD-2026-00142 a été reçu.
|
||
Nous l'examinerons sous 72h maximum.
|
||
Vous serez notifié de la décision par email et in-app.
|
||
"""
|
||
Et le statut de l'appel est "En cours d'examen"
|
||
Et je peux suivre le statut dans "Mes sanctions"
|
||
|
||
Scénario: Délai de soumission de 7 jours maximum
|
||
Étant donné que j'ai reçu une sanction le 2026-01-15
|
||
Quand j'essaie de faire appel le 2026-01-25 (10 jours plus tard)
|
||
Alors le formulaire d'appel est désactivé
|
||
Et un message s'affiche:
|
||
"""
|
||
Le délai de 7 jours pour faire appel est dépassé.
|
||
Cette décision est désormais définitive.
|
||
"""
|
||
Et je ne peux plus contester la sanction
|
||
|
||
Scénario: Bouton "Faire appel" visible si délai respecté
|
||
Étant donné que j'ai reçu une sanction il y a 3 jours
|
||
Quand je consulte "Mes sanctions"
|
||
Alors le bouton "Faire appel" est actif
|
||
Et un compteur indique "4 jours restants pour faire appel"
|
||
Et je peux cliquer pour soumettre un appel
|
||
|
||
# 14.3.4 - Délai de réponse pour appel
|
||
|
||
Scénario: SLA de 72h garanti pour appel standard
|
||
Étant donné que j'ai soumis un appel standard le lundi à 10:00
|
||
Quand l'appel est en cours de traitement
|
||
Alors un modérateur senior est assigné
|
||
Et l'appel doit être traité avant jeudi 10:00 (72h - 3 jours ouvrés)
|
||
Et je reçois une réponse dans ce délai
|
||
|
||
Scénario: Appel complexe avec notification intermédiaire
|
||
Étant donné que j'ai soumis un appel complexe
|
||
Et que le traitement nécessite plus de 72h
|
||
Quand 3 jours se sont écoulés
|
||
Alors je reçois un email de notification intermédiaire:
|
||
"""
|
||
Votre appel #MOD-2026-00142 est en cours d'examen approfondi.
|
||
Nous vous répondrons sous 2 jours maximum.
|
||
"""
|
||
Et l'appel est traité sous 5 jours ouvrés au total
|
||
Et un modérateur senior + admin modération examinent le cas
|
||
|
||
Scénario: Appel CRITIQUE traité en 24h
|
||
Étant donné que j'ai reçu une suspension longue ou un ban
|
||
Et que je soumets un appel
|
||
Quand l'appel est classé en priorité CRITIQUE
|
||
Alors l'admin modération traite l'appel sous 24h
|
||
Et je reçois une réponse rapide
|
||
Et le cas est examiné en priorité absolue
|
||
|
||
Scénario: Réponse finale détaillée - Appel accepté
|
||
Étant donné que mon appel est accepté
|
||
Quand je reçois la réponse finale
|
||
Alors l'email contient:
|
||
| élément | contenu |
|
||
| Décision | Annulation de la sanction |
|
||
| Justification | Explication de pourquoi l'appel est accepté |
|
||
| Actions | Strike retiré, suspension annulée, contenu rétabli |
|
||
| Définitif | "Cette décision est définitive" |
|
||
Et le strike est retiré de mon compte
|
||
Et le contenu est rétabli sur la plateforme
|
||
Et je peux continuer normalement
|
||
|
||
Scénario: Réponse finale détaillée - Appel rejeté
|
||
Étant donné que mon appel est rejeté
|
||
Quand je reçois la réponse finale
|
||
Alors l'email contient:
|
||
| élément | contenu |
|
||
| Décision | Maintien de la sanction |
|
||
| Justification | Explication de pourquoi l'appel est rejeté |
|
||
| Actions | Sanction maintenue, strike conservé |
|
||
| Définitif | "Cette décision est définitive" |
|
||
Et la sanction reste active
|
||
Et je ne peux pas faire de second appel
|
||
Et je dois respecter la suspension
|
||
|
||
Scénario: Réponse finale - Réduction de sanction
|
||
Étant donné que mon appel est partiellement accepté
|
||
Quand je reçois la réponse finale
|
||
Alors la décision est "Réduction de sanction"
|
||
Et l'email explique:
|
||
"""
|
||
Après examen de votre appel, nous reconnaissons des circonstances atténuantes.
|
||
La sanction est réduite:
|
||
- Strike 2 → Strike 1
|
||
- Suspension 7 jours → Suspension 3 jours
|
||
|
||
Cette décision est définitive.
|
||
"""
|
||
Et le strike est réduit
|
||
Et la suspension est raccourcie
|
||
Et je suis notifié de la nouvelle date de fin
|
||
|
||
Scénario: Suivi du statut de l'appel in-app
|
||
Étant donné que j'ai soumis un appel
|
||
Quand je consulte "Mes sanctions"
|
||
Alors je vois le statut actuel de l'appel:
|
||
| statut | badge | couleur |
|
||
| En cours d'examen | En cours 🔍 | orange |
|
||
| Appel accepté | Accepté ✓ | vert |
|
||
| Appel rejeté | Rejeté ✗ | rouge |
|
||
| Sanction réduite | Partiellement accepté| bleu |
|
||
Et une notification badge m'alerte quand le statut change
|
||
|
||
# Transparence et traçabilité
|
||
|
||
Scénario: Historique complet des sanctions visible
|
||
Étant donné que je suis un créateur
|
||
Quand j'ouvre "Profil créateur > Mes sanctions"
|
||
Alors je vois la liste complète de mes sanctions passées:
|
||
| colonne | description |
|
||
| Date | 15/01/2026 |
|
||
| Contenu | "Mon podcast #42" |
|
||
| Catégorie | 🚫 Haine & violence |
|
||
| Sanction | Strike 2 - Suspension 7j |
|
||
| Statut | Active / Terminée / Annulée |
|
||
| Appel | Aucun / Accepté / Rejeté |
|
||
Et les sanctions sont triées par date décroissante
|
||
|
||
Scénario: Conformité DSA - Transparence obligatoire
|
||
Étant donné que le système de sanction est en place
|
||
Quand un audit DSA est effectué
|
||
Alors chaque sanction contient:
|
||
| élément DSA | présent |
|
||
| Référence précise à la règle violée | oui |
|
||
| Explication claire et compréhensible | oui |
|
||
| Preuve (extrait + transcription) | oui |
|
||
| Possibilité de recours (appel) | oui |
|
||
| Délai de recours clairement indiqué | oui |
|
||
| Réponse motivée au recours | oui |
|
||
Et le système est conforme au Digital Services Act
|
||
|
||
# Pas de second appel
|
||
|
||
Scénario: Décision définitive après premier appel
|
||
Étant donné que mon premier appel a été rejeté
|
||
Quand j'essaie de faire un second appel
|
||
Alors le bouton "Faire appel" est désactivé
|
||
Et un message s'affiche: "Cette décision est définitive. Aucun second appel n'est possible."
|
||
Et je ne peux plus contester la sanction
|
||
Et je dois respecter la décision finale
|
||
|
||
# Coût des notifications
|
||
|
||
Scénario: Coût des notifications multi-canal
|
||
Étant donné que 100 sanctions sont appliquées en un mois
|
||
Quand on calcule le coût des notifications
|
||
Alors le coût total est d'environ 0.10€:
|
||
| canal | coût unitaire | coût pour 100 |
|
||
| Email | 0.001€ | 0.10€ |
|
||
| Push | 0€ | 0€ |
|
||
| In-app | 0€ | 0€ |
|
||
Et le coût est négligeable même à grande échelle
|