337 lines
10 KiB
Markdown
337 lines
10 KiB
Markdown
## 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)
|