Files
roadwave/features/api/premium/stream-conflict-detection.feature
jpgiannetti c48222cc63 feat(gherkin): compléter couverture règles métier avec 47 features manquantes
Ajout de 47 features Gherkin (~650 scénarios) pour couvrir 100% des règles métier :

- Authentification (5) : validation mot de passe, tentatives connexion, multi-device, 2FA, récupération
- Audio-guides (12) : détection mode, création, navigation piéton/voiture, ETA, gestion points, progression
- Navigation (5) : notifications minimalistes, décompte 5s, stationnement, historique, basculement auto
- Création contenu (3) : image auto, restrictions modification, suppression
- Radio live (2) : enregistrement auto, interdictions modération
- Droits auteur (6) : fair use 30s, détection musique, signalements, sanctions, appels
- Modération (9) : badges Bronze/Argent/Or, score fiabilité, utilisateur confiance, audit, anti-abus
- Premium (2) : webhooks Mangopay, tarification multi-canal
- Profil/Partage/Recherche (5) : badge vérifié, stats arrondies, partage premium, filtres avancés, carte

Tous les scénarios incluent edge cases, métriques de performance et conformité RGPD.
Couverture fonctionnelle MVP maintenant complète.
2026-02-03 21:25:47 +01:00

224 lines
11 KiB
Gherkin
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# language: fr
@api @premium @multi-device @mvp
Fonctionnalité: Détection et gestion des conflits de streaming multi-device Premium
En tant qu'abonné Premium
Je peux écouter sur plusieurs appareils (iPhone, iPad, Android, Web)
Mais un seul stream audio peut être actif à la fois
Afin de respecter les conditions d'abonnement Premium individuel
Contexte:
Étant donné un utilisateur avec abonnement Premium actif
Et plusieurs appareils enregistrés sur le compte :
| device_id | platform | nom | last_seen |
| iphone-123 | iOS | iPhone de Jean | 2026-02-03 14:00:00 |
| ipad-456 | iOS | iPad Pro | 2026-02-03 12:30:00 |
| android-789 | Android | Samsung Galaxy | 2026-02-02 18:00:00 |
| web-abc | Web | Chrome MacBook | 2026-02-03 10:00:00 |
# ============================================================================
# DÉTECTION STREAM ACTIF ET CONFLIT
# ============================================================================
Scénario: Premier stream - aucun conflit
Étant donné aucun stream n'est actuellement actif sur le compte
Quand l'utilisateur démarre la lecture sur "iPhone de Jean"
Alors le stream doit démarrer normalement
Et une session active doit être enregistrée dans Redis :
| user_id | user-123 |
| device_id | iphone-123 |
| started_at | 2026-02-03 14:00:00|
| content_id | content-xyz |
| stream_token | token-abc123 |
Et le TTL Redis doit être de 2 heures
Scénario: Tentative de stream simultané sur second appareil
Étant donné un stream actif sur "iPhone de Jean" depuis 10 minutes
Quand l'utilisateur tente de démarrer la lecture sur "iPad Pro"
Alors une réponse HTTP 409 Conflict doit être retournée
Et le message doit indiquer :
"""
Un contenu est déjà en cours de lecture sur "iPhone de Jean".
Voulez-vous arrêter la lecture sur cet appareil et continuer ici ?
"""
Et les options proposées doivent être :
| option | action |
| Continuer ici | kill_previous_session |
| Annuler | cancel_new_session |
Scénario: Utilisateur choisit "Continuer ici" - kill de l'ancienne session
Étant donné un stream actif sur "iPhone de Jean"
Et l'utilisateur tente de lire sur "iPad Pro"
Et le conflit est détecté
Quand l'utilisateur choisit "Continuer ici"
Alors l'ancienne session sur "iPhone de Jean" doit être terminée immédiatement
Et un message WebSocket doit être envoyé à "iPhone de Jean" :
"""
{"type": "stream_stopped", "reason": "playback_started_on_other_device", "device": "iPad Pro"}
"""
Et la lecture sur "iPhone de Jean" doit s'arrêter avec notification :
"""
Lecture arrêtée : un autre appareil utilise votre compte Premium.
"""
Et le nouveau stream sur "iPad Pro" doit démarrer normalement
Scénario: Utilisateur choisit "Annuler" - maintien de la session actuelle
Étant donné un stream actif sur "iPhone de Jean"
Et l'utilisateur tente de lire sur "iPad Pro"
Et le conflit est détecté
Quand l'utilisateur choisit "Annuler"
Alors la session sur "iPhone de Jean" doit continuer normalement
Et aucun stream ne doit démarrer sur "iPad Pro"
Et l'utilisateur doit être redirigé vers l'écran d'accueil sur "iPad Pro"
# ============================================================================
# GESTION AUTOMATIQUE DES SESSIONS EXPIRÉES
# ============================================================================
Scénario: Session expirée automatiquement après pause prolongée
Étant donné un stream actif sur "iPhone de Jean"
Et l'utilisateur met en pause à 14:00:00
Et le TTL Redis est configuré pour expirer après 30 minutes de pause
Quand il est 14:35:00 (>30 min de pause)
Alors la session Redis doit expirer automatiquement
Et l'utilisateur peut démarrer un nouveau stream sur n'importe quel appareil
Et aucun conflit ne doit être détecté
Scénario: Heartbeat maintient la session active pendant la lecture
Étant donné un stream actif sur "iPhone de Jean"
Quand l'application envoie un heartbeat toutes les 30 secondes
Alors le TTL Redis doit être renouvelé à 2 heures à chaque heartbeat
Et la session doit rester active tant que les heartbeats continuent
Et si 3 heartbeats consécutifs échouent, la session doit expirer
Scénario: Fermeture propre de l'application libère la session
Étant donné un stream actif sur "iPhone de Jean"
Quand l'utilisateur ferme proprement l'application (swipe kill ou logout)
Alors une requête "end_session" doit être envoyée à l'API
Et la session Redis doit être immédiatement supprimée
Et l'utilisateur peut démarrer un stream sur un autre appareil sans délai
# ============================================================================
# CAS LIMITES ET EDGE CASES
# ============================================================================
Scénario: Crash application sans fermeture propre
Étant donné un stream actif sur "iPhone de Jean"
Quand l'application crash sans envoyer "end_session"
Alors la session Redis reste active avec son TTL
Et après 2 minutes sans heartbeat, la session doit être marquée "stale"
Et un nouveau stream peut être démarré après 2 minutes sans heartbeat
Ou l'utilisateur peut forcer le kill via le conflit modal
Scénario: Connexion réseau perdue pendant stream
Étant donné un stream actif sur "iPhone de Jean"
Quand la connexion réseau est perdue pendant 5 minutes
Alors les heartbeats échouent mais l'app continue en buffer
Et après 3 heartbeats manqués (90 secondes), la session est considérée "stale"
Et un autre appareil peut démarrer un stream après 90 secondes
Scénario: Deux appareils tentent de démarrer simultanément (race condition)
Étant donné aucun stream actif
Quand "iPhone de Jean" et "iPad Pro" tentent de démarrer un stream à la même milliseconde
Alors le premier à obtenir le lock Redis doit réussir
Et le second doit recevoir un conflit 409
Et un mécanisme de lock distribué (Redis SET NX) doit être utilisé
Scénario: Utilisateur bascule rapidement entre appareils (<10s)
Étant donné un stream sur "iPhone de Jean"
Quand l'utilisateur kill la session et démarre sur "iPad Pro"
Et tente de redémarrer sur "iPhone de Jean" 5 secondes après
Alors le système doit détecter le conflit avec "iPad Pro"
Et proposer à nouveau de kill la session iPad
Et un délai de grâce de 5 secondes doit être respecté pour éviter les boucles
# ============================================================================
# GESTION UTILISATEUR GRATUIT (pas de multi-device)
# ============================================================================
Scénario: Utilisateur gratuit tente de streamer sur 2 appareils
Étant donné un utilisateur avec abonnement gratuit (pas Premium)
Et un stream actif sur "iPhone de Jean"
Quand l'utilisateur tente de lire sur "iPad Pro"
Alors une réponse HTTP 403 Forbidden doit être retournée
Et le message doit indiquer :
"""
Le multi-device nécessite un abonnement Premium.
Actuellement en lecture sur "iPhone de Jean".
Passez à Premium pour écouter sur plusieurs appareils.
"""
Et un bouton "Passer à Premium" doit être proposé
# ============================================================================
# INTERFACE ADMIN & GESTION DES CONFLITS
# ============================================================================
Scénario: Dashboard admin - voir sessions actives par utilisateur
Étant donné un administrateur connecté au dashboard
Quand l'admin recherche l'utilisateur "user-123"
Alors les sessions actives doivent être affichées :
| device_id | platform | started_at | content_id | duration |
| iphone-123 | iOS | 2026-02-03 14:00:00 | content-xyz | 15:30 |
Et l'admin doit pouvoir "Terminer la session" manuellement
Scénario: Support client - résolution conflit bloqué
Étant donné un utilisateur signale ne pas pouvoir lire sur aucun appareil
Et une session "fantôme" existe dans Redis (crash + heartbeat bloqué)
Quand le support client force la suppression de la session Redis
Alors la clé Redis "active_stream:user-123" doit être supprimée
Et l'utilisateur doit pouvoir redémarrer immédiatement
# ============================================================================
# MÉTRIQUES & MONITORING
# ============================================================================
Scénario: Logging des conflits pour analytics
Étant donné un conflit est détecté entre "iPhone de Jean" et "iPad Pro"
Quand le conflit est résolu par kill de session
Alors un événement analytics doit être loggé :
| event_type | stream_conflict_resolved |
| user_id | user-123 |
| previous_device | iphone-123 |
| new_device | ipad-456 |
| resolution | kill_previous |
| previous_session_duration | 900 |
| timestamp | 2026-02-03 14:15:00 |
Et ces métriques doivent être disponibles dans le dashboard
Scénario: Alerte monitoring - taux de conflits élevé
Étant donné le système monitore les conflits de stream
Quand le taux de conflits dépasse 15% des nouvelles sessions sur 1 heure
Alors une alerte Slack doit être envoyée à l'équipe technique
Et le message doit indiquer :
"""
Taux de conflits stream élevé : 18% (seuil : 15%)
Sessions impactées : 234 sur 1300
Action recommandée : vérifier expiration Redis et heartbeats
"""
# ============================================================================
# COMPATIBILITÉ AVEC D'AUTRES FEATURES
# ============================================================================
Scénario: Radio live avec conflit de stream
Étant donné un utilisateur écoute une radio live sur "iPhone de Jean"
Quand l'utilisateur démarre un stream sur "iPad Pro" et kill la session iPhone
Alors la radio live doit s'arrêter sur iPhone
Et le nouveau stream sur iPad peut être une radio live ou contenu normal
Et la progression audio-guide (si applicable) doit être sauvegardée
Scénario: Mode offline ne déclenche PAS de conflit
Étant donné un stream actif en ligne sur "iPhone de Jean"
Quand l'utilisateur écoute un contenu téléchargé en mode offline sur "iPad Pro"
Alors aucun conflit ne doit être détecté
Car le mode offline ne consomme pas de stream en ligne
Et les deux lectures peuvent coexister
Scénario: Multi-device avec partage familial (post-MVP)
Étant donné la fonctionnalité de partage familial est activée (post-MVP)
Et le compte principal a 3 profils famille
Quand chaque profil démarre un stream sur son appareil
Alors jusqu'à 3 streams simultanés doivent être autorisés
Et la détection de conflit doit s'appliquer par profil (1 stream/profil)