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:
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)
|
||||
|
||||
Reference in New Issue
Block a user