feat(rgpd): compléter documentation RGPD avec 12 nouvelles sections
Règles RGPD (docs/domains/_shared/rules/rgpd.md): - Ajouter sections 13.11-13.22 (droits utilisateurs, mineurs, sécurité) - Droit de rectification, opposition, limitation du traitement - Gestion des mineurs: 13 ans minimum + consentement parental 13-15 ans - Protection renforcée: RoadWave Kids pour < 13 ans - Sécurité: chiffrement multi-niveaux, procédure breach 72h CNIL - Politique de confidentialité avec versioning - Sous-traitants, DPIA, délais de réponse Entités (6 nouvelles): - PARENTAL_CONSENTS + PARENTAL_CONTROLS (workflow 13-15 ans) - PRIVACY_POLICY_VERSIONS + USER_POLICY_ACCEPTANCES - ACCOUNT_DELETIONS (grace period 30j) - BREACH_INCIDENTS + BREACH_AFFECTED_USERS - USER_PROFILE_HISTORY (audit trail rectification) - DATA_RETENTION_LOGS (purge 5 ans) Diagrammes séquences (5 nouveaux): - Consentement parental avec validation email - Anonymisation GPS automatique après 24h - Notification breach CNIL (procédure 72h) - Export données asynchrone - Suppression compte avec grace period Cycles de vie (3 nouveaux + 1 enrichi): - parental-consent-lifecycle.md - breach-incident-lifecycle.md - account-deletion-lifecycle.md - user-account-lifecycle.md (ajout états mineurs, frozen) Features BDD (4 nouvelles, 195 scénarios RGPD): - minors-protection.feature (9 scénarios) - data-security.feature (12 scénarios) - privacy-policy.feature (8 scénarios) - user-rights.feature (8 scénarios) Infrastructure: - Réorganiser docs générées: docs/bdd + output → generated/bdd + generated/pdf - Mettre à jour mkdocs.yml, Makefile, scripts Python - Ajouter /generated/ au .gitignore
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -64,4 +64,6 @@ config/*.local.yaml
|
||||
# MkDocs
|
||||
site/
|
||||
.cache/
|
||||
docs/bdd/
|
||||
|
||||
# Generated documentation
|
||||
/generated/
|
||||
|
||||
2
Makefile
2
Makefile
@@ -70,7 +70,7 @@ clean:
|
||||
## docs-clean: Remove generated documentation (BDD docs and PDF)
|
||||
docs-clean:
|
||||
@echo "$(YELLOW)Cleaning generated documentation...$(NC)"
|
||||
@rm -rf docs/bdd/ output/RoadWave_Documentation.pdf
|
||||
@rm -rf generated/
|
||||
@docker rmi roadwave-pdf-generator 2>/dev/null || true
|
||||
@echo "$(GREEN)✓ Documentation cleaned$(NC)"
|
||||
|
||||
|
||||
40
docs/domains/_shared/entities/account-deletions.md
Normal file
40
docs/domains/_shared/entities/account-deletions.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Account Deletions
|
||||
|
||||
📖 Suppressions de compte avec grace period 30 jours (Article 17 RGPD)
|
||||
|
||||
## Diagramme
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
USERS ||--o| ACCOUNT_DELETIONS : "demande"
|
||||
|
||||
ACCOUNT_DELETIONS {
|
||||
uuid id PK
|
||||
uuid user_id FK
|
||||
string status
|
||||
string cancellation_token
|
||||
timestamp requested_at
|
||||
timestamp effective_at "requested_at + 30j"
|
||||
timestamp cancelled_at
|
||||
timestamp deleted_at
|
||||
string deletion_reason
|
||||
json deleted_data_summary
|
||||
}
|
||||
```
|
||||
|
||||
## Légende
|
||||
|
||||
**Statuts** :
|
||||
- `pending`: Grace period actif (30j), compte désactivé, annulation possible
|
||||
- `cancelled`: Utilisateur a annulé via lien email
|
||||
- `completed`: Suppression effective réalisée après 30j
|
||||
|
||||
**Processus** :
|
||||
1. Demande → compte désactivé, contenus cachés
|
||||
2. Email avec `cancellation_token` (valide 30j)
|
||||
3. Si annulation → `status = cancelled`, compte réactivé
|
||||
4. Si 30j écoulés → job cron supprime données, anonymise contenus
|
||||
|
||||
**Données supprimées** :
|
||||
- Profil utilisateur, historique GPS/écoute, sessions
|
||||
- Contenus créés : anonymisés (`créateur = "Utilisateur supprimé"`)
|
||||
51
docs/domains/_shared/entities/breach-incidents.md
Normal file
51
docs/domains/_shared/entities/breach-incidents.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Breach Incidents
|
||||
|
||||
📖 Registre violations de données (Article 33 RGPD)
|
||||
|
||||
## Diagramme
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
BREACH_INCIDENTS ||--o{ BREACH_AFFECTED_USERS : "impacte"
|
||||
USERS ||--o{ BREACH_AFFECTED_USERS : "est impacté"
|
||||
|
||||
BREACH_INCIDENTS {
|
||||
uuid id PK
|
||||
string severity "low/medium/high/critical"
|
||||
text description
|
||||
json data_categories_affected
|
||||
int estimated_users_count
|
||||
timestamp detected_at
|
||||
timestamp contained_at
|
||||
timestamp cnil_notified_at
|
||||
timestamp users_notified_at
|
||||
text mitigation_actions
|
||||
boolean cnil_notification_required
|
||||
boolean user_notification_required
|
||||
}
|
||||
|
||||
BREACH_AFFECTED_USERS {
|
||||
uuid id PK
|
||||
uuid breach_id FK
|
||||
uuid user_id FK
|
||||
timestamp notified_at
|
||||
string notification_channel "email/push/sms"
|
||||
}
|
||||
```
|
||||
|
||||
## Légende
|
||||
|
||||
**Sévérité** :
|
||||
- `low`: Pas de notification requise (mesures techniques suffisantes)
|
||||
- `medium`: Notification CNIL uniquement
|
||||
- `high`: Notification CNIL + utilisateurs
|
||||
- `critical`: Notification immédiate tous canaux + SMS fondateur
|
||||
|
||||
**Timeline 72h** :
|
||||
- H+0 : Détection, confinement
|
||||
- H+24 : Évaluation gravité
|
||||
- H+48 : Notification CNIL si requis
|
||||
- H+72 : Notification utilisateurs si risque élevé
|
||||
|
||||
**Catégories de données** :
|
||||
- `data_categories_affected`: JSON `["gps", "email", "listening_history"]`
|
||||
44
docs/domains/_shared/entities/data-retention-logs.md
Normal file
44
docs/domains/_shared/entities/data-retention-logs.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Data Retention Logs
|
||||
|
||||
📖 Logs purges automatiques inactivité (Article 5 RGPD - Minimisation)
|
||||
|
||||
## Diagramme
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
DATA_RETENTION_LOGS {
|
||||
uuid id PK
|
||||
string action_type
|
||||
int users_processed
|
||||
int users_warned
|
||||
int users_deleted
|
||||
json details
|
||||
timestamp executed_at
|
||||
bigint execution_duration_ms
|
||||
}
|
||||
```
|
||||
|
||||
## Légende
|
||||
|
||||
**Action types** :
|
||||
- `check_inactive`: Vérification quotidienne comptes inactifs > 5 ans
|
||||
- `send_warnings`: Envoi notifications (90j/30j/7j avant suppression)
|
||||
- `delete_accounts`: Suppression effective comptes inactifs
|
||||
|
||||
**Règles de conservation** :
|
||||
- Auditeur : 5 ans inactivité → suppression
|
||||
- Créateur actif : jamais (tant que contenus écoutés)
|
||||
- Créateur inactif : 5 ans + 2 ans sans écoute → suppression
|
||||
|
||||
**Details JSON** :
|
||||
```json
|
||||
{
|
||||
"threshold_date": "2021-02-08",
|
||||
"user_ids_deleted": ["uuid1", "uuid2"],
|
||||
"notifications_sent": {
|
||||
"90_days": 15,
|
||||
"30_days": 8,
|
||||
"7_days": 3
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -16,6 +16,15 @@ erDiagram
|
||||
USERS ||--o{ INTEREST_GAUGES : "possède"
|
||||
USERS ||--o{ REPORTS : "signale"
|
||||
USERS ||--o{ DATA_EXPORTS : "demande"
|
||||
USERS ||--o{ PARENTAL_CONSENTS : "a"
|
||||
USERS ||--o{ ACCOUNT_DELETIONS : "demande"
|
||||
USERS ||--o{ USER_PROFILE_HISTORY : "modifie"
|
||||
|
||||
PARENTAL_CONSENTS ||--|| PARENTAL_CONTROLS : "configure"
|
||||
PRIVACY_POLICY_VERSIONS ||--o{ USER_POLICY_ACCEPTANCES : "acceptée par"
|
||||
USERS ||--o{ USER_POLICY_ACCEPTANCES : "accepte"
|
||||
BREACH_INCIDENTS ||--o{ BREACH_AFFECTED_USERS : "impacte"
|
||||
USERS ||--o{ BREACH_AFFECTED_USERS : "est impacté"
|
||||
|
||||
CONTENTS ||--o{ LISTENING_HISTORY : "écouté"
|
||||
CONTENTS }o--|| USERS : "créé par"
|
||||
@@ -161,6 +170,80 @@ erDiagram
|
||||
timestamp generated_at
|
||||
timestamp expires_at
|
||||
}
|
||||
|
||||
PARENTAL_CONSENTS {
|
||||
uuid id PK
|
||||
uuid user_id FK
|
||||
string parent_email
|
||||
boolean validated
|
||||
timestamp validated_at
|
||||
timestamp revoked_at
|
||||
}
|
||||
|
||||
PARENTAL_CONTROLS {
|
||||
uuid id PK
|
||||
uuid parental_consent_id FK
|
||||
boolean gps_enabled
|
||||
boolean messaging_enabled
|
||||
boolean content_16plus_enabled
|
||||
}
|
||||
|
||||
PRIVACY_POLICY_VERSIONS {
|
||||
uuid id PK
|
||||
string version
|
||||
boolean major_change
|
||||
timestamp effective_date
|
||||
}
|
||||
|
||||
USER_POLICY_ACCEPTANCES {
|
||||
uuid id PK
|
||||
uuid user_id FK
|
||||
uuid policy_version_id FK
|
||||
boolean accepted
|
||||
timestamp accepted_at
|
||||
}
|
||||
|
||||
ACCOUNT_DELETIONS {
|
||||
uuid id PK
|
||||
uuid user_id FK
|
||||
string status
|
||||
timestamp requested_at
|
||||
timestamp effective_at
|
||||
timestamp deleted_at
|
||||
}
|
||||
|
||||
BREACH_INCIDENTS {
|
||||
uuid id PK
|
||||
string severity
|
||||
int estimated_users_count
|
||||
timestamp detected_at
|
||||
timestamp cnil_notified_at
|
||||
boolean user_notification_required
|
||||
}
|
||||
|
||||
BREACH_AFFECTED_USERS {
|
||||
uuid id PK
|
||||
uuid breach_id FK
|
||||
uuid user_id FK
|
||||
timestamp notified_at
|
||||
}
|
||||
|
||||
USER_PROFILE_HISTORY {
|
||||
uuid id PK
|
||||
uuid user_id FK
|
||||
string field_name
|
||||
text old_value
|
||||
text new_value
|
||||
timestamp changed_at
|
||||
}
|
||||
|
||||
DATA_RETENTION_LOGS {
|
||||
uuid id PK
|
||||
string action_type
|
||||
int users_processed
|
||||
int users_deleted
|
||||
timestamp executed_at
|
||||
}
|
||||
```
|
||||
|
||||
## Légende
|
||||
@@ -205,6 +288,27 @@ erDiagram
|
||||
- **DATA_EXPORTS** : Exports de données utilisateur ([détails](exports.md))
|
||||
- Portabilité RGPD Article 20, délai 48h max
|
||||
|
||||
- **PARENTAL_CONSENTS** : Consentements parentaux 13-15 ans ([détails](parental-consents.md))
|
||||
- Workflow validation email parent, token expire 7j
|
||||
|
||||
- **PARENTAL_CONTROLS** : Paramètres contrôle parental ([détails](parental-consents.md))
|
||||
- GPS, messagerie, contenus +16 configurables par parent
|
||||
|
||||
- **PRIVACY_POLICY_VERSIONS** : Versioning politique confidentialité ([détails](privacy-policy-versions.md))
|
||||
- Popup si changement majeur, historique acceptations
|
||||
|
||||
- **ACCOUNT_DELETIONS** : Suppressions avec grace period 30j ([détails](account-deletions.md))
|
||||
- Annulation possible, suppression effective automatique
|
||||
|
||||
- **BREACH_INCIDENTS** : Registre violations de données ([détails](breach-incidents.md))
|
||||
- Procédure 72h CNIL, notification utilisateurs si risque élevé
|
||||
|
||||
- **USER_PROFILE_HISTORY** : Audit trail modifications profil ([détails](user-profile-history.md))
|
||||
- Droit rectification Article 16, preuve légale
|
||||
|
||||
- **DATA_RETENTION_LOGS** : Logs purges automatiques ([détails](data-retention-logs.md))
|
||||
- Inactivité 5 ans, notifications 90j/30j/7j
|
||||
|
||||
**Entités recommandation & modération** :
|
||||
|
||||
- **INTEREST_GAUGES** : Jauges de centres d'intérêt ([détails](interest-gauges.md))
|
||||
|
||||
49
docs/domains/_shared/entities/parental-consents.md
Normal file
49
docs/domains/_shared/entities/parental-consents.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Parental Consents
|
||||
|
||||
📖 Consentements parentaux pour utilisateurs 13-15 ans (Article 8 RGPD)
|
||||
|
||||
## Diagramme
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
USERS ||--o{ PARENTAL_CONSENTS : "a"
|
||||
PARENTAL_CONSENTS ||--|| PARENTAL_CONTROLS : "configure"
|
||||
|
||||
PARENTAL_CONSENTS {
|
||||
uuid id PK
|
||||
uuid user_id FK "Ado 13-15 ans"
|
||||
string parent_email
|
||||
string validation_token
|
||||
boolean validated
|
||||
timestamp token_expires_at
|
||||
timestamp validated_at
|
||||
inet parent_ip
|
||||
string parent_user_agent
|
||||
timestamp revoked_at
|
||||
string revocation_reason
|
||||
}
|
||||
|
||||
PARENTAL_CONTROLS {
|
||||
uuid id PK
|
||||
uuid parental_consent_id FK
|
||||
boolean gps_enabled
|
||||
boolean messaging_enabled
|
||||
boolean content_16plus_enabled
|
||||
json weekly_digest_config
|
||||
timestamp updated_at
|
||||
}
|
||||
```
|
||||
|
||||
## Légende
|
||||
|
||||
**Workflow** :
|
||||
1. Ado saisit email parent → `validation_token` généré (expire 7j)
|
||||
2. Parent clique lien → `validated = true`
|
||||
3. Parent configure `PARENTAL_CONTROLS`
|
||||
4. Révocation possible → `revoked_at` renseigné
|
||||
|
||||
**Restrictions par défaut (13-15 ans)** :
|
||||
- `gps_enabled`: `false` (GeoIP uniquement)
|
||||
- `messaging_enabled`: `false`
|
||||
- `content_16plus_enabled`: `false`
|
||||
- Dashboard parent : notifications hebdomadaires activité
|
||||
41
docs/domains/_shared/entities/privacy-policy-versions.md
Normal file
41
docs/domains/_shared/entities/privacy-policy-versions.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Privacy Policy Versions
|
||||
|
||||
📖 Versioning politique de confidentialité (Articles 13-14 RGPD)
|
||||
|
||||
## Diagramme
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
PRIVACY_POLICY_VERSIONS ||--o{ USER_POLICY_ACCEPTANCES : "acceptée par"
|
||||
USERS ||--o{ USER_POLICY_ACCEPTANCES : "accepte"
|
||||
|
||||
PRIVACY_POLICY_VERSIONS {
|
||||
uuid id PK
|
||||
string version "v1.0, v2.0, etc."
|
||||
text content_markdown
|
||||
boolean major_change
|
||||
text changelog
|
||||
timestamp effective_date
|
||||
timestamp created_at
|
||||
}
|
||||
|
||||
USER_POLICY_ACCEPTANCES {
|
||||
uuid id PK
|
||||
uuid user_id FK
|
||||
uuid policy_version_id FK
|
||||
boolean accepted
|
||||
timestamp accepted_at
|
||||
inet ip_address
|
||||
}
|
||||
```
|
||||
|
||||
## Légende
|
||||
|
||||
**Versioning** :
|
||||
- `major_change`: `true` → popup obligatoire pour tous les utilisateurs
|
||||
- `major_change`: `false` → notification simple
|
||||
- Fichier source : `docs/legal/politique-confidentialite.md` (versionné Git)
|
||||
|
||||
**Popup si changement majeur** :
|
||||
- Utilisateur doit accepter nouvelle version pour continuer
|
||||
- Refus → compte gelé (lecture seule)
|
||||
38
docs/domains/_shared/entities/user-profile-history.md
Normal file
38
docs/domains/_shared/entities/user-profile-history.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# User Profile History
|
||||
|
||||
📖 Audit trail modifications profil (Article 16 RGPD - Droit de rectification)
|
||||
|
||||
## Diagramme
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
USERS ||--o{ USER_PROFILE_HISTORY : "modifie"
|
||||
|
||||
USER_PROFILE_HISTORY {
|
||||
uuid id PK
|
||||
uuid user_id FK
|
||||
string field_name "email/username/bio/etc."
|
||||
text old_value
|
||||
text new_value
|
||||
string change_reason "user_edit/admin_correction/gdpr_request"
|
||||
inet ip_address
|
||||
timestamp changed_at
|
||||
}
|
||||
```
|
||||
|
||||
## Légende
|
||||
|
||||
**Champs trackés** :
|
||||
- `email`: Re-vérification requise
|
||||
- `username`: Limite 1 changement/30j
|
||||
- `bio`, `avatar_url`, `date_of_birth`
|
||||
|
||||
**Change reasons** :
|
||||
- `user_edit`: Modification self-service utilisateur
|
||||
- `admin_correction`: Correction par admin
|
||||
- `gdpr_request`: Suite demande RGPD formelle
|
||||
|
||||
**Audit** :
|
||||
- Historique complet conservé (preuve légale)
|
||||
- Accessible utilisateur : "Historique de mes modifications"
|
||||
- Accessible DPO : investigations
|
||||
@@ -0,0 +1,110 @@
|
||||
# language: fr
|
||||
|
||||
@privacy @rgpd @security
|
||||
Fonctionnalité: Sécurité des données (Article 32 RGPD)
|
||||
En tant que responsable de traitement
|
||||
Je veux garantir la sécurité des données personnelles
|
||||
Afin de prévenir les violations et fuites
|
||||
|
||||
# Chiffrement transport
|
||||
@encryption @tls
|
||||
Scénario: TLS 1.3 obligatoire pour toutes les communications
|
||||
Quand un client tente de se connecter à l'API
|
||||
Alors la connexion utilise TLS 1.3 uniquement
|
||||
Et les protocoles TLS 1.0, 1.1, 1.2 sont refusés
|
||||
Et le certificat est valide et à jour
|
||||
|
||||
# Chiffrement stockage
|
||||
@encryption @database
|
||||
Scénario: Encryption at rest pour la base de données
|
||||
Étant donné que PostgreSQL stocke des données utilisateurs
|
||||
Alors le chiffrement AES-256 at rest est activé
|
||||
Et les backups sont également chiffrés AES-256
|
||||
Et les backups sont stockés offsite (règle 3-2-1)
|
||||
|
||||
# Tokens JWT sécurisés
|
||||
@encryption @jwt
|
||||
Scénario: Rotation des clés JWT tous les 90 jours
|
||||
Étant donné que l'API utilise des tokens JWT RS256
|
||||
Quand 90 jours se sont écoulés depuis la dernière rotation
|
||||
Alors une nouvelle paire de clés RSA est générée
|
||||
Et l'ancienne clé reste valide 7 jours (overlap)
|
||||
Et tous les tokens sont progressivement re-signés
|
||||
|
||||
# CDN avec signed URLs
|
||||
@cdn @signed-urls
|
||||
Scénario: URLs signées expirables pour les fichiers audio
|
||||
Quand un utilisateur demande à écouter un contenu
|
||||
Alors l'API génère une signed URL valide 1 heure
|
||||
Et l'URL contient un token HMAC
|
||||
Et après expiration, l'URL retourne 403 Forbidden
|
||||
|
||||
# Détection breach
|
||||
@breach @monitoring
|
||||
Scénario: Alerte immédiate si erreurs critiques backend
|
||||
Quand une erreur critique survient dans l'API (500, crash)
|
||||
Alors Sentry déclenche une alerte Discord/Slack immédiate
|
||||
Et l'équipe est notifiée en temps réel
|
||||
Et les logs sont consultables dans Grafana
|
||||
|
||||
@breach @monitoring
|
||||
Scénario: Alerte si pic de requêtes anormal (potentiel DDoS)
|
||||
Étant donné que le trafic habituel est ~1000 req/min
|
||||
Quand le trafic atteint 10000 req/min
|
||||
Alors Grafana déclenche une alerte email
|
||||
Et l'équipe vérifie s'il s'agit d'une attaque
|
||||
|
||||
@breach @monitoring
|
||||
Scénario: Alerte si accès DB non autorisé
|
||||
Quand une connexion PostgreSQL provient d'une IP non whitelistée
|
||||
Alors PostgreSQL bloque la connexion
|
||||
Et un SMS est envoyé au fondateur
|
||||
Et l'IP est loggée pour investigation
|
||||
|
||||
# Procédure breach 72h CNIL
|
||||
@breach @procedure
|
||||
Scénario: Notification CNIL si violation de données sous 72h
|
||||
Étant donné qu'une violation de données est détectée
|
||||
Et que des données GPS utilisateurs ont fuité
|
||||
Quand l'équipe évalue la gravité
|
||||
Alors le runbook "docs/rgpd/procedure-breach.md" est suivi:
|
||||
| Étape | Délai | Action |
|
||||
| 1 | H+0 | Détection et confinement |
|
||||
| 2 | H+24 | Évaluation gravité et impact |
|
||||
| 3 | H+48 | Notification CNIL si risque |
|
||||
| 4 | H+72 | Notification utilisateurs si élevé|
|
||||
Et un email pré-rédigé est envoyé à la CNIL
|
||||
Et le formulaire en ligne CNIL est rempli
|
||||
|
||||
# Mesures organisationnelles
|
||||
@security @access-control
|
||||
Scénario: Accès DB uniquement via VPN et whitelist IP
|
||||
Étant donné que je suis un développeur
|
||||
Quand je tente d'accéder à la DB de production
|
||||
Alors je dois être connecté au VPN OVH
|
||||
Et mon IP doit être dans la whitelist
|
||||
Sinon la connexion est refusée
|
||||
|
||||
@security @2fa
|
||||
Scénario: 2FA obligatoire pour les comptes administrateurs
|
||||
Étant donné que je suis un administrateur
|
||||
Quand je me connecte à Zitadel admin
|
||||
Alors le 2FA (TOTP) est obligatoire
|
||||
Et je ne peux pas désactiver le 2FA
|
||||
Et chaque connexion est loggée avec IP et timestamp
|
||||
|
||||
@security @logs
|
||||
Scénario: Anonymisation des IP dans les logs (rotation 90j)
|
||||
Quand un utilisateur fait une requête API
|
||||
Alors son IP est loggée pour debug
|
||||
Mais les 2 derniers octets sont masqués (ex: 192.168.x.x)
|
||||
Et les logs sont automatiquement supprimés après 90 jours
|
||||
|
||||
# Tests de sécurité
|
||||
@security @pentest
|
||||
Scénario: Pentest annuel obligatoire
|
||||
Étant donné que l'application est en production
|
||||
Quand une année s'est écoulée depuis le dernier pentest
|
||||
Alors un pentest externe est planifié
|
||||
Et les vulnérabilités découvertes sont corrigées sous 30 jours
|
||||
Et un rapport est produit pour audit
|
||||
@@ -0,0 +1,112 @@
|
||||
# language: fr
|
||||
|
||||
@privacy @rgpd @minors @parental-consent
|
||||
Fonctionnalité: Protection des mineurs et consentement parental (Article 8 RGPD)
|
||||
En tant que plateforme responsable
|
||||
Je veux protéger les mineurs avec consentement parental
|
||||
Afin de respecter l'Article 8 RGPD (13-15 ans)
|
||||
|
||||
Contexte:
|
||||
Étant donné que je suis sur la page d'inscription
|
||||
|
||||
Scénario: Blocage inscription si moins de 13 ans
|
||||
Quand je saisis ma date de naissance "15/03/2014"
|
||||
Et que je valide le formulaire
|
||||
Alors je vois le message "RoadWave est réservé aux personnes de 13 ans et plus"
|
||||
Et je vois un lien vers "RoadWave Kids"
|
||||
Et mon inscription est bloquée
|
||||
|
||||
Scénario: Inscription directe si 16 ans ou plus
|
||||
Quand je saisis ma date de naissance "10/01/2008"
|
||||
Et que je valide le formulaire
|
||||
Alors mon compte est créé immédiatement
|
||||
Et aucun consentement parental n'est requis
|
||||
Et j'ai accès à toutes les fonctionnalités
|
||||
|
||||
Plan du Scénario: Workflow consentement parental pour 13-15 ans
|
||||
Quand je saisis ma date de naissance "<date_naissance>"
|
||||
Et que je saisis l'email de mon parent "parent@example.com"
|
||||
Et que je valide le formulaire
|
||||
Alors un email est envoyé à "parent@example.com"
|
||||
Et le lien de validation expire dans 7 jours
|
||||
Et mon compte est créé mais inactif
|
||||
Et je vois "En attente validation parentale"
|
||||
|
||||
Exemples:
|
||||
| date_naissance | âge |
|
||||
| 15/03/2011 | 13 |
|
||||
| 20/06/2010 | 14 |
|
||||
| 01/12/2009 | 15 |
|
||||
|
||||
Scénario: Validation du consentement parental
|
||||
Étant donné que je suis un mineur de 14 ans avec compte inactif
|
||||
Et que mon parent a reçu l'email de validation
|
||||
Quand mon parent clique sur le lien de validation
|
||||
Alors il voit une page avec:
|
||||
| Section |
|
||||
| Résumé données collectées |
|
||||
| Paramètres contrôle parental|
|
||||
| Checkbox consentement |
|
||||
Et quand il coche "J'autorise mon enfant" et valide
|
||||
Alors mon compte est activé
|
||||
Et je reçois un email "Compte activé par ton parent"
|
||||
Et les restrictions 13-15 ans sont appliquées
|
||||
|
||||
Scénario: Restrictions pour comptes 13-15 ans
|
||||
Étant donné que je suis un utilisateur de 14 ans avec compte validé
|
||||
Alors je peux écouter des contenus autorisés
|
||||
Mais je NE peux PAS:
|
||||
| Restriction |
|
||||
| Activer le GPS précis sans accord parent |
|
||||
| Utiliser la messagerie privée |
|
||||
| Voir les contenus marqués +16 |
|
||||
| Afficher ma ville précise sur le profil |
|
||||
|
||||
Scénario: Dashboard parent - Visualisation activité enfant
|
||||
Étant donné que je suis un parent avec enfant de 14 ans
|
||||
Quand je me connecte à "roadwave.fr/parent/[child_id]"
|
||||
Alors je vois:
|
||||
| Information |
|
||||
| Historique d'écoute |
|
||||
| Temps d'écoute hebdomadaire |
|
||||
| Dernière connexion |
|
||||
Et je peux:
|
||||
| Action |
|
||||
| Activer/désactiver GPS précis |
|
||||
| Activer/désactiver messagerie |
|
||||
| Révoquer le consentement |
|
||||
|
||||
Scénario: Révocation du consentement parental
|
||||
Étant donné que je suis un parent
|
||||
Et que mon enfant de 14 ans a un compte actif
|
||||
Quand je clique sur "Révoquer le consentement"
|
||||
Alors le compte de mon enfant est immédiatement désactivé
|
||||
Et il ne peut plus se connecter
|
||||
Et je reçois un email de confirmation
|
||||
|
||||
@roadwave-kids
|
||||
Scénario: RoadWave Kids - Inscription via compte parent
|
||||
Étant donné que je suis un parent avec compte RoadWave actif
|
||||
Quand je vais dans "Mon compte > Ajouter un profil enfant"
|
||||
Et que je saisis:
|
||||
| Champ | Valeur |
|
||||
| Pseudo enfant | "Emma" |
|
||||
| Date naissance | "12/08/2016" |
|
||||
Alors un profil Kids est créé
|
||||
Et je reçois un QR code pour l'app RoadWave Kids
|
||||
Et l'enfant ne peut écouter que les contenus whitelist
|
||||
|
||||
@roadwave-kids
|
||||
Scénario: RoadWave Kids - Restrictions strictes
|
||||
Étant donné que je suis connecté sur l'app RoadWave Kids
|
||||
Alors je peux uniquement:
|
||||
| Fonctionnalité |
|
||||
| Écouter contenus présélectionnés |
|
||||
| Voir ma position ville (GeoIP) |
|
||||
Mais je NE peux PAS:
|
||||
| Restriction |
|
||||
| Activer le GPS précis |
|
||||
| Créer du contenu |
|
||||
| Avoir un profil public |
|
||||
| Utiliser la messagerie |
|
||||
| Voir du contenu UGC |
|
||||
@@ -0,0 +1,99 @@
|
||||
# language: fr
|
||||
|
||||
@privacy @rgpd @transparency
|
||||
Fonctionnalité: Politique de confidentialité et transparence (Articles 13-14 RGPD)
|
||||
En tant qu'utilisateur
|
||||
Je veux comprendre comment mes données sont utilisées
|
||||
Afin de donner un consentement éclairé
|
||||
|
||||
Contexte:
|
||||
Étant donné que l'application RoadWave est disponible
|
||||
|
||||
# Popup première connexion
|
||||
@first-launch
|
||||
Scénario: Affichage de la politique de confidentialité à l'inscription
|
||||
Quand je m'inscris pour la première fois
|
||||
Alors une popup s'affiche avec la politique de confidentialité
|
||||
Et je dois scroller jusqu'en bas pour activer le bouton "J'accepte"
|
||||
Et je dois cocher "J'ai lu et j'accepte la politique de confidentialité"
|
||||
Et je ne peux pas créer de compte sans accepter
|
||||
|
||||
# Contenu obligatoire
|
||||
@content
|
||||
Scénario: Vérification du contenu de la politique de confidentialité
|
||||
Quand je consulte la page "roadwave.fr/confidentialite"
|
||||
Alors je vois les informations suivantes:
|
||||
| Section |
|
||||
| Identité responsable traitement + DPO |
|
||||
| Finalités détaillées par traitement |
|
||||
| Base légale (consentement/contrat/intérêt)|
|
||||
| Destinataires données (CDN, Matomo, etc.) |
|
||||
| Durées de conservation |
|
||||
| Droits utilisateurs (accès, rectif, etc.) |
|
||||
| Droit réclamation CNIL |
|
||||
| Transferts hors UE (aucun) |
|
||||
|
||||
# Versioning
|
||||
@versioning
|
||||
Scénario: Versioning de la politique avec Git et DB
|
||||
Étant donné que la politique de confidentialité est modifiée
|
||||
Quand l'équipe commit les changements
|
||||
Alors le fichier "docs/legal/politique-confidentialite.md" est versionné Git
|
||||
Et une entrée est créée dans "privacy_policy_versions"
|
||||
Avec les champs:
|
||||
| Champ | Valeur |
|
||||
| version | "2.0" |
|
||||
| effective_date| "2026-03-01" |
|
||||
| major_change | true |
|
||||
| changelog | "Ajout tracking..." |
|
||||
|
||||
@versioning
|
||||
Scénario: Notification utilisateurs si changement majeur
|
||||
Étant donné qu'une nouvelle version majeure de la politique est publiée
|
||||
Quand un utilisateur se connecte
|
||||
Alors une popup s'affiche "Politique de confidentialité mise à jour"
|
||||
Et il doit l'accepter à nouveau pour continuer
|
||||
Et s'il refuse, son compte est gelé (accès lecture seule)
|
||||
|
||||
# Transparence algorithme
|
||||
@algorithm-transparency
|
||||
Scénario: Explication simplifiée de l'algorithme de recommandation
|
||||
Quand je vais sur "roadwave.fr/comment-ca-marche"
|
||||
Alors je vois une page "Comment fonctionne la recommandation ?"
|
||||
Avec les explications suivantes:
|
||||
| Critère | Explication |
|
||||
| Distance géographique | Contenus près de vous en priorité |
|
||||
| Centres d'intérêt | Jauges automatiques selon écoutes |
|
||||
| Popularité | Contenus les plus écoutés |
|
||||
Et je peux désactiver la personnalisation (mode anonyme)
|
||||
|
||||
# Contact DPO
|
||||
@dpo-contact
|
||||
Scénario: Accès facile au contact DPO
|
||||
Quand je vais dans "Paramètres > Confidentialité et données"
|
||||
Alors je vois un bouton "Contacter le DPO"
|
||||
Et le lien email "dpo@roadwave.fr" est cliquable
|
||||
Et je vois "Délai de réponse : 1 mois maximum"
|
||||
|
||||
# Profilage et décisions automatisées
|
||||
@profiling
|
||||
Scénario: Information sur le profilage et opposition possible
|
||||
Quand je consulte la politique de confidentialité
|
||||
Alors je vois une section "Profilage et décisions automatisées"
|
||||
Qui explique:
|
||||
| Type décision | Impact | Opposition possible |
|
||||
| Recommandations | Faible | Oui (mode anonyme) |
|
||||
| Modération automatique| Élevé | Oui (contestation) |
|
||||
Et je peux activer le mode anonyme à tout moment
|
||||
|
||||
# Sous-traitants
|
||||
@subprocessors
|
||||
Scénario: Liste transparente des sous-traitants
|
||||
Quand je consulte "roadwave.fr/confidentialite#sous-traitants"
|
||||
Alors je vois la liste complète:
|
||||
| Service | Finalité | Localisation | DPA |
|
||||
| OVH | Hébergement | France | ✅ |
|
||||
| Bunny.net | CDN audio | UE | ✅ |
|
||||
| Brevo | Emails | France | ✅ |
|
||||
| Mangopay | Paiements | Luxembourg | ✅ |
|
||||
Et je vois "Aucun transfert hors UE"
|
||||
@@ -0,0 +1,77 @@
|
||||
# language: fr
|
||||
|
||||
@privacy @rgpd @user-rights
|
||||
Fonctionnalité: Exercice des droits utilisateurs RGPD
|
||||
En tant qu'utilisateur
|
||||
Je veux exercer mes droits RGPD facilement
|
||||
Afin de contrôler mes données personnelles
|
||||
|
||||
Contexte:
|
||||
Étant donné que je suis connecté à mon compte
|
||||
|
||||
# Article 16 - Droit de rectification
|
||||
@rectification
|
||||
Scénario: Modification du pseudo (limite 1/30j)
|
||||
Quand je vais dans "Paramètres > Mon profil"
|
||||
Et que je modifie mon pseudo de "Alice123" à "AliceM"
|
||||
Alors le changement est immédiat
|
||||
Et je ne peux plus modifier mon pseudo pendant 30 jours
|
||||
Et l'historique est enregistré dans "user_profile_history"
|
||||
|
||||
@rectification
|
||||
Scénario: Modification de l'email avec re-vérification
|
||||
Quand je modifie mon email de "old@example.com" à "new@example.com"
|
||||
Alors je reçois un email de vérification sur "new@example.com"
|
||||
Et je dois cliquer sur le lien dans les 24h
|
||||
Et mon ancien email reste actif jusqu'à validation
|
||||
|
||||
# Article 21 - Droit d'opposition
|
||||
@opposition
|
||||
Scénario: Opposition au marketing par email
|
||||
Quand je vais dans "Paramètres > Notifications"
|
||||
Et que je décoche "Recevoir les emails marketing"
|
||||
Alors je ne reçois plus d'emails promotionnels
|
||||
Mais je reçois toujours les emails transactionnels
|
||||
|
||||
@opposition @anonymous-mode
|
||||
Scénario: Activation du mode anonyme (recommandations génériques)
|
||||
Quand je vais dans "Paramètres > Confidentialité"
|
||||
Et que j'active "Mode anonyme"
|
||||
Alors mes jauges d'intérêt sont ignorées
|
||||
Et je reçois uniquement les top contenus de ma zone géographique
|
||||
Et mon historique d'écoute n'est pas utilisé pour les recommandations
|
||||
Et je vois un badge "Mode anonyme actif"
|
||||
|
||||
# Article 18 - Droit à la limitation du traitement
|
||||
@limitation
|
||||
Scénario: Gel temporaire du compte
|
||||
Quand je vais dans "Paramètres > Gestion du compte"
|
||||
Et que je clique sur "Mettre en pause mon compte"
|
||||
Alors mon compte est gelé immédiatement
|
||||
Et mes contenus sont cachés (non diffusés)
|
||||
Et mon profil est invisible
|
||||
Mais je peux toujours me connecter en lecture seule
|
||||
Et je peux réactiver à tout moment
|
||||
|
||||
@limitation
|
||||
Scénario: Réactivation compte gelé
|
||||
Étant donné que mon compte est gelé depuis 15 jours
|
||||
Quand je me connecte
|
||||
Et que je clique sur "Réactiver mon compte"
|
||||
Alors mon compte redevient actif immédiatement
|
||||
Et mes contenus sont à nouveau visibles
|
||||
|
||||
# Article 12 - Délai de réponse 1 mois max
|
||||
@response-time
|
||||
Scénario: Demande d'accès aux données (délai 48h)
|
||||
Quand je demande un export de mes données
|
||||
Alors je reçois un email sous 48h maximum
|
||||
Avec un lien de téléchargement valide 7 jours
|
||||
|
||||
@response-time
|
||||
Scénario: Contestation d'une décision automatisée (délai 24h)
|
||||
Étant donné que mon contenu a été bloqué par la modération automatique
|
||||
Quand je clique sur "Contester cette décision"
|
||||
Alors un humain examine mon cas sous 24h
|
||||
Et je reçois une réponse motivée
|
||||
Et mon contenu est rétabli si la décision était erronée
|
||||
@@ -34,15 +34,7 @@
|
||||
1. Données précises conservées **24h** (recommandation personnalisée)
|
||||
2. Après 24h : conversion en geohash précision 5 (~5km²)
|
||||
3. Coordonnées originales supprimées définitivement
|
||||
|
||||
**Implémentation PostGIS** :
|
||||
```sql
|
||||
-- Job quotidien
|
||||
UPDATE location_history
|
||||
SET location = ST_SetSRID(ST_GeomFromGeoHash(ST_GeoHash(location::geography, 5)), 4326)::geography,
|
||||
anonymized = true
|
||||
WHERE created_at < NOW() - INTERVAL '24 hours' AND anonymized = false;
|
||||
```
|
||||
4. Job quotidien automatique via cron
|
||||
|
||||
**Exceptions** :
|
||||
- ✅ Historique personnel visible (liste trajets) : conservation intégrale tant que compte actif
|
||||
@@ -59,17 +51,7 @@ WHERE created_at < NOW() - INTERVAL '24 hours' AND anonymized = false;
|
||||
|
||||
**Décision** : JSON + HTML + ZIP, génération asynchrone
|
||||
|
||||
**Contenu de l'export** :
|
||||
```
|
||||
export-roadwave-[user_id]-[date].zip
|
||||
├── export.json # Machine-readable
|
||||
├── index.html # Human-readable (stylé)
|
||||
├── audio/
|
||||
│ ├── content-123.opus
|
||||
│ ├── content-456.opus
|
||||
│ └── ...
|
||||
└── README.txt # Instructions
|
||||
```
|
||||
**Format export** : Archive ZIP contenant JSON (machine-readable), HTML (human-readable), fichiers audio, README
|
||||
|
||||
**Données exportées** :
|
||||
- Profil utilisateur (email, pseudo, date inscription, bio)
|
||||
@@ -306,31 +288,283 @@ export-roadwave-[user_id]-[date].zip
|
||||
|
||||
---
|
||||
|
||||
## Récapitulatif Section 13
|
||||
### 13.11 Droit de rectification
|
||||
|
||||
| Mesure | Implémentation | Coût |
|
||||
|--------|----------------|------|
|
||||
| **Consentement** | Tarteaucitron.js + PostgreSQL | 0€ |
|
||||
| **Anonymisation GPS** | Geohash PostGIS (24h) | 0€ |
|
||||
| **Export données** | JSON+HTML+ZIP asynchrone | 0€ |
|
||||
| **Suppression compte** | Grace period 30j + anonymisation | 0€ |
|
||||
| **Mode dégradé** | GeoIP IP2Location + GPS optionnel | 0€ |
|
||||
| **Conservation** | Purge auto 5 ans inactivité | 0€ |
|
||||
| **Analytics** | Matomo self-hosted | ~5€/mois |
|
||||
| **Registre traitements** | Markdown Git | 0€ |
|
||||
| **Breach detection** | Sentry + Grafana + runbook | 0€ |
|
||||
| **DPO** | Fondateur formé CNIL | 0€ |
|
||||
**Décision** : Interface self-service + validation immédiate
|
||||
|
||||
**Coût total RGPD : ~5€/mois**
|
||||
**Données rectifiables** :
|
||||
- Email (avec re-vérification)
|
||||
- Pseudo (unique, disponibilité vérifiée)
|
||||
- Bio / description
|
||||
- Centres d'intérêt (jauges)
|
||||
- Photo de profil
|
||||
|
||||
**Processus** :
|
||||
- Changements immédiats (sauf email)
|
||||
- Email : lien vérification → validation sous 24h
|
||||
- Historique modifications conservé (audit trail)
|
||||
|
||||
**Limitations** :
|
||||
- Pseudo : max 1 changement/30j (anti-squat)
|
||||
|
||||
**Justification** : Conformité Article 16 RGPD, self-service 0€
|
||||
|
||||
---
|
||||
|
||||
## Points d'attention pour Gherkin
|
||||
### 13.12 Droit d'opposition
|
||||
|
||||
- Tester consentement géolocalisation (accept/refuse → contenus différents)
|
||||
- Tester anonymisation GPS après 24h (job cron)
|
||||
- Tester export données (génération complète + vérification contenu)
|
||||
- Tester grace period suppression (annulation possible)
|
||||
- Tester mode GeoIP (ville détectée correctement)
|
||||
- Tester purge automatique (5 ans inactivité)
|
||||
- Tester notifications avant purge (90j/30j/7j)
|
||||
**Décision** : Opt-out granulaire, effet immédiat
|
||||
|
||||
| Traitement | Toggle | Effet |
|
||||
|------------|--------|-------|
|
||||
| **Marketing email** | Paramètres | Stop emails promo |
|
||||
| **Notifications push** | Paramètres | Stop push marketing |
|
||||
| **Analytics** | Banner RGPD | Exclusion Matomo |
|
||||
| **Recommandations personnalisées** | "Mode anonyme" | Reco génériques uniquement |
|
||||
|
||||
**Mode anonyme** :
|
||||
- Désactive algorithme (jauges ignorées)
|
||||
- Recommandations = top contenus zone géo uniquement
|
||||
- Historique non utilisé
|
||||
|
||||
**Justification** : Conformité Article 21 RGPD
|
||||
|
||||
---
|
||||
|
||||
### 13.13 Droit à la limitation du traitement
|
||||
|
||||
**Décision** : "Geler mon compte" temporaire
|
||||
|
||||
**Effets** :
|
||||
- Compte gelé, contenus cachés, profil invisible
|
||||
- Connexion lecture seule OK
|
||||
- Réactivation à tout moment
|
||||
|
||||
**Justification** : Conformité Article 18 RGPD
|
||||
|
||||
---
|
||||
|
||||
### 13.14 Politique de confidentialité
|
||||
|
||||
**Décision** : Page web + popup in-app + versioning Git
|
||||
|
||||
**Emplacement** :
|
||||
- Web : `roadwave.fr/confidentialite`
|
||||
- App : page dédiée paramètres
|
||||
- Popup première connexion (scroll requis)
|
||||
|
||||
**Contenu** : Identité responsable, finalités, base légale, destinataires, durées, droits, transferts UE
|
||||
|
||||
**Versioning** : Git + DB `privacy_policy_versions`, popup si changement majeur
|
||||
|
||||
**Justification** : Conformité Articles 13-14 RGPD
|
||||
|
||||
---
|
||||
|
||||
### 13.15 Minimisation des données
|
||||
|
||||
**Décision** : Collecte strictement nécessaire
|
||||
|
||||
| Donnée | Finalité | Optionnel |
|
||||
|--------|----------|-----------|
|
||||
| Email | Authentification | ❌ |
|
||||
| Pseudo | Identité publique | ❌ |
|
||||
| GPS précis | Reco hyperlocales | ✅ (GeoIP fallback) |
|
||||
| Jauges intérêt | Reco thématiques | ✅ |
|
||||
| Date naissance | Vérifier âge minimum | ❌ (année seule) |
|
||||
|
||||
**Non collecté** : nom/prénom réels, adresse postale (sauf créateurs payés), téléphone (sauf 2FA optionnel)
|
||||
|
||||
**Justification** : Conformité Article 5.1.c RGPD
|
||||
|
||||
---
|
||||
|
||||
### 13.16 Sécurité des données
|
||||
|
||||
**Décision** : Chiffrement multi-niveaux
|
||||
|
||||
| Couche | Implémentation |
|
||||
|--------|----------------|
|
||||
| Transport | TLS 1.3 ([ADR-006](../../../adr/006-chiffrement.md)) |
|
||||
| DB | PostgreSQL encryption at rest AES-256 |
|
||||
| Tokens | JWT RS256 + rotation 90j |
|
||||
| CDN | Signed URLs expirables |
|
||||
| Backups | AES-256 + offsite |
|
||||
|
||||
**Mesures orga** : Whitelist IP, Vault secrets, logs anonymisés, 2FA admins, pentest annuel
|
||||
|
||||
**Justification** : Conformité Article 32 RGPD
|
||||
|
||||
---
|
||||
|
||||
### 13.17 Transferts hors UE
|
||||
|
||||
**Décision** : Hébergement 100% France/UE
|
||||
|
||||
| Service | Localisation | Transfert UE |
|
||||
|---------|--------------|--------------|
|
||||
| Hébergement | OVH France | ❌ |
|
||||
| Database | OVH France | ❌ |
|
||||
| CDN | Bunny.net EU | ❌ |
|
||||
| Matomo | Self-hosted France | ❌ |
|
||||
|
||||
**Si CDN global futur** : Clauses Contractuelles Types (CCE) 2021
|
||||
|
||||
**Justification** : Conformité Articles 44-50 RGPD, souveraineté données
|
||||
|
||||
---
|
||||
|
||||
### 13.18 Profilage et décisions automatisées
|
||||
|
||||
**Décision** : Transparence + droit opposition
|
||||
|
||||
| Traitement | Impact | Intervention humaine | Opposition |
|
||||
|------------|--------|---------------------|------------|
|
||||
| Recommandations | Faible | ❌ | ✅ (mode anonyme) |
|
||||
| Modération auto | Élevé | ✅ (review 24h) | ✅ (appeal) |
|
||||
|
||||
**Transparence** : Page "Comment fonctionne l'algo ?", explications simplifiées
|
||||
|
||||
**Justification** : Conformité Article 22 RGPD
|
||||
|
||||
---
|
||||
|
||||
### 13.19 Gestion des mineurs
|
||||
|
||||
**Décision** : 13 ans minimum + consentement parental 13-15 ans + RoadWave Kids
|
||||
|
||||
#### App principale (RoadWave)
|
||||
|
||||
**Âge minimum** : **13 ans** (alignement YouTube/TikTok)
|
||||
|
||||
**Processus inscription** :
|
||||
1. Saisie date naissance (JJ/MM/AAAA)
|
||||
2. **Si < 13 ans** : blocage + message redirection RoadWave Kids
|
||||
3. **Si 13-15 ans** : workflow consentement parental
|
||||
4. **Si ≥ 16 ans** : inscription directe
|
||||
|
||||
**Workflow consentement parental (13-15 ans)** :
|
||||
1. Ado saisit email parent
|
||||
2. Email automatique parent avec lien validation (expire 7j)
|
||||
3. Parent clique lien → page dédiée avec résumé données collectées, paramètres contrôle parental, checkbox consentement
|
||||
4. Validation parent → compte ado activé avec restrictions
|
||||
|
||||
**Restrictions 13-15 ans** :
|
||||
- ✅ Écoute contenus autorisés
|
||||
- ✅ Création contenus (modération renforcée)
|
||||
- ⚠️ GPS précis : consentement parental explicite requis
|
||||
- ⚠️ Messagerie privée : désactivée par défaut
|
||||
- ⚠️ Contenus sensibles : filtrés (pas de contenu +16)
|
||||
- ⚠️ Profil public limité (pas d'affichage ville précise)
|
||||
|
||||
**Contrôles parentaux** :
|
||||
- Dashboard parent : `roadwave.fr/parent/[child_id]`
|
||||
- Visualisation historique écoute
|
||||
- Activation/désactivation GPS précis
|
||||
- Activation/désactivation messagerie
|
||||
- Révocation consentement à tout moment
|
||||
- Notification hebdomadaire activité
|
||||
|
||||
**Vérification légère identité parent** :
|
||||
- Email parent ≠ email ado (vérification domaine)
|
||||
- Lien expiration 7 jours
|
||||
- Pas de vérification identité forte (MVP)
|
||||
|
||||
#### RoadWave Kids (< 13 ans)
|
||||
|
||||
**App dédiée** : Version séparée avec contrôles renforcés
|
||||
|
||||
**Caractéristiques** :
|
||||
- ❌ Pas de GPS précis (GeoIP ville uniquement)
|
||||
- ❌ Pas de création contenu
|
||||
- ❌ Pas de profil public
|
||||
- ❌ Pas de messagerie
|
||||
- ✅ Contenus présélectionnés (whitelist éditoriale)
|
||||
- ✅ Mode lecture seule
|
||||
- ✅ Contrôle parental obligatoire
|
||||
|
||||
**Contenus autorisés** :
|
||||
- Contes audio enfants
|
||||
- Guides touristiques famille
|
||||
- Podcasts éducatifs labellisés
|
||||
- Histoires locales patrimoine
|
||||
|
||||
**Workflow inscription** :
|
||||
1. Création compte parent (RoadWave standard)
|
||||
2. Ajout profil enfant dans dashboard parent
|
||||
3. App Kids : login via QR code parent
|
||||
4. Pas de compte autonome enfant
|
||||
|
||||
**Modération** :
|
||||
- 100% contenus présélectionnés par équipe éditoriale
|
||||
- Aucun UGC accessible
|
||||
- Whitelist créateurs vérifiés uniquement
|
||||
|
||||
**Justification** :
|
||||
- Conformité Article 8 RGPD (13-16 ans selon pays)
|
||||
- 13 ans France = seuil légal avec consentement parental
|
||||
- App Kids = protection renforcée < 13 ans
|
||||
- Alignement marché (YouTube 13+, YouTube Kids)
|
||||
|
||||
**Roadmap** :
|
||||
- **MVP** : App principale 16+ uniquement (simplicité)
|
||||
- **Phase 2** : Workflow 13-15 ans + consentement parental
|
||||
- **Phase 3** : RoadWave Kids (app séparée)
|
||||
|
||||
---
|
||||
|
||||
### 13.20 Sous-traitants et DPA
|
||||
|
||||
**Décision** : DPA systématique, audit annuel
|
||||
|
||||
| Service | Traitement | Localisation | DPA | Certifications |
|
||||
|---------|------------|--------------|-----|----------------|
|
||||
| OVH | Hébergement | France | ✅ | ISO 27001, HDS |
|
||||
| Bunny.net | CDN | UE | ✅ | ISO 27001 |
|
||||
| Brevo | Emailing | France | ✅ | RGPD certified |
|
||||
| Mangopay | Paiements | Luxembourg | ✅ | PCI-DSS, ACPR |
|
||||
|
||||
**Obligations DPA** : Traitement selon instructions, confidentialité, sécurité, assistance droits, suppression fin contrat
|
||||
|
||||
**Gestion** : `docs/rgpd/sous-traitants.md`, review annuelle
|
||||
|
||||
**Justification** : Conformité Article 28 RGPD
|
||||
|
||||
---
|
||||
|
||||
### 13.21 Analyse d'impact (DPIA)
|
||||
|
||||
**Décision** : DPIA obligatoire (GPS + profilage grande échelle)
|
||||
|
||||
**Raisons** :
|
||||
- Traitement grande échelle données GPS sensibles
|
||||
- Profilage automatisé recommandations
|
||||
- Surveillance zones publiques
|
||||
|
||||
**Contenu** : Description traitement, finalités, nécessité, risques (tracking, profilage, fuite), mesures atténuation (anonymisation 24h, consentement, chiffrement, mode dégradé)
|
||||
|
||||
**Fichier** : `docs/rgpd/dpia-geolocalisation.md`, review annuelle
|
||||
|
||||
**Justification** : Conformité Article 35 RGPD (critères CNIL remplis)
|
||||
|
||||
---
|
||||
|
||||
### 13.22 Délai de réponse aux demandes
|
||||
|
||||
**Décision** : 1 mois max, automatisation maximale
|
||||
|
||||
**Canaux** : Email dpo@roadwave.fr, formulaire in-app, courrier postal
|
||||
|
||||
| Droit | Délai cible | Automatisation |
|
||||
|-------|-------------|----------------|
|
||||
| Accès (export) | 48h | ✅ Worker |
|
||||
| Rectification | Immédiat | ✅ Self-service |
|
||||
| Suppression | Immédiat | ✅ Self-service |
|
||||
| Opposition | Immédiat | ✅ Toggles |
|
||||
| Limitation | Immédiat | ✅ Gel compte |
|
||||
| Portabilité | 48h | ✅ Export |
|
||||
| Contestation décision | 24h | ⚠️ Manuel |
|
||||
|
||||
**Vérification identité** : Si email vérifié = aucune vérif supplémentaire
|
||||
|
||||
**Justification** : Conformité Article 12 RGPD
|
||||
|
||||
55
docs/domains/_shared/sequences/anonymisation-gps.md
Normal file
55
docs/domains/_shared/sequences/anonymisation-gps.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# Anonymisation automatique GPS après 24h
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User as Utilisateur
|
||||
participant App as Application
|
||||
participant DB as Base de données (PostGIS)
|
||||
participant Cron as Job Cron Quotidien
|
||||
|
||||
Note over User,App: Écoute de contenu avec GPS
|
||||
|
||||
User->>App: Écoute contenu (GPS activé)
|
||||
App->>App: Capturer position GPS précise
|
||||
App->>DB: INSERT position (lat, lon, anonymized: false)
|
||||
Note over DB: Position précise stockée<br/>Utilisée pour recommandations
|
||||
|
||||
Note over DB,Cron: Moins de 24h : position précise conservée
|
||||
|
||||
App->>DB: SELECT positions pour recommandations
|
||||
DB->>App: Positions GPS précises (< 24h)
|
||||
App->>User: Recommandations hyperlocales
|
||||
|
||||
Note over Cron: 24h+ plus tard
|
||||
|
||||
Cron->>DB: SELECT positions WHERE created_at < NOW() - 24h AND anonymized = false
|
||||
DB->>Cron: Liste positions à anonymiser
|
||||
|
||||
loop Pour chaque position
|
||||
Cron->>DB: Convertir (lat, lon) → geohash précision 5 (~5km²)
|
||||
Cron->>DB: UPDATE position avec geohash
|
||||
Cron->>DB: Supprimer coordonnées précises
|
||||
Cron->>DB: SET anonymized = true
|
||||
end
|
||||
|
||||
Cron->>DB: Log anonymisation (nombre positions traitées)
|
||||
|
||||
Note over DB: Positions anonymisées utilisées pour analytics
|
||||
|
||||
App->>DB: SELECT positions anonymisées (analytics globales)
|
||||
DB->>App: Positions geohash uniquement
|
||||
App->>App: Générer heatmap trafic (~5km² précision)
|
||||
|
||||
Note over User: Exception : historique personnel
|
||||
|
||||
User->>App: Consulter "Mon historique d'écoute"
|
||||
App->>DB: SELECT historique personnel utilisateur
|
||||
DB->>App: Positions précises conservées (tant que compte actif)
|
||||
App->>User: Trajets détaillés
|
||||
```
|
||||
|
||||
**Légende** :
|
||||
- **< 24h** : GPS précis conservé (recommandations hyperlocales)
|
||||
- **> 24h** : Conversion automatique en geohash précision 5 (~5km²)
|
||||
- **Exception** : Historique personnel conservé intact tant que compte actif
|
||||
- **Analytics** : Uniquement positions anonymisées (geohash)
|
||||
43
docs/domains/_shared/sequences/consentement-parental.md
Normal file
43
docs/domains/_shared/sequences/consentement-parental.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Consentement parental (13-15 ans)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Ado as Adolescent (13-15 ans)
|
||||
participant App as Application
|
||||
participant DB as Base de données
|
||||
participant Email as Service Email
|
||||
participant Parent as Parent
|
||||
|
||||
Ado->>App: Inscription (date naissance 13-15 ans)
|
||||
App->>Ado: Demande email parent
|
||||
Ado->>App: Saisit email parent
|
||||
|
||||
App->>DB: Créer compte (statut: pending_parental_consent)
|
||||
App->>Email: Envoyer email validation parent
|
||||
Email->>Parent: Email avec lien (expire 7j)
|
||||
App->>Ado: "En attente validation parentale"
|
||||
|
||||
Note over Parent: Parent clique lien validation
|
||||
|
||||
Parent->>App: Accès page consentement
|
||||
App->>Parent: Afficher résumé données + contrôles
|
||||
Parent->>App: Valider consentement + paramètres
|
||||
|
||||
App->>DB: Enregistrer consentement parental
|
||||
App->>DB: Activer compte (statut: active_minor)
|
||||
App->>DB: Appliquer restrictions 13-15 ans
|
||||
|
||||
App->>Email: Notification ado (compte activé)
|
||||
Email->>Ado: Email confirmation
|
||||
|
||||
App->>Email: Notification parent (récapitulatif)
|
||||
Email->>Parent: Email + lien dashboard parental
|
||||
|
||||
Ado->>App: Connexion
|
||||
App->>Ado: Accès restreint (GPS/messagerie selon config parent)
|
||||
```
|
||||
|
||||
**Légende** :
|
||||
- Délai expiration lien : 7 jours
|
||||
- Restrictions 13-15 ans : GPS précis, messagerie, contenus +16 (configurables par parent)
|
||||
- Dashboard parent : `roadwave.fr/parent/[child_id]`
|
||||
65
docs/domains/_shared/sequences/export-donnees.md
Normal file
65
docs/domains/_shared/sequences/export-donnees.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Export de données (portabilité)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User as Utilisateur
|
||||
participant App as Application
|
||||
participant DB as Base de données
|
||||
participant Queue as File d'attente
|
||||
participant Worker as Worker Background
|
||||
participant CDN as CDN (fichiers audio)
|
||||
participant Storage as Stockage temporaire
|
||||
participant Email as Service Email
|
||||
|
||||
User->>App: Demande export données
|
||||
|
||||
App->>DB: Vérifier dernière demande
|
||||
alt Dernière demande < 30 jours
|
||||
DB->>App: Demande refusée
|
||||
App->>User: "Prochain export disponible dans X jours"
|
||||
else Demande autorisée
|
||||
App->>DB: Créer demande export (statut: pending)
|
||||
App->>Queue: Ajouter job export
|
||||
App->>User: "Export en cours, email sous 48h"
|
||||
|
||||
Queue->>Worker: Job export disponible
|
||||
|
||||
Note over Worker: Génération asynchrone
|
||||
|
||||
Worker->>DB: Récupérer profil utilisateur
|
||||
Worker->>DB: Récupérer historique d'écoute
|
||||
Worker->>DB: Récupérer contenus créés (métadonnées)
|
||||
Worker->>DB: Récupérer centres d'intérêt
|
||||
Worker->>DB: Récupérer historique consentements
|
||||
|
||||
Worker->>CDN: Télécharger fichiers audio utilisateur
|
||||
CDN->>Worker: Fichiers audio (.opus)
|
||||
|
||||
Worker->>Worker: Générer export.json (machine-readable)
|
||||
Worker->>Worker: Générer index.html (human-readable)
|
||||
Worker->>Worker: Générer README.txt
|
||||
Worker->>Worker: Créer archive ZIP
|
||||
|
||||
Worker->>Storage: Stocker ZIP (expire 7j)
|
||||
Storage->>Worker: URL signée (expire 7j)
|
||||
|
||||
Worker->>DB: Mettre à jour demande (statut: completed)
|
||||
Worker->>DB: Enregistrer URL + date expiration
|
||||
|
||||
Worker->>Email: Envoyer email avec lien
|
||||
Email->>User: Email + lien téléchargement (valide 7j)
|
||||
|
||||
User->>Storage: Clic lien téléchargement
|
||||
Storage->>User: Téléchargement ZIP
|
||||
|
||||
Note over Storage: Après 7 jours
|
||||
|
||||
Storage->>Storage: Suppression automatique ZIP
|
||||
end
|
||||
```
|
||||
|
||||
**Légende** :
|
||||
- Limite : 1 export / 30 jours (anti-abus)
|
||||
- Délai génération : 48h maximum (conformité RGPD Article 20)
|
||||
- Expiration lien : 7 jours
|
||||
- Format : ZIP contenant JSON, HTML, audio, README
|
||||
63
docs/domains/_shared/sequences/notification-breach.md
Normal file
63
docs/domains/_shared/sequences/notification-breach.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Notification violation de données (breach) - Procédure 72h CNIL
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Monitoring as Monitoring (Sentry/Grafana)
|
||||
participant Equipe as Équipe Technique
|
||||
participant DPO as DPO
|
||||
participant DB as Base de données
|
||||
participant CNIL as CNIL
|
||||
participant Users as Utilisateurs impactés
|
||||
|
||||
Note over Monitoring: H+0 - Détection
|
||||
|
||||
Monitoring->>Equipe: Alerte breach détecté
|
||||
Equipe->>Equipe: Confinement immédiat
|
||||
Equipe->>DB: Bloquer accès compromis
|
||||
Equipe->>DPO: Notification breach
|
||||
|
||||
Note over DPO,Equipe: H+0 à H+24 - Évaluation
|
||||
|
||||
DPO->>DB: Investigation périmètre
|
||||
DB->>DPO: Données compromises
|
||||
DPO->>DB: Liste utilisateurs impactés
|
||||
DB->>DPO: X utilisateurs
|
||||
|
||||
DPO->>DPO: Évaluation gravité
|
||||
Note over DPO: - Type données (GPS, email, etc.)<br/>- Nombre utilisateurs<br/>- Risque pour droits/libertés
|
||||
|
||||
alt Risque pour utilisateurs
|
||||
Note over DPO: H+24 à H+48 - Préparation notification CNIL
|
||||
|
||||
DPO->>DPO: Rédaction rapport breach
|
||||
Note over DPO: - Nature violation<br/>- Catégories/nb données<br/>- Conséquences probables<br/>- Mesures prises/envisagées
|
||||
|
||||
DPO->>CNIL: Notification sous 72h (email + formulaire en ligne)
|
||||
CNIL->>DPO: Accusé réception
|
||||
|
||||
alt Risque élevé pour utilisateurs
|
||||
Note over DPO: H+48 à H+72 - Notification utilisateurs
|
||||
|
||||
DPO->>Users: Email notification breach
|
||||
Note over Users: - Nature violation<br/>- Coordonnées DPO<br/>- Mesures prises<br/>- Recommandations (changer mdp, etc.)
|
||||
|
||||
DPO->>Users: Notification in-app
|
||||
end
|
||||
else Risque faible (mesures techniques suffisantes)
|
||||
DPO->>DPO: Documentation interne uniquement
|
||||
Note over DPO: Pas de notification CNIL requise
|
||||
end
|
||||
|
||||
Note over DPO: Post-incident
|
||||
|
||||
DPO->>Equipe: Audit sécurité complet
|
||||
DPO->>DB: Enregistrement incident (registre violations)
|
||||
DPO->>DPO: Plan correctif
|
||||
```
|
||||
|
||||
**Légende** :
|
||||
- **H+0 à H+24** : Détection, confinement, évaluation périmètre
|
||||
- **H+24 à H+48** : Évaluation gravité, préparation rapport
|
||||
- **H+48 à H+72** : Notification CNIL (si risque) + utilisateurs (si risque élevé)
|
||||
- Délai CNIL : **72h maximum** (Article 33 RGPD)
|
||||
- Notification utilisateurs obligatoire si **risque élevé** pour droits/libertés (Article 34 RGPD)
|
||||
51
docs/domains/_shared/sequences/suppression-compte.md
Normal file
51
docs/domains/_shared/sequences/suppression-compte.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Suppression compte avec grace period
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User as Utilisateur
|
||||
participant App as Application
|
||||
participant DB as Base de données
|
||||
participant Email as Service Email
|
||||
participant Cron as Job Cron
|
||||
|
||||
User->>App: Demande suppression compte
|
||||
App->>User: Confirmation (êtes-vous sûr ?)
|
||||
User->>App: Confirmer
|
||||
|
||||
App->>DB: Désactiver compte (statut: pending_deletion)
|
||||
App->>DB: Cacher contenus (visible: false)
|
||||
App->>DB: Révoquer sessions/tokens
|
||||
App->>DB: Enregistrer date suppression effective (J+30)
|
||||
|
||||
App->>Email: Email confirmation + lien annulation
|
||||
Email->>User: Email (lien valide 30j)
|
||||
App->>User: "Compte désactivé. Suppression dans 30 jours."
|
||||
|
||||
Note over User,App: Grace period 30 jours
|
||||
|
||||
alt Utilisateur annule
|
||||
User->>App: Clic lien annulation
|
||||
App->>DB: Réactiver compte (statut: active)
|
||||
App->>DB: Restaurer visibilité contenus
|
||||
App->>Email: Email confirmation réactivation
|
||||
Email->>User: "Compte réactivé"
|
||||
else 30 jours sans annulation
|
||||
Cron->>DB: Job quotidien (vérif comptes pending_deletion)
|
||||
DB->>Cron: Liste comptes J+30 dépassé
|
||||
|
||||
loop Pour chaque compte
|
||||
Cron->>DB: Supprimer données personnelles
|
||||
Cron->>DB: Anonymiser contenus (créateur: "Utilisateur supprimé")
|
||||
Cron->>DB: Supprimer historique GPS/écoute
|
||||
Cron->>DB: Marquer statut: deleted
|
||||
end
|
||||
|
||||
Cron->>Email: Email confirmation suppression effective
|
||||
Email->>User: "Compte définitivement supprimé"
|
||||
end
|
||||
```
|
||||
|
||||
**Légende** :
|
||||
- Grace period : 30 jours
|
||||
- Pendant grace period : compte inaccessible, contenus cachés
|
||||
- Après 30j : suppression définitive, contenus anonymisés conservés
|
||||
42
docs/domains/_shared/states/account-deletion-lifecycle.md
Normal file
42
docs/domains/_shared/states/account-deletion-lifecycle.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Cycle de vie - Suppression de compte
|
||||
|
||||
## Diagramme
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Requested: Utilisateur demande suppression
|
||||
|
||||
Requested --> GracePeriod: Compte désactivé, email envoyé
|
||||
|
||||
GracePeriod --> Cancelled: Clic lien annulation (< 30j)
|
||||
GracePeriod --> PendingDeletion: Délai 30j écoulé
|
||||
|
||||
Cancelled --> [*]
|
||||
|
||||
PendingDeletion --> Deleted: Job cron suppression effective
|
||||
|
||||
Deleted --> [*]
|
||||
```
|
||||
|
||||
## Règles
|
||||
|
||||
| État | Valeur | Description |
|
||||
|------|--------|-------------|
|
||||
| Requested | `requested` | Demande initiée, validation requise |
|
||||
| Grace Period | `grace_period` | 30j annulation possible, compte inaccessible |
|
||||
| Cancelled | `cancelled` | Utilisateur a annulé, compte réactivé |
|
||||
| Pending Deletion | `pending_deletion` | File job cron (< 24h) |
|
||||
| Deleted | `deleted` | Données supprimées, contenus anonymisés |
|
||||
|
||||
**Grace period** : 30 jours
|
||||
**Pendant grace period** :
|
||||
- Compte désactivé (login impossible)
|
||||
- Contenus cachés (non diffusés)
|
||||
- Sessions/tokens révoqués
|
||||
- Email avec token annulation (valide 30j)
|
||||
|
||||
**Après 30j** :
|
||||
- Données personnelles supprimées
|
||||
- Contenus créés anonymisés (créateur = "Utilisateur supprimé")
|
||||
- Historique GPS/écoute supprimé
|
||||
- Irréversible
|
||||
44
docs/domains/_shared/states/breach-incident-lifecycle.md
Normal file
44
docs/domains/_shared/states/breach-incident-lifecycle.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Cycle de vie - Incident de violation de données
|
||||
|
||||
## Diagramme
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Detected: Alerte monitoring
|
||||
|
||||
Detected --> Contained: Confinement immédiat (H+0)
|
||||
|
||||
Contained --> UnderInvestigation: Évaluation gravité (H+24)
|
||||
|
||||
UnderInvestigation --> Resolved: Risque faible (mesures suffisantes)
|
||||
UnderInvestigation --> CNILNotificationRequired: Risque utilisateurs
|
||||
|
||||
CNILNotificationRequired --> CNILNotified: Notification CNIL (< H+72)
|
||||
|
||||
CNILNotified --> Resolved: Pas de risque élevé utilisateurs
|
||||
CNILNotified --> UsersNotificationRequired: Risque élevé
|
||||
|
||||
UsersNotificationRequired --> UsersNotified: Email + push utilisateurs (< H+72)
|
||||
|
||||
UsersNotified --> Resolved: Post-mortem + correctifs
|
||||
|
||||
Resolved --> [*]
|
||||
```
|
||||
|
||||
## Règles
|
||||
|
||||
| État | Valeur | Délai max |
|
||||
|------|--------|-----------|
|
||||
| Detected | `detected` | H+0 |
|
||||
| Contained | `contained` | H+0 (immédiat) |
|
||||
| Under Investigation | `under_investigation` | H+24 |
|
||||
| CNIL Notification Required | `cnil_notification_required` | H+48 |
|
||||
| CNIL Notified | `cnil_notified` | H+72 (Article 33 RGPD) |
|
||||
| Users Notification Required | `users_notification_required` | H+48 |
|
||||
| Users Notified | `users_notified` | H+72 (Article 34 RGPD) |
|
||||
| Resolved | `resolved` | Post-incident |
|
||||
|
||||
**Sévérité** : `low` / `medium` / `high` / `critical`
|
||||
**Notification CNIL** : Obligatoire si risque pour droits/libertés utilisateurs
|
||||
**Notification utilisateurs** : Obligatoire si risque **élevé**
|
||||
**Runbook** : `docs/rgpd/procedure-breach.md`
|
||||
32
docs/domains/_shared/states/parental-consent-lifecycle.md
Normal file
32
docs/domains/_shared/states/parental-consent-lifecycle.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# Cycle de vie - Consentement parental
|
||||
|
||||
## Diagramme
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> PendingValidation: Ado saisit email parent
|
||||
|
||||
PendingValidation --> Validated: Parent clique lien (< 7j)
|
||||
PendingValidation --> Expired: Délai 7j écoulé
|
||||
|
||||
Validated --> Revoked: Parent révoque consentement
|
||||
Validated --> AutoRevoked: Ado atteint 16 ans
|
||||
|
||||
Expired --> [*]
|
||||
Revoked --> [*]
|
||||
AutoRevoked --> [*]
|
||||
```
|
||||
|
||||
## Règles
|
||||
|
||||
| État | Valeur | Description |
|
||||
|------|--------|-------------|
|
||||
| Pending Validation | `pending_validation` | Email envoyé parent, token valide 7j |
|
||||
| Validated | `validated` | Parent a validé, restrictions 13-15 ans actives |
|
||||
| Expired | `expired` | Token expiré sans validation, compte inactif |
|
||||
| Revoked | `revoked` | Parent révoque, compte désactivé immédiatement |
|
||||
| Auto-Revoked | `auto_revoked` | Ado atteint 16 ans, restrictions levées automatiquement |
|
||||
|
||||
**Délai expiration** : 7 jours
|
||||
**Révocation** : Possible à tout moment via dashboard parent
|
||||
**Transition automatique** : À 16 ans → compte passe en `active` standard
|
||||
@@ -4,18 +4,31 @@
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Active: Inscription validée
|
||||
[*] --> PendingEmailVerification: Inscription
|
||||
[*] --> PendingParentalConsent: Inscription 13-15 ans
|
||||
|
||||
PendingEmailVerification --> Active: Email vérifié (16+ ans)
|
||||
PendingParentalConsent --> ActiveMinor: Parent valide
|
||||
PendingParentalConsent --> Expired: Token expiré (7j)
|
||||
|
||||
Active --> Suspended: Strikes 3/4/5
|
||||
Active --> GracePeriod: Demande suppression
|
||||
Active --> Frozen: Gel temporaire (limitation traitement)
|
||||
Active --> Deleted: Inactivité 5 ans
|
||||
|
||||
ActiveMinor --> Active: 16 ans atteints
|
||||
ActiveMinor --> Suspended: Modération
|
||||
ActiveMinor --> Deleted: Parent révoque
|
||||
|
||||
Frozen --> Active: Réactivation utilisateur
|
||||
|
||||
Suspended --> Active: Fin suspension / Appel
|
||||
Suspended --> Deleted: Suspension définitive
|
||||
|
||||
GracePeriod --> Active: Annulation < 30j
|
||||
GracePeriod --> Deleted: Après 30j
|
||||
|
||||
Expired --> [*]
|
||||
Deleted --> [*]
|
||||
```
|
||||
|
||||
@@ -23,9 +36,20 @@ stateDiagram-v2
|
||||
|
||||
| État | Valeur | Durée/Condition |
|
||||
|------|--------|-----------------|
|
||||
| Active | `active` | Compte fonctionnel |
|
||||
| Pending Email Verification | `pending_email_verification` | Email non vérifié (expire 24h) |
|
||||
| Pending Parental Consent | `pending_parental_consent` | Ado 13-15 ans, attente validation parent (expire 7j) |
|
||||
| Active | `active` | Compte fonctionnel standard (16+ ans) |
|
||||
| Active Minor | `active_minor` | Compte 13-15 ans avec restrictions parentales |
|
||||
| Frozen | `frozen` | Gel temporaire (lecture seule), réactivable à tout moment |
|
||||
| Suspended | `suspended` | Strike 3: 7j, Strike 4: 30j, Strike 5: définitif |
|
||||
| Grace Period | `grace_period` | 30j avant suppression, annulable |
|
||||
| Deleted | `deleted` | Données anonymisées, irréversible |
|
||||
| Expired | `expired` | Token expiré sans validation |
|
||||
| Deleted | `deleted` | Données supprimées, contenus anonymisés, irréversible |
|
||||
|
||||
**Restrictions Active Minor** :
|
||||
- GPS précis : configurable par parent
|
||||
- Messagerie privée : désactivée par défaut
|
||||
- Contenus +16 : filtrés
|
||||
- Transition auto vers `active` à 16 ans
|
||||
|
||||
**Purge inactivité** : 5 ans sans connexion (notifications 90j/30j/7j avant)
|
||||
|
||||
30
mkdocs.yml
30
mkdocs.yml
@@ -103,6 +103,20 @@ nav:
|
||||
- RGPD: domains/_shared/rules/rgpd.md
|
||||
- Gestion Erreurs: domains/_shared/rules/gestion-erreurs.md
|
||||
- 'Annexe Post-MVP': domains/_shared/rules/ANNEXE-POST-MVP.md
|
||||
- Features BDD:
|
||||
- 'RGPD & Conformité':
|
||||
- Consentement: generated/bdd/_shared/features/rgpd-compliance/consentement.md
|
||||
- Anonymisation GPS: generated/bdd/_shared/features/rgpd-compliance/anonymisation-gps.md
|
||||
- Portabilité Données: generated/bdd/_shared/features/rgpd-compliance/portabilite-donnees.md
|
||||
- Suppression Compte: generated/bdd/_shared/features/rgpd-compliance/suppression-compte.md
|
||||
- Conservation Données: generated/bdd/_shared/features/rgpd-compliance/conservation-donnees.md
|
||||
- Cookies & Analytics: generated/bdd/_shared/features/rgpd-compliance/cookies-analytics.md
|
||||
- Mode Dégradé GeoIP: generated/bdd/_shared/features/rgpd-compliance/mode-degrade-geoip.md
|
||||
- Compliance Administrative: generated/bdd/_shared/features/rgpd-compliance/compliance-administrative.md
|
||||
- Protection Mineurs: generated/bdd/_shared/features/rgpd-compliance/minors-protection.md
|
||||
- Sécurité Données: generated/bdd/_shared/features/rgpd-compliance/data-security.md
|
||||
- Politique Confidentialité: generated/bdd/_shared/features/rgpd-compliance/privacy-policy.md
|
||||
- Droits Utilisateurs: generated/bdd/_shared/features/rgpd-compliance/user-rights.md
|
||||
- Entités:
|
||||
- "Vue d'ensemble": domains/_shared/entities/entities-overview.md
|
||||
- 'Auth & Sécurité':
|
||||
@@ -112,6 +126,12 @@ nav:
|
||||
- Consentements: domains/_shared/entities/consents.md
|
||||
- Historique GPS: domains/_shared/entities/location-history.md
|
||||
- Exports Données: domains/_shared/entities/exports.md
|
||||
- Consentements Parentaux: domains/_shared/entities/parental-consents.md
|
||||
- Politique Confidentialité: domains/_shared/entities/privacy-policy-versions.md
|
||||
- Suppressions Compte: domains/_shared/entities/account-deletions.md
|
||||
- Incidents Breach: domains/_shared/entities/breach-incidents.md
|
||||
- Historique Profil: domains/_shared/entities/user-profile-history.md
|
||||
- Logs Rétention Données: domains/_shared/entities/data-retention-logs.md
|
||||
- 'Recommandation & Modération':
|
||||
- Jauges Intérêt: domains/_shared/entities/interest-gauges.md
|
||||
- Signalements: domains/_shared/entities/reports.md
|
||||
@@ -121,13 +141,21 @@ nav:
|
||||
- Session: domains/_shared/states/session-lifecycle.md
|
||||
- Signalement: domains/_shared/states/report-lifecycle.md
|
||||
- Export Données: domains/_shared/states/export-lifecycle.md
|
||||
- Consentement Parental: domains/_shared/states/parental-consent-lifecycle.md
|
||||
- Suppression Compte: domains/_shared/states/account-deletion-lifecycle.md
|
||||
- Incident Breach: domains/_shared/states/breach-incident-lifecycle.md
|
||||
- Séquences:
|
||||
- Authentification: domains/_shared/sequences/authentication-flow.md
|
||||
- Refresh Token: domains/_shared/sequences/token-refresh.md
|
||||
- Modération Contenu: domains/_shared/sequences/content-moderation.md
|
||||
- Signalement: domains/_shared/sequences/content-report.md
|
||||
- Export Données: domains/_shared/sequences/data-export.md
|
||||
- Export Données (RGPD): domains/_shared/sequences/export-donnees.md
|
||||
- Suppression Compte: domains/_shared/sequences/account-deletion.md
|
||||
- Suppression Compte (RGPD): domains/_shared/sequences/suppression-compte.md
|
||||
- Consentement Parental: domains/_shared/sequences/consentement-parental.md
|
||||
- Anonymisation GPS: domains/_shared/sequences/anonymisation-gps.md
|
||||
- Notification Breach: domains/_shared/sequences/notification-breach.md
|
||||
- 'Supporting Subdomains':
|
||||
- '🎯 Recommendation':
|
||||
- Vue d'ensemble: domains/recommendation/README.md
|
||||
@@ -198,6 +226,8 @@ nav:
|
||||
- 'Validation TestFlight': mobile/testflight-validation-plan.md
|
||||
- Conformité & Compliance:
|
||||
- 'Soumission aux Stores': compliance/stores-submission.md
|
||||
- Tests BDD:
|
||||
- "Vue d'ensemble": generated/bdd/index.md
|
||||
- Architecture & Techniques:
|
||||
- Séquences:
|
||||
- 'Cache Géospatial': architecture/sequences/cache-geospatial.md
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -368,7 +368,7 @@ def main():
|
||||
# Chemins
|
||||
project_root = Path(__file__).parent.parent
|
||||
features_dir = project_root / 'docs' / 'domains'
|
||||
output_dir = project_root / 'docs' / 'bdd'
|
||||
output_dir = project_root / 'generated' / 'bdd'
|
||||
|
||||
# Nettoyer le dossier de sortie
|
||||
if output_dir.exists():
|
||||
|
||||
@@ -339,9 +339,9 @@ def main():
|
||||
project_root = Path(__file__).parent.parent
|
||||
docs_dir = project_root / 'docs'
|
||||
mkdocs_path = project_root / 'mkdocs.yml'
|
||||
output_dir = project_root / 'output'
|
||||
output_dir = project_root / 'generated' / 'pdf'
|
||||
|
||||
output_dir.mkdir(exist_ok=True)
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
print("📄 Génération du PDF de la documentation RoadWave...")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user