refactor(docs): réorganiser la documentation selon principes DDD
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.
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
# language: fr
|
||||
|
||||
@api @authentication @sessions @mvp
|
||||
Fonctionnalité: Gestion des sessions multi-appareils
|
||||
|
||||
En tant qu'utilisateur
|
||||
Je veux gérer mes sessions actives sur plusieurs appareils
|
||||
Afin de contrôler l'accès à mon compte et améliorer la sécurité
|
||||
|
||||
Contexte:
|
||||
Étant donné que le système supporte les sessions suivantes:
|
||||
| Paramètre | Valeur |
|
||||
| Nombre max de sessions simultanées | 5 |
|
||||
| Durée de vie d'une session | 30 jours |
|
||||
| Durée d'inactivité avant expiration | 7 jours |
|
||||
| Durée du token de refresh | 90 jours |
|
||||
| Taille max du stockage de session | 10 KB |
|
||||
|
||||
Scénario: Création d'une nouvelle session avec empreinte d'appareil
|
||||
Étant donné un utilisateur "alice@roadwave.fr" non connecté
|
||||
Quand l'utilisateur se connecte depuis un iPhone 14 Pro avec iOS 17.2
|
||||
Alors une nouvelle session est créée avec les métadonnées:
|
||||
| Champ | Valeur |
|
||||
| Device Type | mobile |
|
||||
| OS | iOS 17.2 |
|
||||
| App Version | 1.2.3 |
|
||||
| Device Model | iPhone 14 Pro |
|
||||
| Browser | N/A |
|
||||
| IP Address | 1.2.3.4 |
|
||||
| Geolocation | Paris, France |
|
||||
| Created At | 2026-02-03T14:32:18Z |
|
||||
| Last Activity | 2026-02-03T14:32:18Z |
|
||||
Et un token JWT avec durée de vie de 30 jours est généré
|
||||
Et un refresh token avec durée de vie de 90 jours est généré
|
||||
Et un événement "SESSION_CREATED" est enregistré
|
||||
Et la métrique "sessions.created" est incrémentée
|
||||
|
||||
Scénario: Connexion simultanée sur plusieurs appareils
|
||||
Étant donné un utilisateur "bob@roadwave.fr" connecté sur:
|
||||
| Appareil | OS | Dernière activité |
|
||||
| iPhone 13 | iOS 16.5 | Il y a 5 min |
|
||||
| iPad Pro | iPadOS 17.1 | Il y a 2 heures |
|
||||
| MacBook Pro | macOS 14.2 | Il y a 1 jour |
|
||||
Quand l'utilisateur se connecte depuis un Samsung Galaxy S23
|
||||
Alors une nouvelle session est créée
|
||||
Et l'utilisateur a maintenant 4 sessions actives
|
||||
Et toutes les sessions précédentes restent valides
|
||||
Et un événement "NEW_DEVICE_LOGIN" est enregistré
|
||||
Et une notification push est envoyée sur tous les appareils: "Nouvelle connexion depuis Samsung Galaxy S23"
|
||||
|
||||
Scénario: Limitation du nombre de sessions simultanées
|
||||
Étant donné un utilisateur "charlie@roadwave.fr" avec 5 sessions actives
|
||||
Quand l'utilisateur se connecte depuis un 6ème appareil
|
||||
Alors la session la plus ancienne est automatiquement révoquée
|
||||
Et une nouvelle session est créée pour le nouvel appareil
|
||||
Et l'utilisateur reçoit une notification: "Votre session sur [Ancien Appareil] a été fermée automatiquement"
|
||||
Et un événement "SESSION_EVICTED_MAX_LIMIT" est enregistré
|
||||
Et la métrique "sessions.evicted.max_limit" est incrémentée
|
||||
|
||||
Scénario: Liste des sessions actives dans les paramètres du compte
|
||||
Étant donné un utilisateur "david@roadwave.fr" avec 3 sessions actives
|
||||
Quand l'utilisateur accède à "Mon compte > Sécurité > Appareils connectés"
|
||||
Alors l'utilisateur voit la liste suivante:
|
||||
| Appareil | Localisation | Dernière activité | IP | Actions |
|
||||
| iPhone 14 Pro | Paris, France | Actif maintenant | 1.2.3.4 | [Cet appareil]|
|
||||
| iPad Air | Lyon, France | Il y a 2 heures | 5.6.7.8 | [Déconnecter] |
|
||||
| MacBook Pro | Marseille, FR | Il y a 3 jours | 9.10.11.12| [Déconnecter] |
|
||||
Et la session actuelle est clairement identifiée
|
||||
Et un bouton "Déconnecter tous les autres appareils" est disponible
|
||||
|
||||
Scénario: Révocation manuelle d'une session spécifique
|
||||
Étant donné un utilisateur "eve@roadwave.fr" avec 4 sessions actives
|
||||
Et il consulte la liste de ses appareils depuis son iPhone
|
||||
Quand l'utilisateur clique sur "Déconnecter" pour la session "MacBook Pro"
|
||||
Alors la session "MacBook Pro" est immédiatement révoquée
|
||||
Et le token JWT associé est invalidé dans Redis
|
||||
Et le refresh token est révoqué
|
||||
Et l'utilisateur sur le MacBook Pro est déconnecté lors de sa prochaine requête
|
||||
Et un événement "SESSION_REVOKED_MANUAL" est enregistré
|
||||
Et une notification est envoyée: "Vous avez été déconnecté de votre MacBook Pro"
|
||||
|
||||
Scénario: Déconnexion de tous les autres appareils
|
||||
Étant donné un utilisateur "frank@roadwave.fr" avec 5 sessions actives
|
||||
Et il suspecte un accès non autorisé
|
||||
Quand l'utilisateur clique sur "Déconnecter tous les autres appareils" depuis son iPhone
|
||||
Alors toutes les sessions sauf la session actuelle (iPhone) sont révoquées
|
||||
Et 4 tokens JWT sont invalidés
|
||||
Et 4 refresh tokens sont révoqués
|
||||
Et un événement "SESSIONS_REVOKED_ALL_OTHER" est enregistré
|
||||
Et une notification est envoyée sur tous les appareils déconnectés
|
||||
Et un email de confirmation est envoyé: "Vous avez déconnecté tous vos autres appareils"
|
||||
Et la métrique "sessions.revoked.bulk" est incrémentée
|
||||
|
||||
Scénario: Détection de connexion suspecte depuis un nouveau pays
|
||||
Étant donné un utilisateur "grace@roadwave.fr" avec sessions habituelles en France
|
||||
Quand l'utilisateur se connecte depuis une IP en Russie
|
||||
Alors une alerte de sécurité est déclenchée
|
||||
Et un email est envoyé: "Connexion détectée depuis Russie - Est-ce bien vous ?"
|
||||
Et une notification push est envoyée sur tous les appareils de confiance
|
||||
Et la session est créée mais marquée comme "suspecte"
|
||||
Et un événement "SUSPICIOUS_LOCATION_LOGIN" est enregistré avec niveau "HIGH"
|
||||
Et l'utilisateur doit confirmer son identité par code SMS avant d'accéder aux fonctionnalités sensibles
|
||||
|
||||
Scénario: Expiration automatique d'une session inactive
|
||||
Étant donné un utilisateur "henry@roadwave.fr" avec une session sur iPad
|
||||
Et la session n'a pas été utilisée depuis 8 jours
|
||||
Quand le job de nettoyage des sessions s'exécute
|
||||
Alors la session iPad est automatiquement révoquée
|
||||
Et le token JWT est invalidé
|
||||
Et le refresh token est révoqué
|
||||
Et un événement "SESSION_EXPIRED_INACTIVITY" est enregistré
|
||||
Et un email est envoyé: "Votre session sur iPad a expiré suite à 8 jours d'inactivité"
|
||||
Et la métrique "sessions.expired.inactivity" est incrémentée
|
||||
|
||||
Scénario: Rafraîchissement automatique du token avant expiration
|
||||
Étant donné un utilisateur "iris@roadwave.fr" avec une session active
|
||||
Et le token JWT expire dans 2 minutes
|
||||
Quand l'application mobile effectue une requête API
|
||||
Alors l'API détecte que le token expire bientôt
|
||||
Et un nouveau token JWT est généré automatiquement
|
||||
Et le nouveau token est retourné dans le header "X-Refreshed-Token"
|
||||
Et l'application mobile stocke le nouveau token
|
||||
Et un événement "TOKEN_REFRESHED" est enregistré
|
||||
Et la métrique "tokens.refreshed" est incrémentée
|
||||
|
||||
Scénario: Révocation de toutes les sessions lors d'un changement de mot de passe
|
||||
Étant donné un utilisateur "jack@roadwave.fr" avec 4 sessions actives
|
||||
Quand l'utilisateur change son mot de passe depuis son iPhone
|
||||
Alors toutes les sessions sauf la session actuelle (iPhone) sont révoquées
|
||||
Et tous les tokens JWT sont invalidés
|
||||
Et tous les refresh tokens sont révoqués
|
||||
Et un événement "SESSIONS_REVOKED_PASSWORD_CHANGE" est enregistré
|
||||
Et un email est envoyé: "Votre mot de passe a été modifié. Toutes vos autres sessions ont été déconnectées."
|
||||
Et des notifications push sont envoyées sur tous les appareils déconnectés
|
||||
|
||||
Scénario: Persistance de la session avec "Se souvenir de moi"
|
||||
Étant donné un utilisateur "kate@roadwave.fr" qui se connecte
|
||||
Quand l'utilisateur coche l'option "Se souvenir de moi"
|
||||
Alors la durée de vie du token JWT est étendue à 90 jours
|
||||
Et la durée de vie du refresh token est étendue à 180 jours
|
||||
Et la session persiste même après fermeture de l'application
|
||||
Et un cookie sécurisé "remember_token" est stocké (pour web)
|
||||
Et un événement "LONG_SESSION_CREATED" est enregistré
|
||||
Et la métrique "sessions.remember_me.enabled" est incrémentée
|
||||
|
||||
Scénario: Détection de vol de token et révocation automatique
|
||||
Étant donné un utilisateur "luke@roadwave.fr" avec une session active
|
||||
Et le token JWT a été volé et utilisé depuis une IP différente
|
||||
Quand le système détecte une utilisation simultanée du même token depuis 2 IP différentes
|
||||
Alors toutes les sessions de l'utilisateur sont immédiatement révoquées
|
||||
Et tous les tokens sont invalidés
|
||||
Et un email d'alerte critique est envoyé: "Activité suspecte détectée - Toutes vos sessions ont été fermées"
|
||||
Et une notification push urgente est envoyée sur tous les appareils
|
||||
Et l'utilisateur doit réinitialiser son mot de passe avant de se reconnecter
|
||||
Et un événement "TOKEN_THEFT_DETECTED" est enregistré avec niveau "CRITICAL"
|
||||
Et l'équipe de sécurité est alertée via webhook
|
||||
|
||||
Scénario: Synchronisation des informations de session en temps réel
|
||||
Étant donné un utilisateur "mary@roadwave.fr" connecté sur 3 appareils
|
||||
Quand l'utilisateur révoque une session depuis son iPhone
|
||||
Alors la liste des sessions est mise à jour en temps réel sur tous les appareils via WebSocket
|
||||
Et l'appareil déconnecté reçoit immédiatement une notification de déconnexion
|
||||
Et l'UI est rafraîchie automatiquement sur tous les appareils connectés
|
||||
Et la métrique "sessions.realtime_sync" est incrémentée
|
||||
|
||||
Scénario: Métriques de performance de gestion des sessions
|
||||
Étant donné que le système gère 100 000 sessions actives
|
||||
Quand les métriques de performance sont collectées
|
||||
Alors les indicateurs suivants sont respectés:
|
||||
| Métrique | Valeur cible |
|
||||
| Temps de création de session | < 50ms |
|
||||
| Temps de validation de token | < 20ms |
|
||||
| Temps de révocation de session | < 100ms |
|
||||
| Latence de synchronisation temps réel | < 500ms |
|
||||
| Taux de succès du refresh automatique | > 99.9% |
|
||||
Et les métriques sont exportées vers le système de monitoring
|
||||
Et des alertes sont déclenchées si les seuils sont dépassés
|
||||
|
||||
Scénario: Stockage sécurisé des sessions dans Redis
|
||||
Étant donné un utilisateur "nathan@roadwave.fr" avec une session active
|
||||
Quand la session est stockée dans Redis
|
||||
Alors les données suivantes sont chiffrées:
|
||||
| Champ | Chiffrement |
|
||||
| User ID | Hash |
|
||||
| Refresh Token | AES-256 |
|
||||
| Device Info | Non |
|
||||
| IP Address | Hash |
|
||||
Et la clé Redis a un TTL correspondant à la durée de vie de la session
|
||||
Et les données sensibles ne sont jamais loggées en clair
|
||||
Et les accès à Redis sont audités
|
||||
Et la métrique "sessions.storage.encrypted" est incrémentée
|
||||
Reference in New Issue
Block a user