Initial commit
This commit is contained in:
336
docs/regles-metier/02-conformite-rgpd.md
Normal file
336
docs/regles-metier/02-conformite-rgpd.md
Normal file
@@ -0,0 +1,336 @@
|
||||
## 13. Conformité RGPD
|
||||
|
||||
### 13.1 Gestion du consentement
|
||||
|
||||
**Décision** : Tarteaucitron.js + PostgreSQL backend
|
||||
|
||||
**Implémentation web** :
|
||||
- ✅ Tarteaucitron.js (opensource, self-hosted)
|
||||
- ✅ Banner RGPD français, customisable
|
||||
- ✅ Granularité : fonctionnel / analytique / marketing
|
||||
|
||||
**Implémentation backend** :
|
||||
- Table `user_consents` avec versioning
|
||||
- Champs : user_id, consent_type, version, accepted, timestamp
|
||||
- Historique complet conservé (preuve légale)
|
||||
|
||||
**Consentements requis** :
|
||||
- **Géolocalisation précise** : obligatoire (banner + permission OS)
|
||||
- **Analytics** : optionnel (Matomo)
|
||||
- **Notifications push** : optionnel (permission OS)
|
||||
|
||||
**Justification** :
|
||||
- Opensource, 0€, conformité RGPD garantie
|
||||
- Historique backend = preuve légale en cas de contrôle
|
||||
- Granularité conforme recommandations CNIL
|
||||
|
||||
---
|
||||
|
||||
### 13.2 Anonymisation des données GPS
|
||||
|
||||
**Décision** : Geohash après 24h
|
||||
|
||||
**Processus** :
|
||||
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;
|
||||
```
|
||||
|
||||
**Exceptions** :
|
||||
- ✅ Historique personnel visible (liste trajets) : conservation intégrale tant que compte actif
|
||||
- ❌ Analytics globales : uniquement geohash anonyme
|
||||
|
||||
**Justification** :
|
||||
- Vraie anonymisation RGPD (CNIL compliant)
|
||||
- Permet analytics agrégées (heatmaps trafic)
|
||||
- PostGIS natif, 0€
|
||||
|
||||
---
|
||||
|
||||
### 13.3 Export des données (portabilité)
|
||||
|
||||
**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
|
||||
```
|
||||
|
||||
**Données exportées** :
|
||||
- Profil utilisateur (email, pseudo, date inscription, bio)
|
||||
- Historique d'écoute (titres, dates, durées)
|
||||
- Contenus créés (audio + métadonnées)
|
||||
- Abonnements et likes
|
||||
- Centres d'intérêt (jauges)
|
||||
- Historique consentements
|
||||
|
||||
**Processus** :
|
||||
1. Demande via paramètres compte
|
||||
2. Génération asynchrone (worker background)
|
||||
3. Email avec lien download (expire **7 jours**)
|
||||
4. Délai : **48h maximum** (conformité RGPD)
|
||||
|
||||
**Limite** :
|
||||
- Maximum **1 export/mois** (anti-abus)
|
||||
|
||||
**Justification** :
|
||||
- Conformité article 20 RGPD (portabilité)
|
||||
- Double format (human + machine)
|
||||
- Worker asynchrone évite timeout
|
||||
|
||||
---
|
||||
|
||||
### 13.4 Suppression du compte
|
||||
|
||||
**Décision** : Grace period 30j + anonymisation contenus
|
||||
|
||||
**Processus** :
|
||||
1. Utilisateur clique "Supprimer mon compte"
|
||||
2. Compte désactivé immédiatement (login impossible)
|
||||
3. Contenus cachés pendant 30 jours (non diffusés)
|
||||
4. Email confirmation + lien annulation (valide 30j)
|
||||
5. Après 30j sans annulation : suppression effective
|
||||
|
||||
**Suppression effective** :
|
||||
- ✅ Compte utilisateur supprimé (données personnelles)
|
||||
- ✅ Historique d'écoute supprimé
|
||||
- ✅ GPS historique supprimé
|
||||
- ✅ Sessions et tokens révoqués
|
||||
- ⚠️ Contenus créés **anonymisés** (créateur = "Utilisateur supprimé")
|
||||
- ⚠️ Likes et abonnements supprimés (mais compteurs préservés)
|
||||
|
||||
**Contenus conservés anonymement** :
|
||||
- Audio files (CDN)
|
||||
- Métadonnées (titre, description, tags, géolocalisation)
|
||||
- Statistiques d'écoute
|
||||
|
||||
**Justification** :
|
||||
- Grace period évite suppressions impulsives
|
||||
- Anonymisation contenus = intérêt légitime communauté
|
||||
- Conforme RGPD si créateur = donnée supprimée
|
||||
|
||||
---
|
||||
|
||||
### 13.5 Mode dégradé (sans GPS précis)
|
||||
|
||||
**Décision** : GeoIP par défaut, GPS optionnel
|
||||
|
||||
**Niveaux de précision** :
|
||||
|
||||
| Niveau | Technologie | Contenus accessibles | Consentement |
|
||||
|--------|-------------|---------------------|--------------|
|
||||
| **Pays** | Aucune géoloc | Contenus nationaux uniquement | ❌ Non requis |
|
||||
| **Ville** | GeoIP (MaxMind) | Contenus régionaux/ville | ❌ Non requis |
|
||||
| **Précis** | GPS | Tous contenus (hyperlocaux inclus) | ✅ Requis |
|
||||
|
||||
**Implémentation** :
|
||||
- Démarrage app : GeoIP automatique (IP → ville)
|
||||
- Banner in-app : "Activez la géolocalisation pour découvrir du contenu près de chez vous"
|
||||
- Upgrade volontaire vers GPS
|
||||
|
||||
**API GeoIP** :
|
||||
- MaxMind GeoLite2 (gratuit, self-hosted)
|
||||
- Update DB mensuelle automatique
|
||||
- Précision ~80% au niveau ville
|
||||
|
||||
**Justification** :
|
||||
- RGPD : pas de consentement requis pour GeoIP (pas de donnée personnelle)
|
||||
- UX dégradée acceptable (contenus disponibles)
|
||||
- Progressive disclosure (upgrade optionnel)
|
||||
|
||||
---
|
||||
|
||||
### 13.6 Durée de conservation des données
|
||||
|
||||
**Décision** : 5 ans inactivité → purge automatique
|
||||
|
||||
**Règles** :
|
||||
|
||||
| Type de compte | Seuil inactivité | Action |
|
||||
|----------------|------------------|--------|
|
||||
| **Auditeur uniquement** | 5 ans sans connexion | Suppression automatique |
|
||||
| **Créateur avec contenus actifs** | Jamais (tant qu'écoutes) | Conservation indéfinie |
|
||||
| **Créateur inactif** | 5 ans sans connexion + 2 ans sans écoute | Suppression automatique |
|
||||
|
||||
**Notifications avant suppression** :
|
||||
- Email + push : **90 jours** avant
|
||||
- Email + push : **30 jours** avant
|
||||
- Email + push : **7 jours** avant
|
||||
- Toute connexion = reset compteur inactivité
|
||||
|
||||
**Contenu conservé** :
|
||||
- Contenus créés par comptes supprimés (anonymisés) : conservation indéfinie
|
||||
|
||||
**Justification** :
|
||||
- Conformité principe minimisation RGPD
|
||||
- 5 ans = équilibre raisonnable (standard industrie)
|
||||
- Exception créateurs actifs = intérêt légitime plateforme
|
||||
|
||||
---
|
||||
|
||||
### 13.7 Cookies et trackers web
|
||||
|
||||
**Décision** : Matomo self-hosted, zéro cookie tiers
|
||||
|
||||
**Cookies utilisés** :
|
||||
|
||||
| Cookie | Type | Durée | Finalité | Consentement |
|
||||
|--------|------|-------|----------|--------------|
|
||||
| `session` | Technique | 30j | Authentification | ❌ Non requis |
|
||||
| `refresh_token` | Technique | 30j | Session persistante | ❌ Non requis |
|
||||
| `_pk_id` | Analytique | 13 mois | Matomo (IP anonyme) | ✅ Requis |
|
||||
|
||||
**Analytics : Matomo self-hosted** :
|
||||
- Hébergé sur nos serveurs (Docker)
|
||||
- IP anonymisées automatiquement (2 derniers octets)
|
||||
- Pas de cookie si consentement refusé
|
||||
- Alternative : Plausible (SaaS EU, 9€/mois)
|
||||
|
||||
**Trackers interdits** :
|
||||
- ❌ Google Analytics
|
||||
- ❌ Facebook Pixel
|
||||
- ❌ Hotjar, Mixpanel, etc.
|
||||
|
||||
**Justification** :
|
||||
- Souveraineté données (pas de transfert US)
|
||||
- Conformité RGPD max (CNIL compatible)
|
||||
- Matomo = opensource, 0€ infra
|
||||
|
||||
---
|
||||
|
||||
### 13.8 Registre des traitements
|
||||
|
||||
**Décision** : Document Markdown versionné Git (MVP)
|
||||
|
||||
**Emplacement** :
|
||||
- `docs/rgpd/registre-traitements.md`
|
||||
- Versionné Git (historique modifications)
|
||||
|
||||
**Contenu obligatoire par traitement** :
|
||||
- Nom et finalité du traitement
|
||||
- Catégories de données collectées
|
||||
- Base légale (consentement / contrat / intérêt légitime)
|
||||
- Durée de conservation
|
||||
- Destinataires (sous-traitants, CDN, etc.)
|
||||
- Transferts hors UE (aucun prévu)
|
||||
|
||||
**Responsable** :
|
||||
- DPO / Fondateur
|
||||
- Review trimestrielle obligatoire
|
||||
- Update immédiate si nouveau traitement
|
||||
|
||||
**Migration future** :
|
||||
- Si > 100K utilisateurs : interface admin PostgreSQL
|
||||
|
||||
**Justification** :
|
||||
- Obligation RGPD Article 30
|
||||
- Markdown = simple, versionné, auditable
|
||||
- 0€
|
||||
|
||||
---
|
||||
|
||||
### 13.9 Notification violations de données (breach)
|
||||
|
||||
**Décision** : Monitoring + alertes + runbook
|
||||
|
||||
**Détection automatique** :
|
||||
|
||||
| Événement | Outil | Alerte |
|
||||
|-----------|-------|--------|
|
||||
| Erreurs backend critiques | Sentry | Discord/Slack immédiat |
|
||||
| Pic requêtes anormal | Grafana | Email équipe |
|
||||
| Accès non autorisé DB | PostgreSQL logs | SMS fondateur |
|
||||
| Authentification suspecte | Zitadel alerts | Email équipe |
|
||||
|
||||
**Procédure breach** :
|
||||
- Runbook : `docs/rgpd/procedure-breach.md`
|
||||
- Checklist 72h CNIL :
|
||||
1. H+0 : Détection et confinement
|
||||
2. H+24 : Évaluation gravité (données concernées, utilisateurs impactés)
|
||||
3. H+48 : Notification CNIL si risque pour utilisateurs
|
||||
4. H+72 : Notification utilisateurs si risque élevé
|
||||
|
||||
**Contact CNIL** :
|
||||
- Email pré-rédigé (template)
|
||||
- Formulaire en ligne (account CNIL créé)
|
||||
|
||||
**Justification** :
|
||||
- Obligation RGPD Article 33 (notification 72h)
|
||||
- Monitoring proactif évite découverte tardive
|
||||
- Sentry gratuit < 5K events/mois
|
||||
|
||||
---
|
||||
|
||||
### 13.10 DPO (Délégué à la Protection des Données)
|
||||
|
||||
**Décision** : Fondateur = DPO temporaire (MVP)
|
||||
|
||||
**Raison légale** :
|
||||
- Non obligatoire si :
|
||||
- < 250 employés
|
||||
- Pas de traitement à grande échelle de données sensibles
|
||||
- RoadWave : données localisation = sensible MAIS échelle MVP
|
||||
|
||||
**Formation** :
|
||||
- CNIL : formation gratuite en ligne (4h)
|
||||
- Certification CNIL "Atelier RGPD" (gratuit)
|
||||
|
||||
**Contact** :
|
||||
- Email : dpo@roadwave.fr
|
||||
- Publié dans CGU et mentions légales
|
||||
- Délai réponse : **1 mois** (RGPD)
|
||||
|
||||
**Migration future** :
|
||||
- Si > 100K utilisateurs : DPO externe mutualisé (~200€/mois)
|
||||
- Ou recrutement DPO interne si > 10 employés
|
||||
|
||||
**Justification** :
|
||||
- Conforme RGPD (non obligatoire en phase MVP)
|
||||
- 0€, contrôle total
|
||||
- Bonne pratique : avoir un contact identifié
|
||||
|
||||
---
|
||||
|
||||
## Récapitulatif Section 13
|
||||
|
||||
| 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 MaxMind + 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€ |
|
||||
|
||||
**Coût total RGPD : ~5€/mois**
|
||||
|
||||
---
|
||||
|
||||
## Points d'attention pour Gherkin
|
||||
|
||||
- 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)
|
||||
Reference in New Issue
Block a user