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,282 @@
|
||||
# language: fr
|
||||
|
||||
@rgpd @data-portability
|
||||
Fonctionnalité: Portabilité des données (Article 20 RGPD)
|
||||
|
||||
# 13.3 - Export JSON + HTML + ZIP, génération asynchrone
|
||||
|
||||
Contexte:
|
||||
Étant donné que je suis un utilisateur connecté
|
||||
Et que j'ai utilisé l'application depuis 6 mois
|
||||
|
||||
Scénario: Demande d'export depuis les paramètres
|
||||
Étant donné que je suis dans "Paramètres > Confidentialité"
|
||||
Quand je clique sur "Exporter mes données"
|
||||
Alors une page d'information s'affiche expliquant:
|
||||
"""
|
||||
Vous allez recevoir une archive contenant toutes vos données personnelles:
|
||||
- Profil et informations de compte
|
||||
- Historique d'écoute complet
|
||||
- Contenus audio que vous avez créés
|
||||
- Abonnements et likes
|
||||
- Centres d'intérêt
|
||||
- Historique des consentements
|
||||
|
||||
L'export sera généré sous 48h maximum et vous recevrez un email avec un lien de téléchargement valide 7 jours.
|
||||
"""
|
||||
Et un bouton "Confirmer l'export" est disponible
|
||||
|
||||
Scénario: Confirmation et démarrage de l'export
|
||||
Étant donné que je clique sur "Confirmer l'export"
|
||||
Quand la demande est validée
|
||||
Alors un message de confirmation s'affiche:
|
||||
"""
|
||||
Votre demande d'export a été prise en compte. Vous recevrez un email sous 48h avec un lien de téléchargement.
|
||||
"""
|
||||
Et un worker background démarre la génération de l'export
|
||||
Et le statut de l'export est "En cours de génération"
|
||||
Et je peux voir le statut dans "Paramètres > Confidentialité > Mes exports"
|
||||
|
||||
# Structure de l'export
|
||||
|
||||
Scénario: Contenu de l'archive ZIP
|
||||
Étant donné que mon export est généré
|
||||
Quand je télécharge et ouvre l'archive
|
||||
Alors l'archive a la structure suivante:
|
||||
"""
|
||||
export-roadwave-[user_id]-[date].zip
|
||||
├── export.json # Machine-readable (JSON complet)
|
||||
├── index.html # Human-readable (stylé, navigation)
|
||||
├── audio/
|
||||
│ ├── content-123.opus # Mes contenus créés
|
||||
│ ├── content-456.opus
|
||||
│ └── ...
|
||||
└── README.txt # Instructions et informations
|
||||
"""
|
||||
Et tous les fichiers sont inclus
|
||||
|
||||
Scénario: Contenu du fichier export.json
|
||||
Étant donné que j'ouvre le fichier export.json
|
||||
Quand j'analyse le contenu
|
||||
Alors le JSON contient les sections suivantes:
|
||||
| section | description |
|
||||
| profile | Email, pseudo, date inscription, bio |
|
||||
| listening_history | Historique complet d'écoute |
|
||||
| created_contents | Métadonnées des contenus créés |
|
||||
| subscriptions | Liste des créateurs suivis |
|
||||
| likes | Liste des contenus likés |
|
||||
| interest_gauges | Valeurs des jauges d'intérêt |
|
||||
| consent_history | Historique des consentements |
|
||||
| premium_subscription | Informations abonnement Premium |
|
||||
Et le JSON est formaté de manière lisible (indentation)
|
||||
Et toutes les dates sont au format ISO 8601
|
||||
|
||||
Scénario: Contenu du fichier index.html
|
||||
Étant donné que j'ouvre le fichier index.html dans un navigateur
|
||||
Quand la page se charge
|
||||
Alors je vois un site web stylé avec navigation
|
||||
Et les sections suivantes sont affichées:
|
||||
| section | contenu |
|
||||
| Mon profil | Email, pseudo, date inscription, statistiques |
|
||||
| Historique d'écoute | Liste paginée avec dates, titres, durées |
|
||||
| Mes contenus | Liste avec lectures audio intégrées |
|
||||
| Mes abonnements | Grille des créateurs suivis |
|
||||
| Mes likes | Liste des contenus likés avec liens |
|
||||
| Centres d'intérêt | Graphiques des jauges |
|
||||
| Consentements | Historique des acceptations/refus |
|
||||
Et la navigation est intuitive (menu latéral)
|
||||
Et le design est responsive (mobile/desktop)
|
||||
|
||||
Scénario: Fichiers audio inclus dans l'export
|
||||
Étant donné que j'ai créé 5 contenus audio
|
||||
Quand mon export est généré
|
||||
Alors le dossier `audio/` contient mes 5 fichiers
|
||||
Et les fichiers sont au format Opus original
|
||||
Et chaque fichier est nommé: `content-[id].opus`
|
||||
Et les fichiers audio correspondent aux métadonnées dans export.json
|
||||
|
||||
Scénario: Fichier README.txt explicatif
|
||||
Étant donné que j'ouvre le fichier README.txt
|
||||
Quand je lis le contenu
|
||||
Alors le fichier explique:
|
||||
"""
|
||||
Bienvenue dans votre export de données RoadWave.
|
||||
|
||||
Contenu de l'archive:
|
||||
- export.json: Toutes vos données au format JSON (machine-readable)
|
||||
- index.html: Visualisation web de vos données (ouvrir dans un navigateur)
|
||||
- audio/: Vos contenus audio créés au format Opus
|
||||
|
||||
Cet export a été généré le [date] et contient toutes vos données personnelles conformément à l'article 20 du RGPD.
|
||||
|
||||
Pour toute question: dpo@roadwave.fr
|
||||
"""
|
||||
|
||||
# Données exportées en détail
|
||||
|
||||
Plan du Scénario: Données de profil exportées
|
||||
Étant donné que mon export est généré
|
||||
Quand j'ouvre export.json et lis la section "profile"
|
||||
Alors je trouve les données suivantes:
|
||||
| champ | exemple |
|
||||
| email | user@example.com |
|
||||
| pseudo | @roadwave_user |
|
||||
| date_inscription | 2025-01-15T10:30:00Z |
|
||||
| bio | Passionné d'automobile... |
|
||||
| avatar_url | https://cdn.roadwave.fr/... |
|
||||
| compte_verifie | false |
|
||||
| premium | true |
|
||||
|
||||
Scénario: Historique d'écoute exporté
|
||||
Étant donné que j'ai écouté 150 contenus depuis 6 mois
|
||||
Quand mon export est généré
|
||||
Alors la section "listening_history" contient 150 entrées
|
||||
Et chaque entrée contient:
|
||||
| champ | exemple |
|
||||
| content_id | C123 |
|
||||
| content_title | Histoire de la Tour Eiffel |
|
||||
| creator_name | @historien_paris |
|
||||
| listened_at | 2025-01-20T15:30:00Z |
|
||||
| duration_listened | 180 (secondes) |
|
||||
| completion_rate | 0.85 (85%) |
|
||||
| location | [geohash ou coords précises]|
|
||||
Et les contenus sont triés par date décroissante
|
||||
|
||||
Scénario: Centres d'intérêt exportés
|
||||
Étant donné que mes jauges d'intérêt sont:
|
||||
| catégorie | valeur |
|
||||
| Automobile | 78% |
|
||||
| Voyage | 65% |
|
||||
| Musique | 52% |
|
||||
| Politique | 30% |
|
||||
Quand mon export est généré
|
||||
Alors la section "interest_gauges" contient ces valeurs
|
||||
Et chaque jauge indique la date de dernière modification
|
||||
|
||||
Scénario: Historique des consentements exporté
|
||||
Étant donné que j'ai modifié mes consentements plusieurs fois
|
||||
Quand mon export est généré
|
||||
Alors la section "consent_history" contient:
|
||||
| date | consent_type | accepted | version |
|
||||
| 2025-01-15T10:00 | Fonctionnel | oui | 1 |
|
||||
| 2025-01-15T10:00 | Analytique | oui | 1 |
|
||||
| 2025-01-15T10:00 | Marketing | non | 1 |
|
||||
| 2025-03-20T14:30 | Analytique | non | 1 |
|
||||
Et l'historique complet est visible
|
||||
|
||||
# Génération asynchrone
|
||||
|
||||
Scénario: Génération asynchrone pour éviter timeout
|
||||
Étant donné que j'ai beaucoup de données (500 contenus créés, 10 000 écoutes)
|
||||
Quand je demande un export
|
||||
Alors la génération se fait en arrière-plan via un worker
|
||||
Et la page web ne timeout pas
|
||||
Et je peux continuer à utiliser l'application pendant la génération
|
||||
Et je reçois un email quand l'export est prêt
|
||||
|
||||
Scénario: Délai de génération conforme RGPD
|
||||
Étant donné que je demande un export le 2025-01-20 à 10:00
|
||||
Quand le worker génère l'export
|
||||
Alors l'export est disponible maximum 48h plus tard (avant le 2025-01-22 à 10:00)
|
||||
Et la plupart des exports sont prêts en moins de 6h
|
||||
Et le délai respecte l'article 20 du RGPD
|
||||
|
||||
Scénario: Email de notification avec lien de téléchargement
|
||||
Étant donné que mon export est terminé
|
||||
Quand le worker finalise la génération
|
||||
Alors je reçois un email avec le sujet "Votre export de données RoadWave est prêt"
|
||||
Et l'email contient:
|
||||
"""
|
||||
Bonjour,
|
||||
|
||||
Votre export de données est prêt. Vous pouvez le télécharger via le lien ci-dessous:
|
||||
|
||||
[Télécharger mon export] (lien sécurisé, expire dans 7 jours)
|
||||
|
||||
Taille de l'archive: 45 MB
|
||||
Contenu: Profil, historique, contenus audio, abonnements, likes, centres d'intérêt
|
||||
|
||||
Pour toute question: dpo@roadwave.fr
|
||||
"""
|
||||
Et le lien de téléchargement est sécurisé (token unique)
|
||||
|
||||
Scénario: Lien de téléchargement expire après 7 jours
|
||||
Étant donné que mon export a été généré le 2025-01-20
|
||||
Et que je reçois le lien de téléchargement
|
||||
Quand j'essaie d'accéder au lien le 2025-01-28 (8 jours plus tard)
|
||||
Alors le lien est expiré
|
||||
Et je reçois un message "Ce lien a expiré. Veuillez demander un nouvel export."
|
||||
Et je peux demander un nouvel export si nécessaire
|
||||
|
||||
# Limite anti-abus
|
||||
|
||||
Scénario: Limite de 1 export par mois
|
||||
Étant donné que j'ai demandé un export le 2025-01-15
|
||||
Quand j'essaie de demander un nouvel export le 2025-01-20
|
||||
Alors je reçois un message d'erreur:
|
||||
"""
|
||||
Vous avez déjà demandé un export ce mois-ci. Vous pourrez demander un nouvel export à partir du 2025-02-15.
|
||||
"""
|
||||
Et le bouton "Confirmer l'export" est désactivé
|
||||
Et la date du prochain export possible est affichée
|
||||
|
||||
Scénario: Nouvel export possible après 1 mois
|
||||
Étant donné que j'ai demandé un export le 2025-01-15
|
||||
Quand la date atteint le 2025-02-15
|
||||
Alors je peux demander un nouvel export
|
||||
Et le bouton "Confirmer l'export" est actif
|
||||
Et aucune limite ne s'applique
|
||||
|
||||
# Sécurité
|
||||
|
||||
Scénario: Lien de téléchargement sécurisé avec token unique
|
||||
Étant donné que mon export est prêt
|
||||
Quand je reçois le lien de téléchargement
|
||||
Alors le lien contient un token unique et non devinable
|
||||
Et le format du lien est: `https://roadwave.fr/exports/download/[token_unique]`
|
||||
Et le token est valide uniquement pour mon compte
|
||||
Et le token expire après 7 jours ou après 3 téléchargements
|
||||
|
||||
Scénario: Vérification de l'authentification avant téléchargement
|
||||
Étant donné que je reçois le lien d'export
|
||||
Quand je clique sur le lien
|
||||
Alors le système vérifie que je suis connecté
|
||||
Et si je ne suis pas connecté, je suis redirigé vers la page de connexion
|
||||
Et après connexion, le téléchargement démarre automatiquement
|
||||
Et seul le propriétaire du compte peut télécharger l'export
|
||||
|
||||
# Conformité RGPD Article 20
|
||||
|
||||
Scénario: Conformité portabilité des données
|
||||
Étant donné que mon export est généré
|
||||
Quand un auditeur RGPD vérifie la conformité
|
||||
Alors l'export respecte les exigences de l'article 20:
|
||||
| exigence RGPD | respecté |
|
||||
| Format structuré (JSON) | oui |
|
||||
| Format couramment utilisé | oui |
|
||||
| Format lisible par machine | oui |
|
||||
| Format interopérable | oui |
|
||||
| Délai raisonnable (48h max) | oui |
|
||||
| Exhaustivité des données | oui |
|
||||
| Gratuité pour l'utilisateur | oui |
|
||||
|
||||
Scénario: Gratuité de l'export
|
||||
Étant donné que je demande un export de mes données
|
||||
Quand l'export est généré et téléchargé
|
||||
Alors aucun coût n'est facturé
|
||||
Et l'export est entièrement gratuit
|
||||
Et aucune inscription Premium n'est requise
|
||||
Et le droit à la portabilité est accessible à tous les utilisateurs
|
||||
|
||||
# Statut de l'export visible
|
||||
|
||||
Scénario: Suivi du statut de génération
|
||||
Étant donné que j'ai demandé un export
|
||||
Quand j'ouvre "Paramètres > Confidentialité > Mes exports"
|
||||
Alors je vois le statut actuel:
|
||||
| statut | description |
|
||||
| En cours de génération| Worker en train de générer l'archive |
|
||||
| Prêt au téléchargement| Lien de téléchargement disponible |
|
||||
| Expiré | Lien expiré (>7j), nouvel export requis |
|
||||
Et la date de demande est affichée
|
||||
Et la taille estimée de l'archive est visible
|
||||
Reference in New Issue
Block a user