docs: améliorer rendu markdown et navigation mkdocs

- Ajouter ADR-018 (librairies Go) dans TECHNICAL.md
- Transformer Shared en menu dépliable dans mkdocs (cohérence avec autres domaines)
- Corriger listes markdown (ajout lignes vides avant listes)
- Corriger line breaks dans génération BDD (étapes "Et" sur nouvelles lignes)
- Ajouter script fix-markdown-lists.sh pour corrections futures

Impacte 86 fichiers de documentation et 164 fichiers BDD générés.
This commit is contained in:
jpgiannetti
2026-02-09 20:49:52 +01:00
parent 95c65b8be1
commit 35aaa105d0
87 changed files with 1044 additions and 91 deletions

View File

@@ -74,6 +74,7 @@ Fonctionnalité: Recherche avancée de contenus
```
**Conventions Gherkin** :
- Langue française (`# language: fr`)
- Mots-clés : `Fonctionnalité`, `Scénario`, `Étant donné`, `Quand`, `Alors`
- Commentaires pour référencer les règles DDD
@@ -94,6 +95,7 @@ Cette commande :
Si la catégorie n'existe pas encore, l'ajouter :
```yaml
- '🎯 Recommendation':
# ...
- Tests BDD:
@@ -156,6 +158,7 @@ Description du contexte métier...
**Justification** : Parce que...
**Exemple** :
- Cas nominal : ...
- Cas d'erreur : ...
@@ -177,6 +180,7 @@ Les règles métier doivent être testables → créer des features BDD.
### Étape 5 : Ajouter dans `mkdocs.yml`
```yaml
- '🎙️ Content':
- Règles:
- Création & Publication: domains/content/rules/creation-publication.md
@@ -234,6 +238,7 @@ Requêtes sqlc : `backend/queries/nouvelle_thing.sql`
### Ajouter dans `mkdocs.yml`
```yaml
- Entités:
- Vue d'ensemble: domains/[domain]/entities/vue-ensemble.md
- Nouvelle Entité: domains/[domain]/entities/nouvelle-entite.md # ← NOUVEAU
@@ -268,6 +273,7 @@ sequenceDiagram
## Légende
**Acteurs** :
- Utilisateur : Client de l'API
- API : Backend RoadWave
- Database : PostgreSQL

View File

@@ -80,6 +80,7 @@ Lorsque plusieurs contenus sont disponibles dans une zone, **seul le plus pertin
Chaque utilisateur possède des **jauges d'intérêt** qui évoluent dynamiquement :
### Catégories
- Automobile
- Voyage
- Famille
@@ -116,6 +117,7 @@ Interactions simplifiées pour sécurité routière maximale :
| **Play/Pause** | Mettre en pause / reprendre la lecture |
**Like automatique** : Le système détecte automatiquement vos préférences selon votre temps d'écoute :
- Écoute ≥80% du contenu → Like renforcé (+2 points jauge)
- Écoute 30-79% du contenu → Like standard (+1 point jauge)
- Skip après <10s → Signal négatif (-0.5 point)
@@ -198,6 +200,7 @@ Approche hybride combinant participation communautaire, IA et modérateurs dédi
| **Strike 4** | Ban définitif du compte créateur | Permanent |
**Notes** :
- **Tolérance 1ère fois** (droits d'auteur uniquement) : avertissement sans strike
- **Violations graves** (haine, illégalité, violence) : strike immédiat sans tolérance
- **Réhabilitation** : -1 strike tous les 6 mois sans nouvelle violation

View File

@@ -8,6 +8,7 @@
|-----------|-------------|-----|
| **Backend** | Go + Fiber | [ADR-001](adr/001-langage-backend.md) |
| **Architecture Backend** | Monolithe Modulaire | [ADR-010](adr/010-architecture-backend.md) |
| **Librairies Backend** | Fiber, pgx, rueidis, sqlc, etc. | [ADR-018](adr/018-librairies-go.md) |
| **Authentification** | Zitadel (self-hosted OVH) | [ADR-008](adr/008-authentification.md) |
| **Streaming** | HLS | [ADR-002](adr/002-protocole-streaming.md) |
| **Codec** | Opus | [ADR-003](adr/003-codec-audio.md) |

View File

@@ -47,6 +47,7 @@ Streaming audio vers des utilisateurs mobiles en voiture, avec réseaux instable
La latence HLS (5-30s) entre en conflit avec les notifications géolocalisées qui doivent déclencher l'audio **au moment précis** où l'utilisateur atteint un point d'intérêt.
**Exemple critique** :
- Utilisateur en voiture à 90 km/h (25 m/s)
- ETA de 7 secondes avant le point → notification affichée
- Latence HLS de 15 secondes
@@ -69,6 +70,7 @@ La latence HLS (5-30s) entre en conflit avec les notifications géolocalisées q
```
**Stratégie de cache** :
- Télécharge les **15 premières secondes** de chaque POI à proximité
- Limite : 3 POI simultanés en cache (max ~25 MB)
- Purge automatique après 200m de distance passée
@@ -152,16 +154,19 @@ Si le pre-buffer échoue (réseau faible, pas de cache), afficher un **loader av
### Impact sur l'Infrastructure
#### Backend (Go)
- **Nouveau service** : `audiocache.Service` pour préparer les extraits M4A
- **Endpoint** : `GET /api/v1/audio/poi/:id/intro` (retourne 15s d'audio)
- **CDN** : Cache NGINX avec TTL 7 jours sur `/audio/*/intro.m4a`
#### Mobile (Flutter)
- **Package** : `just_audio` avec cache local (`flutter_cache_manager`)
- **Stockage** : Max 100 MB de cache audio (auto-purge LRU)
- **Logique** : `PreBufferService` avec scoring de priorité POI
#### Coûts
- **Bande passante** : +10-15 MB/utilisateur/session (vs streaming pur)
- **Stockage CDN** : +500 MB pour 1000 POI × 5 MB intro (négligeable)
- **Économie** : Cache CDN réduit les requêtes origin (-60% selon tests)

View File

@@ -44,12 +44,14 @@ flowchart LR
## Justification
### PostgreSQL + PostGIS
- Requêtes géospatiales complexes et précises
- Index GIST pour performance
- ACID, fiabilité éprouvée
- Écosystème mature
### PgBouncer
- **Connection pooling** : Réduit l'overhead de création de connexions PostgreSQL
- **Mode transaction** : Connexion réutilisée entre transactions (optimal pour API stateless)
- **Performance** : Permet de gérer 1000+ connexions concurrentes avec ~100 connexions réelles à PostgreSQL
@@ -57,6 +59,7 @@ flowchart LR
- **Port** : :6432 (vs :5432 pour PostgreSQL direct)
### Redis
- Cache géo natif (`GEORADIUS`) : 100K+ requêtes/sec
- Sessions utilisateurs
- Pub/sub pour temps réel
@@ -81,11 +84,13 @@ LIMIT 20;
### Configuration PgBouncer
**Mode recommandé** : `transaction`
- Connexion libérée après chaque transaction
- Optimal pour API stateless (Go + Fiber)
- Maximise la réutilisation des connexions
**Pool sizing** :
- `default_pool_size` : 20 (connexions par base)
- `max_client_conn` : 1000 (connexions clients max)
- `reserve_pool_size` : 5 (connexions de secours)

View File

@@ -67,11 +67,13 @@ features/
**Exécuté par** : Backend (Godog + step definitions Go dans `/backend/tests/bdd/`)
**Exemples de scénarios** :
- `POST /api/v1/auth/register` avec email invalide → retourne 400
- `GET /api/v1/contents/nearby` avec rayon 500m → retourne POI triés par distance
- `DELETE /api/v1/user/account` → supprime données RGPD conformément
**Caractéristiques** :
- Focus sur la **logique métier backend** (algorithme, validation, persistance)
- Pas d'interface utilisateur
- Testable via requêtes HTTP directes
@@ -85,11 +87,13 @@ features/
**Exécuté par** : Mobile (Flutter `integration_test` + step definitions Dart dans `/mobile/tests/bdd/`)
**Exemples de scénarios** :
- Cliquer sur "Lecture" → widget audio player s'affiche avec progress bar
- Mode piéton activé → carte interactive affichée + bouton "Télécharger zone"
- Scroll dans liste podcasts → lazy loading déclenche pagination
**Caractéristiques** :
- Focus sur l'**expérience utilisateur mobile**
- Validation visuelle (widgets, animations, navigation)
- Mock du backend si nécessaire (tests UI isolés)
@@ -103,11 +107,13 @@ features/
**Exécuté par** : Backend **ET** Mobile ensemble
**Exemples de scénarios** :
- Abonnement Premium : Formulaire mobile → API Zitadel → API RoadWave → Mangopay → Confirmation UI
- Erreur réseau : Perte connexion pendant streaming → Fallback mode offline → Reprise auto après reconnexion
- Notification géolocalisée : GPS détecte POI → Backend calcule recommandation → Push notification → Ouverture app → Lecture audio
**Caractéristiques** :
- Tests **cross-composants** (intégration complète)
- Implique souvent des **services tiers** (Zitadel, Mangopay, Firebase)
- Validation du **parcours utilisateur de bout en bout**
@@ -117,10 +123,12 @@ features/
### Implémentation Step Definitions
**Backend** : `/backend/tests/bdd/`
- Step definitions Go pour features `api/` et `e2e/`
- Utilise `godog` et packages backend (`service`, `repository`)
**Mobile** : `/mobile/tests/bdd/`
- Step definitions Dart pour features `ui/` et `e2e/`
- Utilise Flutter `integration_test` framework

View File

@@ -14,11 +14,13 @@ RoadWave nécessite un système d'authentification sécurisé pour mobile (iOS/A
**Zitadel self-hosted sur OVH France** pour l'IAM avec validation JWT locale côté API Go.
**Méthode d'authentification** : **Email/Password uniquement** (pas d'OAuth tiers)
- ✅ Authentification native Zitadel (email + mot de passe)
-**Pas de fournisseurs OAuth externes** (Google, Apple, Facebook)
- **Protocole** : OAuth2 PKCE (entre app mobile et Zitadel uniquement)
**Architecture de déploiement** :
- Container Docker sur le même VPS OVH (Gravelines, France) que l'API
- Base de données PostgreSQL partagée avec RoadWave (séparation logique par schéma)
- Aucune donnée d'authentification ne transite par des serveurs tiers
@@ -102,12 +104,14 @@ graph TB
4. App mobile → Go API avec JWT → validation locale
**Ce que nous N'UTILISONS PAS** :
- ❌ "Sign in with Google"
- ❌ "Sign in with Apple"
- ❌ "Sign in with Facebook"
- ❌ Aucun autre fournisseur externe
**Pourquoi OAuth2 alors ?** :
- OAuth2 PKCE est le **standard moderne** pour auth mobile (sécurisé, refresh tokens, etc.)
- Zitadel implémente OAuth2/OIDC comme **protocole**, mais l'auth reste email/password
- Alternative serait session cookies (moins adapté mobile) ou JWT custom (réinventer la roue)

View File

@@ -45,6 +45,7 @@ RoadWave nécessite applications iOS et Android avec support CarPlay/Android Aut
- **Cache images** : `cached_network_image` (LRU cache)
**Points d'attention** :
- ⚠️ **Permissions progressives requises** pour `geofence_service` et `geolocator` (voir section "Stratégie de Permissions")
- ⚠️ **Licences** : 100% permissives (MIT, BSD-3) - voir ADR-020
@@ -53,6 +54,7 @@ RoadWave nécessite applications iOS et Android avec support CarPlay/Android Aut
### Contexte et Enjeux
**Problème** : La géolocalisation en arrière-plan (requise pour le mode piéton) est **très scrutée** par Apple et Google :
- **iOS App Store** : Taux de rejet ~70% si permission "Always Location" mal justifiée
- **Android Play Store** : `ACCESS_BACKGROUND_LOCATION` nécessite déclaration spéciale depuis Android 10
- **RGPD** : Permissions doivent être **optionnelles** et l'app **utilisable sans**
@@ -74,6 +76,7 @@ Trois niveaux de permissions doivent être gérés :
**Quand** : Premier lancement de l'app
**Demande** : `locationWhenInUse` uniquement
- iOS : "Allow While Using App"
- Android : `ACCESS_FINE_LOCATION`
@@ -136,21 +139,25 @@ Pour vous proposer du contenu audio adapté
Le service de gestion des permissions (`lib/core/services/location_permission_service.dart`) doit implémenter :
**Détection du niveau actuel** :
- Vérifier le statut de la permission `location` (when in use)
- Vérifier le statut de la permission `locationAlways` (background)
- Retourner le niveau le plus élevé accordé
**Demande de permission de base** (Étape 1) :
- Demander uniquement la permission `location` (when in use)
- Utilisée lors de l'onboarding
- Aucun écran d'éducation requis
**Demande de permission arrière-plan** (Étape 2) :
- **Toujours** afficher un écran d'éducation AVANT la demande OS
- Demander la permission `locationAlways` (iOS) ou `ACCESS_BACKGROUND_LOCATION` (Android)
- Si refusée de manière permanente, proposer l'ouverture des réglages système
**Gestion des refus** :
- Détecter si la permission est refusée de manière permanente
- Proposer l'ouverture des réglages de l'appareil avec un message clair
- Permettre à l'utilisateur d'annuler
@@ -160,6 +167,7 @@ Le service de gestion des permissions (`lib/core/services/location_permission_se
#### iOS (`ios/Runner/Info.plist`)
**Clés requises** :
- `NSLocationWhenInUseUsageDescription` : Décrire l'usage pour le mode voiture (contenu géolocalisé en temps réel)
- `NSLocationAlwaysAndWhenInUseUsageDescription` : Décrire l'usage optionnel pour le mode piéton (notifications audio-guides en arrière-plan), mentionner explicitement que c'est optionnel et désactivable
- `UIBackgroundModes` : Activer les modes `location` et `remote-notification`
@@ -170,11 +178,13 @@ Le service de gestion des permissions (`lib/core/services/location_permission_se
#### Android (`android/app/src/main/AndroidManifest.xml`)
**Permissions requises** :
- `ACCESS_FINE_LOCATION` et `ACCESS_COARSE_LOCATION` : Permission de base (when in use)
- `ACCESS_BACKGROUND_LOCATION` : Permission arrière-plan (Android 10+), nécessite justification Play Store
- `FOREGROUND_SERVICE` et `FOREGROUND_SERVICE_LOCATION` : Service persistant pour mode piéton (Android 12+)
**Android Play Store** : Déclaration requise dans Play Console lors de la soumission :
- Justification : "Notifications géolocalisées pour audio-guides touristiques en arrière-plan"
- Vidéo démo obligatoire montrant le flow de demande de permission
@@ -191,12 +201,14 @@ Le service de gestion des permissions (`lib/core/services/location_permission_se
### Tests de Validation Stores
**Checklist App Store (iOS)** :
- [ ] Permission "Always" demandée **uniquement** si user active mode piéton
- [ ] Écran d'éducation **avant** demande OS (requis iOS 13+)
- [ ] App fonctionne sans permission "Always" (validation critique)
- [ ] Texte `Info.plist` clair et honnête (pas de tracking publicitaire)
**Checklist Play Store (Android)** :
- [ ] Déclaration `ACCESS_BACKGROUND_LOCATION` avec justification détaillée
- [ ] Vidéo démo flow de permissions (< 30s, requis Play Console)
- [ ] App fonctionne sans permission background (validation critique)

View File

@@ -79,6 +79,7 @@ Approche **multi-niveaux** : unitaires, intégration, BDD (Gherkin), E2E, load t
- `github.com/cucumber/godog`
- `github.com/testcontainers/testcontainers-go`
- `grafana/k6` (AGPL-3.0, usage interne OK)
- Temps CI : ~3-5 min (tests unitaires + BDD)
- Tests intégration/E2E : nightly builds (15-30 min)
- Load tests : avant chaque release majeure

View File

@@ -68,6 +68,7 @@ mobile/tests/bdd/inscription_steps.dart → Teste l'UI mobile
```
Cela garantit que :
- Les spécifications métier sont uniques et cohérentes
- Chaque couche teste sa responsabilité
- Les tests valident le contrat entre front et back

View File

@@ -52,6 +52,7 @@ OVH Object Storage (~1.20€/100GB)
| **Scale** | 100K+ | Scaleway Kubernetes (Kapsule) | ~500€ | Auto-scaling OU multi-région |
**Triggers détaillés** :
- **Phase 2** : CPU > 70% (7j), latence p99 > 100ms, backups > 1h/semaine, MRR > 2000€
- **Phase 3** : Auto-scaling horizontal requis, multi-région Europe, DevOps dédié, > 5 services

View File

@@ -8,6 +8,7 @@
RoadWave nécessite un service d'envoi d'emails **techniques uniquement** (pas de notifications sociales, alertes marketing, promotions).
**Périmètre strict** :
-**Authentification** : Vérification email (inscription), réinitialisation mot de passe, changement email
-**Sécurité** : Alertes connexion inhabituelle, changement password
-**Modération** : Strikes, suspensions, bannissements

View File

@@ -45,6 +45,7 @@ Architecture hybride en **2 phases** :
5. Utilisateur clique → app s'ouvre → HLS démarre l'audio (ADR-002)
**Limitations MVP** :
- Fonctionne uniquement si l'utilisateur a envoyé sa position < 5 minutes
- En voiture rapide (>80 km/h), possible de "manquer" un POI si position pas mise à jour
@@ -96,10 +97,12 @@ Architecture hybride en **2 phases** :
### Pourquoi implémentation directe APNS/FCM et pas SDK Firebase ?
**Réalité technique** : Notifications natives requièrent obligatoirement Google/Apple
- **APNS (Apple)** : Seul protocole pour notifications iOS → dépendance Apple inévitable
- **FCM (Google)** : Protocole standard Android (Google Play Services)
**Implémentation directe choisie** :
- **Gratuit** : APNS et FCM sont gratuits (pas de limite de volume)
- **Self-hosted** : Code backend 100% maîtrisé, pas de dépendance SDK tiers
- **Fiabilité** : Infrastructure Apple/Google avec 99.95% uptime
@@ -123,6 +126,7 @@ Architecture hybride en **2 phases** :
- ❌ Toujours wrapper autour APNS/FCM
**Décision technique** :
- Implémentation directe APNS/FCM dès le MVP
- **Cohérence ADR** : Respecte ADR-008 (self-hosted) et ADR-015 (souveraineté française)
- **Abstraction layer** : Interface `NotificationProvider` pour faciliter maintenance
@@ -150,9 +154,11 @@ Architecture hybride en **2 phases** :
- ⚠️ **Gestion certificats APNS** : Renouvellement annuel + configuration
- Mitigé par scripts automation (certificats auto-renouvelés)
- Documentation complète du processus
- ⚠️ **Tokens push sensibles** : Tokens FCM/APNS stockés côté backend
- Chiffrement tokens en base (conformité RGPD)
- Rotation automatique des tokens expirés
- ❌ WebSocket nécessite maintien de connexion (charge serveur +10-20%)
- ❌ Mode offline non disponible au MVP (déception possible des early adopters)

View File

@@ -6,6 +6,7 @@
## Contexte
Le backend Go de RoadWave nécessite des librairies tierces pour HTTP, base de données, tests, streaming, etc. Le choix doit privilégier :
- **Licences permissives** (MIT, Apache-2.0, BSD) sans restrictions commerciales
- **Performance** (10M utilisateurs, 100K RPS, p99 < 100ms)
- **Maturité** et maintenance active
@@ -55,6 +56,7 @@ Utilisation de **16 librairies open-source** avec licences permissives.
## Alternatives considérées
Voir pour comparatifs complets :
- Framework : Fiber vs Gin vs Echo vs Chi
- PostgreSQL : pgx vs GORM vs database/sql
- Redis : rueidis vs go-redis vs redigo
@@ -64,17 +66,20 @@ Voir pour comparatifs complets :
## Justification
### Licences
- **15/16 librairies** : MIT, Apache-2.0, BSD, ISC (permissives)
- **1/16** : AGPL-3.0 (k6 load testing, OK usage interne)
- **Compatibilité totale** : Aucun conflit de licence
### Performance
- **Fiber** : 36K RPS (5% plus rapide que Gin/Echo)
- **pgx** : 30-50% plus rapide que GORM
- **rueidis** : Client-side caching automatique
- **zerolog** : Zero allocation, benchmarks 2025
### Maturité
- **Standards** : testify (27% adoption), golang-migrate, viper
- **Production** : Fiber (33K stars), pgx (10K stars), pion (13K stars)
- **Maintenance** : Toutes actives (commits 2025-2026)
@@ -82,12 +87,14 @@ Voir pour comparatifs complets :
## Conséquences
### Positives
- ✅ Aucune restriction licence commerciale
- ✅ Stack cohérent avec ADR existants (001, 002, 007, 008, 013, 015, 019)
- ✅ Performance validée (benchmarks publics)
- ✅ Écosystème mature et documenté
### Négatives
- ⚠️ **k6 (AGPL-3.0)** : Copyleft, mais OK pour tests internes (pas de SaaS k6 prévu)
- ⚠️ **Gestion certificats APNS** : Renouvellement annuel, configuration manuelle
- ❌ Courbe d'apprentissage : 16 librairies à maîtriser (doc nécessaire)

View File

@@ -8,10 +8,12 @@
RoadWave nécessite un service de géolocalisation par IP pour le mode dégradé (utilisateurs sans GPS activé). Ce service permet de détecter la ville/région de l'utilisateur à partir de son adresse IP et d'afficher du contenu régional même sans permission GPS.
**Évolution du marché** :
- **Avant 2019** : MaxMind GeoLite2 était téléchargeable gratuitement (base de données locale)
- **Depuis 2019** : MaxMind nécessite un compte + limite 1000 requêtes/jour (gratuit), puis 0.003$/requête au-delà
**Usage RoadWave** :
- Mode dégradé : ~10% des utilisateurs (estimation)
- Volume : 1000 utilisateurs × 10% = 100 requêtes/jour (MVP)
- Critère : Aucune dépendance à un service tiers payant
@@ -33,6 +35,7 @@ RoadWave nécessite un service de géolocalisation par IP pour le mode dégradé
### IP2Location Lite (choix retenu)
**Avantages** :
- Gratuit (pas de limite de requêtes)
- Self-hosted (souveraineté des données, cohérence avec [ADR-004](004-cdn.md))
- Base de données SQLite légère (50-100 MB)
@@ -41,12 +44,14 @@ RoadWave nécessite un service de géolocalisation par IP pour le mode dégradé
- Pas de compte tiers requis
**Inconvénients** :
- Maintenance mensuelle (mise à jour DB)
- Précision équivalente à MaxMind (~±50 km)
### MaxMind GeoLite2 API (rejeté)
**Pourquoi rejeté** :
- Coût potentiel en cas de dépassement quota (risque faible mais existant)
- Dépendance à un service tiers (perte de souveraineté)
- Compte requis (friction opérationnelle)
@@ -54,6 +59,7 @@ RoadWave nécessite un service de géolocalisation par IP pour le mode dégradé
### Self-hosted MaxMind (rejeté)
**Pourquoi rejeté** :
- Compte MaxMind obligatoire pour télécharger la DB (friction)
- Complexité identique à IP2Location pour résultat équivalent
- IP2Location offre même fonctionnalité sans compte tiers
@@ -84,28 +90,33 @@ flowchart TD
### Maintenance
**Mise à jour mensuelle** :
- Cron job télécharge nouvelle DB IP2Location (1er du mois)
- Backup DB actuelle avant remplacement
- Rechargement service GeoIP (hot reload sans downtime)
**Monitoring** :
- Alertes si DB > 60 jours (DB obsolète)
- Logs requêtes "IP non trouvée" (détection problèmes DB)
## Conséquences
### Positives
- Aucun coût récurrent (gratuit à l'infini)
- Souveraineté complète des données (cohérence ADR-004)
- Pas de dépendance externe (service tiers)
- Latence minimale (lookup local SQLite < 1ms)
### Négatives
- Maintenance mensuelle requise (automatisable)
- Précision limitée (±50 km, acceptable pour mode dégradé)
- Taille base de données (~50-100 MB sur disque)
### Risques atténués
- **DB obsolète** : Alertes automatiques si > 60 jours
- **IP non trouvée** : Fallback "France" par défaut (code pays FR)
- **Perte DB** : Backup automatique avant chaque mise à jour

View File

@@ -6,6 +6,7 @@
## Contexte
L'application mobile RoadWave (iOS/Android) nécessite des librairies tierces pour audio HLS, géolocalisation, notifications, state management, etc. Le choix doit privilégier :
- **Licences permissives** (MIT, Apache-2.0, BSD) sans restrictions commerciales
- **Maturité** et maintenance active (écosystème Flutter)
- **Performance native** (pas de bridge JS)
@@ -53,28 +54,33 @@ Utilisation de **9 librairies open-source** Flutter avec licences permissives, d
## Alternatives considérées
### State Management
- **flutter_bloc** (choisi) : Pattern BLoC, testable, reactive
- **riverpod** : Plus moderne, moins mature
- **provider** : Simple mais limité pour app complexe
- **getx** : Performance mais opinions controversées
### Audio
- **just_audio** (choisi) : HLS natif, communauté active
- **audioplayers** : Moins mature pour streaming
- **flutter_sound** : Orienté recording, pas streaming
### Géolocalisation
- **geolocator** (choisi) : Standard Flutter, 1.2K+ stars
- **location** : Moins maintenu
- **background_location** : Spécifique background uniquement
### Notifications Push
- **flutter_apns + flutter_fcm** (choisi) : Implémentation directe APNS/FCM, pas de vendor lock-in
- **firebase_messaging** : SDK Firebase, vendor lock-in Google
- **OneSignal** : Plus cher (500€/mois @ 100K users), vendor lock-in
- **Custom WebSocket** : Complexe, toujours besoin APNS/FCM au final (voir ADR-017)
### Geofencing (Phase 2)
- **geofence_service** (choisi) : Natif iOS/Android, économie batterie optimale
- **background_geolocation** : Payant (149$/an par app)
- **flutter_background_location** : Moins mature
@@ -82,17 +88,20 @@ Utilisation de **9 librairies open-source** Flutter avec licences permissives, d
## Justification
### Licences
- **7/9 librairies** : MIT (permissive totale)
- **2/9** : BSD-3 (permissive, compatible commercial)
- **Compatibilité totale** : Aucun conflit de licence, aucune restriction commerciale
### Maturité
- **flutter_bloc** : 11.6K stars, adoption large (state management standard)
- **just_audio** : 900+ stars, utilisé production (podcasts apps)
- **geolocator** : 1.2K stars, maintenu BaseFlow (entreprise Flutter)
- **dio** : 12K+ stars, client HTTP le plus utilisé Flutter
### Performance
- **Compilation native** : Dart → ARM64 (pas de bridge JS comme React Native)
- **just_audio** : Utilise AVPlayer (iOS) et ExoPlayer (Android) natifs
- **geolocator** : Accès direct CoreLocation (iOS) et FusedLocation (Android)
@@ -100,6 +109,7 @@ Utilisation de **9 librairies open-source** Flutter avec licences permissives, d
- **geofence_service** (Phase 2) : Geofencing natif, minimise consommation batterie
### Conformité Stores
- **Permissions progressives** : `permission_handler` + stratégie ADR-010
- **Background modes MVP** : `geolocator` (When In Use) + `firebase_messaging` approuvés stores
- **Background modes Phase 2** : `geofence_service` nécessite permission "Always" (taux acceptation ~30%)
@@ -171,6 +181,7 @@ graph TB
## Conséquences
### Positives
- ✅ Aucune restriction licence commerciale (100% permissif)
- ✅ Stack cohérent avec ADR-010 (Frontend Mobile)
- ✅ Performance native (compilation ARM64 directe)
@@ -179,6 +190,7 @@ graph TB
- ✅ Conformité stores (permissions progressives)
### Négatives
- ⚠️ **CarPlay/Android Auto** : Packages communautaires (pas officiels Flutter)
- ⚠️ **Configuration APNS/FCM** : Gestion certificats et OAuth2, configuration manuelle
- ⚠️ **Permission "Always" Phase 2** : Taux acceptation ~30% (geofencing local)
@@ -190,6 +202,7 @@ graph TB
> **Note** : Les versions exactes seront définies lors de l'implémentation. Cette section indique les packages requis, non les versions à utiliser (qui évoluent rapidement dans l'écosystème Flutter).
**Core (Phase 1 MVP)** :
- `flutter_bloc` - State management
- `just_audio` - Audio HLS streaming
- `dio` - HTTP client
@@ -197,6 +210,7 @@ graph TB
- `cached_network_image` - Cache images
**Géolocalisation & Notifications (Phase 1 MVP)** :
- `geolocator` - GPS haute précision, WebSocket position updates
- `flutter_apns` - Push notifications APNS natif iOS (ADR-017)
- `flutter_fcm` - Push notifications FCM natif Android (ADR-017)
@@ -204,10 +218,12 @@ graph TB
- `permission_handler` - Gestion permissions
**CarPlay/Android Auto (optionnels Phase 1)** :
- `flutter_carplay` - Intégration CarPlay
- `android_auto_flutter` - Support Android Auto
**Geofencing (Phase 2 Post-MVP)** :
- `geofence_service` - Geofencing local pour mode offline (ADR-017 Phase 2)
### Migration depuis ADR-010
@@ -219,15 +235,18 @@ La section "Packages clés" de l'ADR-010 est désormais obsolète et doit réfé
## Risques et Mitigations
### Risque 1 : CarPlay/Android Auto packages communautaires
- **Impact** : Maintenance non garantie par Flutter team
- **Mitigation** : Fork privé si besoin, contribution upstream, ou développement custom si critique
### Risque 2 : Validation App Store (permissions background)
- **Impact** : Taux de rejet ~70% si mal justifié
- **Mitigation Phase 1** : Permission "When In Use" seulement (MVP), moins scrutée par Apple
- **Mitigation Phase 2** : Stratégie progressive (ADR-010), écrans d'éducation, tests beta TestFlight pour permission "Always"
### Risque 3 : Performance audio HLS en arrière-plan
- **Impact** : Interruptions si OS tue l'app
- **Mitigation** : Background audio task iOS, foreground service Android (natif dans `just_audio`)

View File

@@ -14,6 +14,7 @@ L'application nécessite un système de cache performant pour plusieurs cas d'us
- **Rate limiting** : Protection contre les abus API
Les contraintes de performance sont strictes :
- Latence p99 < 5ms pour les requêtes de cache
- Support de 100K+ requêtes/seconde en lecture
- Persistance optionnelle (données non critiques)
@@ -24,6 +25,7 @@ Les contraintes de performance sont strictes :
**Redis 7+ en mode Cluster** sera utilisé comme solution de cache principale.
Configuration :
- Mode Cluster avec 3 nœuds minimum (haute disponibilité)
- Persistence RDB désactivée pour les caches chauds (performance maximale)
- AOF activé uniquement pour les sessions utilisateurs (durabilité)
@@ -76,6 +78,7 @@ Ces commandes permettent de servir les requêtes de proximité directement depui
### Écosystème Go
Librairie `go-redis/redis` (13K+ stars GitHub) :
- Support complet Redis Cluster
- Pipeline et transactions
- Context-aware (intégration Go idiomatique)
@@ -84,6 +87,7 @@ Librairie `go-redis/redis` (13K+ stars GitHub) :
### Pub/Sub pour temps réel
Support natif de messaging publish/subscribe pour :
- Notifications push (invalidation de cache)
- Événements temps réel (nouveau contenu géolocalisé)
- Coordination entre instances API (scaling horizontal)
@@ -106,12 +110,14 @@ Support natif de messaging publish/subscribe pour :
### Stratégie de cache
**TTL par type de donnée** :
- Métadonnées de contenu : 15 minutes (mise à jour rare)
- Résultats géolocalisés : 5 minutes (contenus statiques géographiquement)
- Sessions utilisateurs : 24 heures (renouvellement automatique)
- Rate limiting : 1 minute (fenêtre glissante)
**Invalidation** :
- Publication de contenu → `DEL` métadonnées + publication Pub/Sub
- Modification géolocalisation → `GEOREM` puis `GEOADD`
- Logout utilisateur → `DEL` session
@@ -119,21 +125,25 @@ Support natif de messaging publish/subscribe pour :
### Configuration production
**Cluster 3 nœuds** (minimum haute disponibilité) :
- 1 master + 2 replicas
- Répartition sur 3 zones de disponibilité (anti-affinité)
- `cluster-require-full-coverage no` → lecture dégradée si nœud down
**Mémoire** :
- `maxmemory 2gb` par nœud (ajustable selon charge)
- `maxmemory-policy allkeys-lru` → éviction automatique anciennes clés
**Persistance** :
- RDB désactivé (`save ""`) pour caches chauds
- AOF `appendonly yes` uniquement pour sessions (nœud dédié optionnel)
### Monitoring
Métriques critiques à suivre :
- Taux de hit/miss par namespace (target >95% hit rate)
- Latence p99 par commande (alerter si >10ms)
- Fragmentation mémoire (rebalance si >1.5)

View File

@@ -8,6 +8,7 @@
RoadWave est organisé en monorepo contenant backend Go, mobile Flutter, documentation et features BDD ([ADR-014](014-organisation-monorepo.md)). Sans optimisation, chaque commit déclencherait **tous** les builds (backend + mobile + docs), même si seul un composant a changé.
**Problématique** :
- ❌ Temps de CI/CD inutilement longs (rebuild complet ~15 min)
- ❌ Gaspillage de ressources GitHub Actions
- ❌ Ralentissement du feedback développeur
@@ -44,6 +45,7 @@ RoadWave est organisé en monorepo contenant backend Go, mobile Flutter, documen
#### Workflow Backend (`backend.yml`)
**Déclencheurs** :
- Branches : `main`, `develop`
- Chemins surveillés :
- `backend/**` : Code Go, migrations, configuration
@@ -52,6 +54,7 @@ RoadWave est organisé en monorepo contenant backend Go, mobile Flutter, documen
- `.github/workflows/backend.yml` : Modifications du workflow lui-même
**Jobs exécutés** :
- **Tests unitaires** : Exécution `go test` sur tous les packages
- **Tests d'intégration** : Utilisation de Testcontainers avec PostgreSQL/PostGIS
- **Tests BDD** : Exécution Godog sur features `api/` et `e2e/`
@@ -65,6 +68,7 @@ RoadWave est organisé en monorepo contenant backend Go, mobile Flutter, documen
#### Workflow Mobile (`mobile.yml`)
**Déclencheurs** :
- Branches : `main`, `develop`
- Chemins surveillés :
- `mobile/**` : Code Flutter/Dart, assets, configuration
@@ -73,6 +77,7 @@ RoadWave est organisé en monorepo contenant backend Go, mobile Flutter, documen
- `.github/workflows/mobile.yml` : Modifications du workflow lui-même
**Jobs exécutés** :
- **Tests unitaires** : Exécution `flutter test` sur widgets et logique métier
- **Tests d'intégration** : Tests d'intégration Flutter (interactions UI complexes)
- **Lint** : Analyse statique `flutter analyze`
@@ -80,6 +85,7 @@ RoadWave est organisé en monorepo contenant backend Go, mobile Flutter, documen
- **Build iOS** : Compilation IPA release sans codesign (dépend des tests)
**Environnement** :
- Tests/Lint/Build Android : Ubuntu latest
- Build iOS : macOS latest (requis pour Xcode)
- Flutter 3.16.0+
@@ -89,6 +95,7 @@ RoadWave est organisé en monorepo contenant backend Go, mobile Flutter, documen
#### Workflow Shared (`shared.yml`)
**Déclencheurs** :
- Branches : `main`, `develop`
- Chemins surveillés :
- `docs/**` : ADR, règles métier, documentation technique
@@ -96,6 +103,7 @@ RoadWave est organisé en monorepo contenant backend Go, mobile Flutter, documen
- `.github/workflows/shared.yml` : Modifications du workflow lui-même
**Jobs exécutés** :
- **Validation documentation** : Build MkDocs en mode strict (détecte erreurs markdown)
- **Vérification liens** : Validation des liens internes/externes dans documentation
- **Tests code partagé** : Exécution tests si du code partagé backend-mobile existe
@@ -117,6 +125,7 @@ RoadWave est organisé en monorepo contenant backend Go, mobile Flutter, documen
| **Commit mixte (backend + mobile + docs)** | ✅ | ✅ | ✅ | ~13 min (parallèle) |
**Économie de temps** :
- Commit backend-only : ~5 min (vs 15 min sans path filters) = **67% plus rapide**
- Commit docs-only : ~30s (vs 15 min) = **97% plus rapide**
@@ -125,6 +134,7 @@ RoadWave est organisé en monorepo contenant backend Go, mobile Flutter, documen
Les tests end-to-end dans `/features/e2e/` **déclenchent les deux workflows** (backend ET mobile) car ils testent l'intégration complète :
**Exemples de features E2E** :
- `features/e2e/abonnements/` : Formulaire mobile → API Zitadel → API RoadWave → Mangopay → Confirmation UI
- `features/e2e/error-handling/` : Perte réseau → Fallback mode offline → Reprise auto après reconnexion
@@ -159,6 +169,7 @@ Les tests end-to-end dans `/features/e2e/` **déclenchent les deux workflows** (
**Complexité initiale** : setup plus complexe que workflow monolithique
**Mitigation** :
- Utiliser des **composite actions** pour partager la config commune
- Documentation claire dans ce ADR
- Coût initial faible (~2h setup) vs gains à long terme importants
@@ -177,15 +188,18 @@ Les tests end-to-end dans `/features/e2e/` **déclenchent les deux workflows** (
### Plan d'Implémentation
**Phase 1** : Setup workflows de base (~1h)
- Créer `backend.yml` avec jobs test + lint + build
- Créer `mobile.yml` avec jobs test + lint + build
- Créer `shared.yml` avec validation docs
**Phase 2** : Configuration path filters (~30 min)
- Ajouter `paths:` à chaque workflow
- Tester avec commits isolés (backend-only, mobile-only, docs-only)
**Phase 3** : Optimisations (~30 min)
- Ajouter caching (Go modules, Flutter dependencies, node_modules)
- Créer composite actions pour config partagée
- Ajouter badges status dans README
@@ -226,6 +240,7 @@ Les tests end-to-end dans `/features/e2e/` **déclenchent les deux workflows** (
⚠️ **Faux négatifs** : path filter mal configuré → test non exécuté → bug en production
**Mitigation** :
- Features E2E déclenchent toujours backend + mobile (safety net)
- Tests de validation dans le plan d'implémentation
- Review obligatoire des modifications de workflows

View File

@@ -6,6 +6,7 @@
## Contexte
Le système de modération RoadWave doit traiter des signalements de contenu audio problématique (haine, spam, droits d'auteur, etc.) avec :
- **SLA stricts** : 2h (critique), 24h (haute), 72h (standard) définis dans [Règle 14](../domains/moderation/rules/moderation-flows.md)
- **Scalabilité** : 0-10K+ signalements/mois
- **Conformité DSA** : transparence, traçabilité, délais garantis
@@ -165,12 +166,14 @@ graph TB
### Dépendances
**Backend Go** :
- `gofiber/fiber/v3` : API Dashboard
- `jackc/pgx/v5` : PostgreSQL + LISTEN/NOTIFY
- `redis/rueidis` : Cache priorisation
- Whisper : via Python subprocess ou go-whisper bindings
**Frontend Dashboard** :
- `react` : Framework UI
- `@tanstack/react-table` : Tables performantes
- `wavesurfer.js` : Player audio avec waveform

View File

@@ -6,6 +6,7 @@
## Contexte
RoadWave nécessite un système de monitoring pour garantir la disponibilité cible 99.9% (SLO) définie dans :
- **Métriques** : latency p99 < 100ms, throughput API, erreurs
- **Alerting** : détection pannes, dégradations performance
- **Incident response** : runbooks, escalation, post-mortems
@@ -93,16 +94,19 @@ graph TB
### Métriques Clés
**API Performance** (requêtes PromQL) :
- Latency p99 : histogramme quantile 99e percentile sur durée requêtes HTTP (fenêtre 5 min)
- Error rate : ratio requêtes 5xx / total requêtes (fenêtre 5 min)
- Throughput : taux de requêtes par seconde (fenêtre 5 min)
**Infrastructure** :
- CPU usage : taux utilisation CPU (mode non-idle, fenêtre 5 min)
- Memory usage : ratio mémoire disponible / totale
- Disk I/O : temps I/O disque (fenêtre 5 min)
**Business** (compteurs custom) :
- Active users (DAU) : `roadwave_active_users_total`
- Audio streams actifs : `roadwave_hls_streams_active`
- Signalements modération : `roadwave_moderation_reports_total`
@@ -182,6 +186,7 @@ graph TB
### Dashboards Grafana
**Dashboard principal** :
- Latency p50/p95/p99 API (5 min, 1h, 24h)
- Error rate 5xx/4xx (seuil alerte >1%)
- Throughput requests/sec
@@ -189,12 +194,14 @@ graph TB
- Business : DAU, streams actifs, signalements modération
**Dashboard PostgreSQL** :
- Slow queries (>100ms)
- Connections actives vs max
- Cache hit ratio (cible >95%)
- Deadlocks count
**Dashboard Redis** :
- Memory usage
- Evictions count
- Commands/sec
@@ -203,27 +210,32 @@ graph TB
### Alerting Rules
**Alertes critiques** (Telegram + Email immédiat) :
- **API Down** : Job API indisponible pendant >1 min → Notification immédiate
- **High Error Rate** : Taux erreurs 5xx >1% pendant >5 min → Notification immédiate
- **Database Down** : PostgreSQL indisponible pendant >1 min → Notification immédiate
**Alertes warnings** (Email uniquement) :
- **High Latency** : Latency p99 >100ms pendant >10 min → Investigation requise
- **Disk Space Running Out** : Espace disque <10% pendant >30 min → Nettoyage requis
### Backup & Disaster Recovery
**PostgreSQL WAL-E** :
- Méthode : Backup continu Write-Ahead Log (WAL)
- Rétention : 7 jours full + WAL incrémentaux
- Stockage : S3 OVH région GRA (France)
- Chiffrement : AES-256 server-side
**RTO (Recovery Time Objective)** : 1h
- Restore depuis S3 : ~30 min (DB 10 GB)
- Validation + relance services : ~30 min
**RPO (Recovery Point Objective)** : 15 min
- Fréquence archivage WAL : toutes les 15 min
- Perte maximale : 15 min de transactions

View File

@@ -6,6 +6,7 @@
## Contexte
RoadWave manipule des données sensibles nécessitant une protection renforcée :
- **Secrets applicatifs** : JWT signing key, DB credentials, Mangopay API keys
- **PII utilisateurs** : Positions GPS précises, emails, données bancaires (via Mangopay)
- **Conformité** : RGPD (minimisation données, encryption at rest), PCI-DSS (paiements)
@@ -88,11 +89,13 @@ graph TB
3. Login root + activation KV-v2 engine (path : `roadwave/`)
**Secrets stockés** :
- **JWT signing key** : Paire RS256 privée/publique
- **Database credentials** : Host, port, user, password (généré aléatoire 32 caractères)
- **Mangopay API** : Client ID, API key, webhook secret
**Récupération depuis Backend Go** :
- Utilisation SDK `hashicorp/vault/api`
- Authentification via token Vault (variable env VAULT_TOKEN)
- Récupération secrets via KVv2 engine
@@ -100,28 +103,33 @@ graph TB
### Encryption PII (Field-level)
**Données chiffrées** (AES-256-GCM) :
- **GPS précis** : lat/lon conservés 24h puis réduits à geohash-5 (~5km²) ([Règle 02](../domains/_shared/rules/rgpd.md))
- **Email** : chiffré en base, déchiffré uniquement à l'envoi
- **Numéro téléphone** : si ajouté (Phase 2)
**Architecture encryption** :
- Utilisation bibliothèque standard Go `crypto/aes` avec mode GCM (AEAD)
- Master key 256 bits (32 bytes) récupérée depuis Vault
- Chiffrement : génération nonce aléatoire + seal GCM → encodage base64
- Stockage : colonne `email_encrypted` en base PostgreSQL
**Contraintes** :
- Index direct sur champ chiffré impossible
- Solution : index sur hash SHA-256 de l'email chiffré pour recherche
### HTTPS/TLS Configuration
**Let's Encrypt wildcard certificate** :
- Méthode : Certbot avec DNS-01 challenge (API OVH)
- Domaines couverts : `roadwave.fr` + `*.roadwave.fr` (wildcard)
- Renouvellement : automatique via cron quotidien (30j avant expiration)
**Nginx TLS configuration** :
- Protocol : TLS 1.3 uniquement (pas de TLS 1.2 ou inférieur)
- Ciphers : TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384
- HSTS : max-age 1 an, includeSubDomains
@@ -214,12 +222,14 @@ graph TB
### Rate Limiting (Protection DDoS/Brute-force)
**Configuration** :
- Middleware Fiber `limiter` avec backend Redis
- Limite : 100 requêtes par minute par IP (global)
- Clé de limitation : adresse IP client
- Réponse limitation : HTTP 429 "Too many requests"
**Rate limits par endpoint** :
- `/auth/login` : 5 req/min/IP (protection brute-force)
- `/moderation/report` : 10 req/24h/user (anti-spam)
- API générale : 100 req/min/IP
@@ -236,6 +246,7 @@ graph TB
| **Encryption master key** | Jamais (re-encryption massive) | Backup sécurisé uniquement |
**Process rotation DB credentials** :
- Vault génère automatiquement nouveau password
- Vault met à jour PostgreSQL avec nouveau password
- Application récupère nouveau password au prochain accès Vault

View File

@@ -103,10 +103,12 @@ Quelles autres options ont été évaluées ?
## Conséquences
### Positives
- Avantage 1
- Avantage 2
### Négatives
- Limitation 1
- Compromis accepté

View File

@@ -7,6 +7,7 @@
## Contexte
RoadWave est une app audio géolocalisée utilisée en conduite (CarPlay/Android Auto) avec :
- Contenu généré par utilisateurs (UGC)
- Monétisation : publicités géolocalisées + Premium (4.99€ web / 5.99€ IAP)
- GPS en arrière-plan
@@ -15,6 +16,7 @@ RoadWave est une app audio géolocalisée utilisée en conduite (CarPlay/Android
## Stratégie de conformité
**Approche multi-plateforme** avec :
- Modération UGC robuste (IA + humain)
- Prix différenciés selon région (US/EU/Monde)
- GPS avec disclosure complète
@@ -32,6 +34,7 @@ RoadWave est une app audio géolocalisée utilisée en conduite (CarPlay/Android
## Conformité détaillée
### Android Auto / CarPlay ✅
- 100% audio (pas de vidéo)
- Commandes standard au volant
- Aucun achat in-car
@@ -42,16 +45,19 @@ RoadWave est une app audio géolocalisée utilisée en conduite (CarPlay/Android
### Google Play ⚠️
**UGC (critique)** :
- Modération hybride IA + humain ✅
- 3 premiers contenus validés manuellement ✅
- Système de strikes (4 = ban) ✅
- Signalement + blocage utilisateurs ✅
**GPS Background (critique)** :
- Permission "Always Location" = **OPTIONNELLE**
- Demandée uniquement pour mode piéton (notifications arrière-plan audio-guides)
- Justification Play Console :
> "RoadWave permet aux utilisateurs de recevoir des alertes audio-guides lorsqu'ils passent à pied près de monuments/musées, même quand l'app est en arrière-plan. Cette fonctionnalité est optionnelle et peut être désactivée dans les paramètres."
- In-app disclosure obligatoire (écran dédié avant demande permission)
- Si refusée : app fonctionne en mode voiture uniquement
- **Action** : Remplir formulaire background location Play Console avec justification
@@ -68,19 +74,23 @@ RoadWave est une app audio géolocalisée utilisée en conduite (CarPlay/Android
### App Store ⚠️
**Prix différenciés (légaux depuis 2025-2026)** :
- 🇺🇸 US : Lien externe autorisé (0% commission)
- 🇪🇺 EU : Paiement externe DMA (7-20% commission réduite)
- 🌍 Monde : IAP obligatoire (30% commission)
**UGC** :
- Mode Kids obligatoire (filtrage selon âge) ✅
- Système de modération + signalement ✅
**GPS Background (critique)** :
- Permission "Always Location" = **OPTIONNELLE**
- Deux strings Info.plist requises :
- `NSLocationWhenInUseUsageDescription` : explication mode voiture
- `NSLocationAlwaysAndWhenInUseUsageDescription` : explication mode piéton (optionnel)
- In-app disclosure obligatoire avant demande "Always"
- Flux two-step : When In Use → Always (si user active mode piéton)
- Si refusée : app fonctionne en mode voiture uniquement
@@ -89,6 +99,7 @@ RoadWave est une app audio géolocalisée utilisée en conduite (CarPlay/Android
### Revenus créateurs
**Position** : Paiements créateurs = "services" (comme YouTube/Uber), pas IAP
- Paiement via Mangopay Connect (externe)
- Commission stores uniquement sur Premium (IAP)
- Comparables : YouTube AdSense, TikTok Creator Fund, Uber
@@ -110,12 +121,14 @@ RoadWave est une app audio géolocalisée utilisée en conduite (CarPlay/Android
## Stratégie de lancement
**Phase 1 - MVP** :
- IAP uniquement (5.99€/mois mondial)
- Modération UGC active
- GPS avec disclosure
- CarPlay/Android Auto basique
**Phase 2 - Post-validation** :
- Prix différenciés US (lien externe 4.99€)
- Paiement externe EU (DMA)
- Monétisation créateurs (Mangopay)

View File

@@ -200,13 +200,6 @@ domains/<domain>/
└── features/ # Tests BDD Gherkin (*.feature)
```
## Navigation
- *(structure legacy, déprécié)*
- [🏛️ ADR (Architecture Decision Records)](../adr/README.md)
- [⚖️ Documentation légale](../legal/README.md)
- [🔧 Documentation technique](../TECHNICAL.md)
## Ubiquitous Language Global
**Termes transversaux utilisés dans tous les domaines** :

View File

@@ -24,6 +24,7 @@ Le domaine **Shared** constitue le **Core Domain** de RoadWave. Il contient les
## Ubiquitous Language
**Termes métier du domaine partagé** :
- **User** : Utilisateur de la plateforme (auditeur, créateur, ou les deux)
- **Content** : Tout contenu audio diffusé sur la plateforme
- **Subscription** : Abonnement d'un utilisateur à un créateur ou une catégorie

View File

@@ -25,6 +25,7 @@ erDiagram
## 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
@@ -36,5 +37,6 @@ erDiagram
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é"`)

View File

@@ -36,16 +36,19 @@ erDiagram
## 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"]`

View File

@@ -23,17 +23,20 @@ erDiagram
## Légende
**Types de consentement** :
- `geolocation_precise` : Géolocalisation GPS précise (obligatoire pour contenu hyperlocal)
- `analytics` : Analytics Matomo (optionnel)
- `push_notifications` : Notifications push (optionnel)
- `cookies_analytics` : Cookies analytiques (optionnel)
**Versioning** :
- Chaque changement de CGU/politique = nouvelle version
- Historique complet conservé (preuve légale)
- Format version : `v1.0`, `v2.0`, etc.
**Conformité RGPD** :
- Granularité : fonctionnel / analytique / marketing
- Consentement libre et éclairé
- Révocable à tout moment

View File

@@ -21,11 +21,13 @@ erDiagram
## 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

View File

@@ -29,17 +29,20 @@ erDiagram
## Légende
**Types d'appareil** :
- `mobile` : Smartphone Android/iOS
- `tablet` : Tablette
- `desktop` : Ordinateur
- `car` : Système embarqué (CarPlay/Android Auto)
**Appareil de confiance** :
- Option "Ne plus demander sur cet appareil" → bypass 2FA pendant **30 jours**
- Révocable depuis paramètres compte
- Liste des appareils de confiance visible
**Sécurité** :
- Détection automatique nouveau device → notification push + email
- Localisation suspecte (pays différent) → alerte
- Révocation individuelle ou globale possible

View File

@@ -25,11 +25,13 @@ erDiagram
## Légende
**Formats d'export** :
- `json` : Machine-readable (données brutes)
- `html` : Human-readable (page web stylée)
- `zip` : Archive complète (JSON + HTML + audio files)
**Contenu de l'export** :
- Profil utilisateur (email, pseudo, date inscription, bio)
- Historique d'écoute (titres, dates, durées)
- Contenus créés (audio + métadonnées)
@@ -38,6 +40,7 @@ erDiagram
- Historique consentements RGPD
**Statuts** :
- `pending` : Demande en file d'attente
- `generating` : Génération en cours (worker background)
- `ready` : Export disponible au téléchargement
@@ -45,6 +48,7 @@ erDiagram
- `expired` : Export expiré (supprimé automatiquement)
**Règles** :
- Génération asynchrone (worker background)
- Délai max : **48h** (conformité RGPD)
- Conservation : **7 jours** après génération

View File

@@ -21,6 +21,7 @@ erDiagram
## Légende
**Catégories** :
- `automobile` : Voitures, mécanique, course automobile
- `travel` : Voyages, tourisme, découverte
- `music` : Musique, concerts, artistes
@@ -33,12 +34,14 @@ erDiagram
- `nature` : Nature, randonnée, écologie
**Score** :
- Échelle : **0-100**
- Augmentation : +2% par like, +5% par abonnement créateur
- Diminution : -1% par skip rapide (<30s), -5% par signalement
- Calcul combiné : Distance GPS + matching intérêts
**Algorithme recommandation** :
- **70% géolocalisation** : Proximité GPS
- **30% centres d'intérêt** : Score jauges
- Boost si créateur suivi : +0.3 au score final

View File

@@ -25,23 +25,27 @@ erDiagram
## Légende
**Anonymisation progressive** :
- Données précises conservées **24h** (recommandation personnalisée)
- Après 24h : conversion en **geohash précision 5** (~5km²)
- Coordonnées originales supprimées définitivement
- Job quotidien PostGIS automatique
**Exceptions** :
- Historique personnel visible (liste trajets) : conservation intégrale tant que compte actif
- Analytics globales : uniquement geohash anonyme
- Suppression complète si suppression du compte
**Contexte** :
- `listening` : Position pendant écoute de contenu
- `search` : Position lors d'une recherche
- `background` : Tracking en arrière-plan
- `manual` : Position partagée manuellement
**Conformité RGPD** :
- Vraie anonymisation (CNIL compliant)
- Permet analytics agrégées (heatmaps trafic)
- PostGIS natif, 0€

View File

@@ -43,6 +43,7 @@ erDiagram
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`

View File

@@ -32,10 +32,12 @@ erDiagram
## 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)

View File

@@ -29,6 +29,7 @@ erDiagram
## Légende
**Catégories de signalement** :
- `spam` : Contenu publicitaire non sollicité
- `hate_speech` : Discours haineux, discrimination
- `violence` : Violence explicite
@@ -39,6 +40,7 @@ erDiagram
- `other` : Autre raison (commentaire obligatoire)
**Statuts** :
- `pending` : En attente de revue
- `under_review` : En cours d'examen par modérateur
- `actioned` : Action prise (contenu retiré/édité)
@@ -46,6 +48,7 @@ erDiagram
- `duplicate` : Doublon d'un signalement existant
**Actions possibles** :
- `content_removed` : Contenu supprimé
- `content_edited` : Métadonnées modifiées (âge, tags)
- `warning_sent` : Avertissement au créateur
@@ -54,6 +57,7 @@ erDiagram
- `no_action` : Aucune action (signalement infondé)
**Workflow modération** :
- **3 premiers contenus** : Modération préalable obligatoire
- **Après validation** : Modération a posteriori (signalements)
- **Priorisation** : Nombre de signalements (>3 = urgent)

View File

@@ -30,16 +30,19 @@ erDiagram
## Légende
**Durées de vie** :
- Access token : **15 minutes**
- Refresh token : **30 jours** (rotatif)
- Inactivité : Déconnexion automatique après **30 jours**
**Sécurité** :
- Tokens stockés en **SHA256** (jamais en clair)
- Rotation automatique des refresh tokens
- Détection replay attack
**Multi-device** :
- Sessions simultanées **illimitées**
- Révocation individuelle ou globale possible
- Alertes si connexion depuis nouveau device ou pays différent

View File

@@ -23,16 +23,19 @@ erDiagram
## 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

View File

@@ -19,6 +19,7 @@
### Contexte du report
**Raisons** :
- **Coût modération** : Classification manuelle humaine très coûteuse (~2000€/mois pour 1-2 modérateurs senior full-time)
- **Risque juridique** : Accusations de biais éditorial, contentieux DSA
- **Complexité technique** : Dashboard audit, logs 3 ans, alertes déséquilibre
@@ -26,6 +27,7 @@
- **Pas essentiel MVP** : L'application fonctionne sans ce système
**Version MVP** (actuelle) :
- Tag "Politique" simple (comme "Économie", "Sport")
- Pas de classification gauche/droite
- Pas d'équilibrage imposé
@@ -36,6 +38,7 @@
### Spécifications complètes (future implémentation)
**Échelle de classification** (5 niveaux) :
- 🔴 **Extrême gauche** (anticapitalisme radical, révolution)
- 🟠 **Gauche** (écologie, social, critique capitalisme modérée)
-**Centre/Neutre** (pas de positionnement politique clair)
@@ -44,11 +47,13 @@
- 🟢 **Non politique** (enfants, musique, fiction, culture générale)
**Qui classifie** :
- ❌ Pas de classification automatique IA (outil informatif uniquement, jamais décisionnaire)
- ✅ Modérateurs senior après transcription
- ✅ Créateur peut contester via processus d'appel
**Affichage** :
- Badge politique visible : **au choix de l'utilisateur** (paramètre "Afficher orientation politique")
- Par défaut : badges masqués (UX neutre)
@@ -62,17 +67,20 @@
| **Masquer politique** | 0% gauche / 0% droite / 100% centre-neutre + non politique | Option apolitique |
**Audit et conformité DSA** :
- Rapport hebdomadaire automatique : % gauche/droite/centre diffusé par utilisateur
- Alerte si déséquilibre global plateforme (>55% d'un bord)
- Logs conservés **3 ans** (exigence Digital Services Act EU)
- Dashboard admin : visualisation répartition temps réel
**Sanctions mauvaise classification** :
- Classification volontairement incorrecte = Strike 1
- Récidive = Strike 2 (suspension 7j)
- Détection via signalements utilisateurs + audit modération
**Justification** :
- **Conformité juridique DSA** (obligation neutralité plateforme EU)
- Protection contre accusations de biais éditorial
- Transparence auditable
@@ -90,6 +98,7 @@
5. Validation juridique du processus de classification
**Chronologie estimée** :
- Phase 1 (Post-MVP+3 mois) : Validation demande utilisateurs via sondages
- Phase 2 (Post-MVP+6 mois) : Recrutement modérateurs + développement dashboard
- Phase 3 (Post-MVP+9 mois) : Tests bêta avec utilisateurs volontaires
@@ -104,12 +113,14 @@
### Contexte du report
**Raisons** :
- **Complexité technique** : Intégration Lightning Network, gestion wallets crypto
- **Réglementation** : Incertitude juridique crypto en EU (MiCA 2025)
- **Focus MVP** : Priorité sur monétisation via abonnements Premium et publicités
- **Adoption utilisateurs** : Nécessite éducation et adoption crypto préalables
**Version MVP** (actuelle) :
- Monétisation créateurs via :
- Partage revenus publicités (3€ CPM)
- 70% revenus abonnements Premium
@@ -128,6 +139,7 @@
5. Conversion EUR/BTC automatique (optionnelle)
**Avantages Lightning Network** :
- ✅ Frais quasi-nuls (<1%) vs 1.8% Mangopay
- ✅ Transactions instantanées (<1 seconde)
- ✅ Micropaiements possibles (dès 0.01€)
@@ -135,12 +147,14 @@
- ✅ Pas d'intermédiaire (peer-to-peer)
**Contraintes** :
- ❌ Adoption crypto limitée (2-5% population EU en 2026)
- ❌ Volatilité BTC (nécessite conversion EUR immédiate)
- ❌ UX complexe pour utilisateurs non-crypto
- ❌ Réglementation MiCA en évolution
**Alternatives étudiées** :
- Ko-fi / Buy Me a Coffee : simple mais frais 5%
- PayPal/Stripe : frais 2.9% + 0.30€ (non viable pour micropaiements)
- Mangopay : déjà utilisé, mais frais élevés pour petits montants
@@ -157,6 +171,7 @@
5. Demande créateurs confirmée via sondages
**Chronologie estimée** :
- Phase 1 (Post-MVP+6 mois) : Étude de marché et demande utilisateurs
- Phase 2 (Post-MVP+12 mois) : Développement intégration Lightning
- Phase 3 (Post-MVP+15 mois) : Tests bêta avec créateurs volontaires
@@ -171,6 +186,7 @@
### Contexte du report
**Raisons** :
- **Masse critique requise** : Nécessite pool suffisant d'utilisateurs simultanés (>500) pour matching rapide (<30s)
- **Infrastructure WebRTC** : Coût serveurs TURN/STUN supplémentaire (~500€/mois pour 1000 utilisateurs actifs)
- **Complexité modération** : Contenu live non enregistré = risques abus, nécessite système de confiance et signalement robuste
@@ -178,6 +194,7 @@
- **UX conducteur** : Commandes vocales avancées nécessaires pour sécurité routière
**Version MVP** (actuelle) :
- Radio live créateurs uniquement (1 vers N)
- Pas de connexion P2P entre auditeurs
- Chat textuel limité aux POIs et commentaires
@@ -220,12 +237,14 @@
- Badge "En roulette" visible sur profil (transparence)
**Avantages** :
- ✅ Sérendipité et découverte (esprit "Chatroulette audio")
- ✅ Complémentarité conducteur/piéton (récit route vs récit urbain)
- ✅ Fidèle concept RoadWave (usagers de la route connectés)
- ✅ Réutilisation infrastructure WebRTC existante (radio live)
**Contraintes** :
- ❌ Nécessite pool minimum 500 utilisateurs actifs simultanés
- ❌ Modération temps réel complexe (contenu éphémère)
- ❌ Coût infrastructure TURN/STUN significatif
@@ -233,10 +252,12 @@
- ❌ Commandes vocales avancées requises pour conducteurs
**Monétisation** :
- Gratuit avec limitation : 3 sessions/jour de 5 min
- Premium : sessions illimitées + matching prioritaire (moins d'attente)
**Aspects légaux** :
- Âge minimum : 18 ans pour accès roulette
- Charte d'utilisation spécifique (respect, pas de contenu sexuel/violent, pas de sollicitation commerciale)
- Anonymat relatif : pseudo + ville visible, pas de photo
@@ -254,12 +275,14 @@
6. Commandes vocales avancées implémentées pour conducteurs
**Chronologie estimée** :
- Phase 1 (Post-MVP+3 mois) : Validation demande utilisateurs via sondages, analyse concurrence (Clubhouse, Twitter Spaces)
- Phase 2 (Post-MVP+6 mois) : Développement matchmaking + WebRTC P2P renforcé
- Phase 3 (Post-MVP+9 mois) : Tests bêta avec 100 utilisateurs volontaires
- Phase 4 (Post-MVP+12 mois) : Déploiement progressif si KPI positifs (>70% satisfaction, <5% signalements)
**KPI de succès** :
- Temps moyen d'attente matching : <30 secondes
- Taux satisfaction post-session : >70%
- Taux signalement : <5%
@@ -275,12 +298,14 @@
### Contexte du report
**Raisons** :
- **Coût SMS** : ~0.04€/SMS en France via Brevo (400€/mois pour 10K inscriptions)
- **Complexité UX** : Étape supplémentaire à l'inscription (friction)
- **Focus MVP** : Priorité sur l'expérience utilisateur fluide
- **Modération suffisante** : Système de strikes et signalements couvre les cas d'abus initiaux
**Version MVP** (actuelle) :
- Inscription par email uniquement (via Zitadel)
- Confirmation email obligatoire
- Détection basique emails jetables (liste noire publique)
@@ -321,28 +346,33 @@
- Au-delà → signalement automatique modération
**Affichage** :
- Badge "Vérifié ✓" visible sur profil créateur
- Non obligatoire pour auditeurs simples (seulement créateurs)
- Option "Vérifier mon compte" dans paramètres
**Règles de diffusion** :
- Contenus créateurs non-vérifiés : portée limitée à 10 km pendant 30 premiers jours
- Après 30 jours sans signalement : levée restriction
- Créateurs vérifiés : aucune restriction
**Avantages** :
- ✅ Réduction spam et comptes multiples
- ✅ Amélioration confiance plateforme
- ✅ Conformité anti-fraude (KYC léger)
- ✅ Réutilisation infrastructure Brevo (emails + SMS)
**Contraintes** :
- ❌ Coût SMS : ~400€/mois pour 10K inscriptions/mois
- ❌ Friction UX (étape supplémentaire)
- ❌ Numéros virtuels (Twilio, etc.) contournent vérification
- ❌ Certains utilisateurs réticents (vie privée)
**Alternatives étudiées** :
- **Captcha reCAPTCHA v3** : efficace mais contournable, pas de coût
- **Email reputation API** : ~0.01€/vérification (kickbox.io)
- **Vérification bancaire** : trop contraignant pour MVP
@@ -359,12 +389,14 @@
5. Conformité RGPD : consentement stockage numéro mobile
**Chronologie estimée** :
- Phase 1 (Post-MVP+3 mois) : Analyse taux spam/abus, validation besoin
- Phase 2 (Post-MVP+4 mois) : Développement détection emails temporaires + API Brevo SMS
- Phase 3 (Post-MVP+5 mois) : Tests bêta avec créateurs volontaires
- Phase 4 (Post-MVP+6 mois) : Déploiement progressif selon catégorie utilisateur (créateurs en priorité)
**KPI de succès** :
- Réduction comptes spam : >50%
- Taux vérification volontaire (créateurs) : >70%
- Friction UX acceptable : taux abandon inscription <10%
@@ -379,6 +411,7 @@
### Contexte du report
**Raisons** :
- **Complexité technique** : Intégration API TTS (Text-to-Speech), OCR pour PDF scannés, parsing multi-formats
- **Coût infrastructure** : ~0.016€/1000 caractères (Google Cloud TTS) = ~1.60€ par livre moyen (100K caractères)
- **Conformité droits d'auteur** : Risque juridique si conversion de contenus protégés sans licence
@@ -386,6 +419,7 @@
- **Usage limité** : Cas d'usage minoritaire vs contenu audio créé par la communauté
**Version MVP** (actuelle) :
- Contenu audio uniquement créé par les créateurs
- Pas de conversion automatique document → audio
- Utilisateurs doivent uploader directement fichiers audio
@@ -452,12 +486,14 @@
| **Allemand** | Anna, Max | Google Cloud TTS WaveNet |
**Avantages** :
- ✅ Différenciation Premium forte (feature exclusive)
- ✅ Fidélisation utilisateurs (consommation contenu personnel)
- ✅ Réutilisation infrastructure audio existante (HLS, NGINX Cache)
- ✅ Cas d'usage trajets longs (livres, articles longs)
**Contraintes** :
- ❌ Coût TTS : ~1.60€/livre moyen (Google Cloud TTS WaveNet)
- ❌ Coût stockage : ~0.01€/GB/mois (temporaire 90 jours)
- ❌ Risque juridique : conversion contenus protégés (livres, articles premium)
@@ -502,12 +538,14 @@
5. Infrastructure existante stable (HLS, CDN, backend Go)
**Chronologie estimée** :
- Phase 1 (Post-MVP+6 mois) : Étude de marché, sondage utilisateurs Premium, validation juridique
- Phase 2 (Post-MVP+9 mois) : Développement MVP TTS (PDF texte uniquement, FR/EN)
- Phase 3 (Post-MVP+10 mois) : Tests bêta avec 100 utilisateurs Premium volontaires
- Phase 4 (Post-MVP+12 mois) : Déploiement progressif si KPI positifs + ajout formats (EPUB, OCR)
**KPI de succès** :
- Adoption feature : >30% utilisateurs Premium l'utilisent au moins 1 fois/mois
- Satisfaction : >75% note positive (4-5/5)
- Rétention Premium : augmentation >10% grâce à cette feature
@@ -525,6 +563,7 @@
| **Total** | **~650€/mois** |
**Rentabilité** :
- Revenus Premium 1000 users : 4990€/mois (4.99€/mois × 1000)
- Coût TTS : 650€/mois (13% revenus)
- Marge après TTS : 4340€/mois (87%)
@@ -539,6 +578,7 @@
### Contexte du report
**Raisons** :
- **Couverture limitée** : ~30-40% du parc automobile EU en 2026 (CarPlay/Android Auto)
- **Complexité technique** : Intégration Siri Intents (iOS) + Google Actions (Android)
- **Modération vocale** : Signalements vocaux nécessitent enregistrement + transcription audio
@@ -546,6 +586,7 @@
- **Accessibilité secondaire** : Like automatique couvre déjà engagement conducteurs
**Version MVP** (actuelle) :
- ❌ Pas de commandes vocales
- ✅ Like automatique basé sur temps d'écoute (en voiture)
- ✅ Actions manuelles disponibles seulement en mode piéton
@@ -591,6 +632,7 @@
**Implémentation technique** :
**iOS** :
- Siri Intents (framework iOS 12+)
- Clés Intent à ajouter dans `Info.plist` :
```xml
@@ -602,25 +644,30 @@
</dict>
</array>
```
- Paramètres vocaux : détection "like", "abonne", "signale"
**Android** :
- Google Actions on Google Assistant (via assistant voice queries)
- Intégration avec Android App Actions
- Paremeters: Intent extras pour passer contenu actuel
- Fallback : repérer contenu par titre + créateur
**Limitation importante** :
- ⚠️ **CarPlay/Android Auto requis** : Fonctionalité non disponible sur interface mobile
- ⚠️ **Reconnaissance vocale réseau** : Nécessite connexion data
- ⚠️ **Latence acceptable** : <2 secondes entre commande et confirmation
**UX - Feedback utilisateur** :
- Siri : "✓ J'ai ajouté ce contenu à vos favoris"
- Google Assistant : "✓ Vous êtes maintenant abonné à [Créateur]"
- Confirmation audio pour signalement : "Signalement envoyé. Catégorie : Spam"
**Signalements vocaux** :
- Enregistrement automatique de la voix (tampon 30 secondes)
- Transcription audio → texte (via Google Cloud Speech ou similaire)
- Catégorie pré-remplie selon réponse vocale ("Spam" → catégorie Spam)
@@ -638,12 +685,14 @@
5. Système de confiance utilisateur en place (éviter abus signalements)
**Chronologie estimée** :
- Phase 1 (Post-MVP+2 mois) : Validation demande utilisateurs (CarPlay/Android Auto)
- Phase 2 (Post-MVP+4 mois) : Développement Siri Intents + Google Actions
- Phase 3 (Post-MVP+6 mois) : Tests bêta avec conducteurs volontaires
- Phase 4 (Post-MVP+8 mois) : Déploiement progressif si KPI positifs
**KPI de succès** :
- Adoption commandes vocales : >30% utilisateurs CarPlay/Android Auto
- Taux erreur reconnaissance vocale : <10%
- Satisfaction utilisateurs : >75% (4-5/5)
@@ -667,6 +716,7 @@
### Contexte du report
**Raisons** :
- **Masse critique requise** : Partenariats avec organismes officiels nécessitent base utilisateurs solide (>50K MAU)
- **Complexité technique** : Intégration APIs externes, système de priorités, TTS automatisé
- **Responsabilité légale** : Diffusion alertes sécurité = engagement fort, nécessite infrastructure stable
@@ -674,6 +724,7 @@
- **ROI incertain** : Valeur ajoutée forte mais sans revenus directs (service public)
**Version MVP** (actuelle) :
- Tous contenus = créateurs classiques
- Pas de système de priorité
- Pas de comptes officiels vérifiés
@@ -696,6 +747,7 @@
| **Compte Officiel** | Validation RoadWave manuelle + contrat partenariat | 🏛️ | **Configurable (0-3)** | **Aucune** |
**Exemples comptes officiels** :
- **Gestionnaires autoroutes** : SANEF, Vinci Autoroutes, APRR, ASF
- **Services météo** : Météo France, vigilance.gouv.fr
- **Sécurité civile** : Préfectures, Plan alerte enlèvement
@@ -796,6 +848,7 @@ Podcast reprend automatiquement à position exacte
```
**Paramètres techniques** :
- **Rayon déclenchement** : 500m-2km selon vitesse (calcul dynamique)
- **Son d'alerte** : Bip distinctif (pas agressif, mais audible)
- **Durée max alerte** : 30 secondes (format court, info essentielle)
@@ -803,6 +856,7 @@ Podcast reprend automatiquement à position exacte
- **Annulation** : bouton "Ignorer" disponible pendant countdown (mais déconseillé)
**Traçabilité** :
- Log : `user_id`, `alert_id`, `action` (played / ignored), `timestamp`
- Statistiques : taux d'écoute alertes vs taux ignore (KPI efficacité)
@@ -855,12 +909,14 @@ Podcast reprend automatiquement à position exacte
```
**TTS (Text-to-Speech)** :
- **Fournisseur** : Google Cloud TTS WaveNet (voix neurale professionnelle)
- **Coût** : ~0.016€/1000 caractères
- **Voix** : "Léa" (féminine, française, ton calme mais ferme pour alertes)
- **Normalisation audio** : -14 LUFS (comme autres contenus)
**Expiration automatique** :
- Alertes météo : 12h après fin vigilance
- Obstacles autoroute : 2h après signalement (si non mis à jour)
- Alertes enlèvement : 48h ou jusqu'à résolution officielle
@@ -909,6 +965,7 @@ Podcast reprend automatiquement à position exacte
```
**Création alerte manuelle** :
- Use case : information non automatisée (événement exceptionnel)
- Champs : Texte (TTS auto), Zone (carte), Priorité (1-3), Durée vie
- Validation admin RoadWave requise (pas auto-publication)
@@ -943,6 +1000,7 @@ Podcast reprend automatiquement à position exacte
5. Tests A/B réussis sur interruption priorité 3 (acceptabilité utilisateurs)
**Chronologie estimée** :
- Phase 1 (Post-MVP+6 mois) : Développement système priorités + dashboard admin + TTS
- Phase 2 (Post-MVP+9 mois) : Premier partenariat (Météo France, API publique simple)
- Phase 3 (Post-MVP+12 mois) : Tests bêta alertes météo avec utilisateurs volontaires
@@ -950,6 +1008,7 @@ Podcast reprend automatiquement à position exacte
- Phase 5 (Post-MVP+18 mois) : Déploiement complet si KPI positifs
**KPI de succès** :
- Taux écoute alertes priorité 3 : >95% (faible taux ignore)
- Satisfaction utilisateurs : >80% jugent alertes utiles (sondage post-alerte)
- Taux faux positifs : <2% (alerte diffusée à tort ou obsolète)
@@ -968,6 +1027,7 @@ Podcast reprend automatiquement à position exacte
| **Total** | **~255€/mois** |
**ROI** :
- Pas de revenus directs (service public)
- Valeur indirecte : **différenciation produit majeure**
- Argument commercial : "RoadWave vous protège en temps réel"

View File

@@ -10,11 +10,13 @@
- ✅ Option "Appareil de confiance" (skip 2FA pour 30 jours)
**Clarification technique** :
- Zitadel utilise OAuth2/OIDC comme **protocole** (standard moderne pour mobile)
- Mais l'authentification reste 100% **email/password natif**
- **Aucun fournisseur externe** (Google, Apple, etc.) n'est intégré
**Justification** :
- Souveraineté : pas de dépendance externe
- RGPD : données 100% contrôlées
- Coût : 0€ (Zitadel intégré)
@@ -35,11 +37,13 @@
| **Email vérifié** | Toutes fonctionnalités débloquées |
**Paramètres** :
- Lien de vérification expire après **7 jours**
- Possibilité de renvoyer le lien (max 3 fois/jour)
- Rappel in-app après création du 3ème contenu
**Justification** :
- Friction minimale à l'inscription
- Anti-spam sans bloquer l'essai du produit
- Incitation naturelle à vérifier (déblocage)
@@ -47,11 +51,13 @@
#### Pour les créateurs (monétisation)
**Vérification obligatoire sous 7 jours** pour :
- Accès au programme de monétisation
- KYC et reversement des revenus (conformité Mangopay)
- Publication illimitée de contenus
**Justification** :
- **Conformité légale** : KYC obligatoire pour transferts financiers
- **Anti-fraude** : Vérification identité réelle pour paiements
- **Responsabilité** : RoadWave doit pouvoir prouver identité créateurs monétisés
@@ -61,22 +67,26 @@
### 1.3 Données requises à l'inscription
**Obligatoires** :
- ✅ Email (format validé)
- ✅ Mot de passe (voir règles ci-dessous)
- ✅ Pseudo (3-30 caractères, alphanumérique + underscore)
- ✅ Date de naissance (vérification âge minimum)
**Optionnelles** :
- ❌ Nom complet (privacy by design)
- ❌ Photo de profil (avatar par défaut généré)
- ❌ Bio (ajout ultérieur)
**Âge minimum** :
- **13 ans minimum** (conformité réglementation réseaux sociaux EU)
- Vérification à l'inscription via date de naissance
- Blocage inscription si <13 ans avec message explicite
**Justification** :
- RGPD minimal data
- Friction réduite (4 champs max)
- Protection mineurs (obligation légale)
@@ -88,22 +98,26 @@
**Décision** : Classification obligatoire des contenus
**Catégories** :
- 🟢 **Tout public** (défaut)
- 🟡 **13+** : contenu mature léger (débats, actualité sensible)
- 🟠 **16+** : contenu mature (violence verbale, sujets sensibles)
- 🔴 **18+** : contenu adulte (langage explicite, sujets réservés)
**Règles de diffusion** :
- Utilisateur 13-15 ans → contenus 🟢 🟡 (Tout public + 13+)
- Utilisateur 16-17 ans → contenus 🟢 🟡 🟠 (Tout public + 13+ + 16+)
- Utilisateur 18+ → tous contenus 🟢 🟡 🟠 🔴
**Modération** :
- Vérification obligatoire de la classification lors de la validation
- Reclassification possible par modérateurs
- Strike si classification volontairement incorrecte
**Justification** :
- Protection mineurs (obligation légale)
- Responsabilité plateforme
- Coût : champ supplémentaire + règle algo
@@ -113,17 +127,20 @@
### 1.5 Validation mot de passe
**Règles** :
- ✅ Minimum **8 caractères**
- ✅ Au moins **1 majuscule**
- ✅ Au moins **1 chiffre**
- ❌ Pas de symbole obligatoire (simplicité)
**Validation** :
- Côté client (feedback temps réel)
- Côté backend (sécurité)
- Message d'erreur explicite par règle non respectée
**Justification** :
- Standard industrie
- Bloque 95% des mots de passe faibles
- UX acceptable (pas trop restrictif)
@@ -135,16 +152,19 @@
**Décision** : Optionnel mais recommandé
**Méthodes disponibles** :
- ✅ TOTP (Time-based One-Time Password) via app (Google Authenticator, Authy)
- ✅ Email (code 6 chiffres, expire 10 min)
- ❌ SMS (coût élevé ~0.05€/SMS)
**Appareil de confiance** :
- Option "Ne plus demander sur cet appareil" → bypass 2FA pendant **30 jours**
- Révocable depuis paramètres compte
- Liste des appareils de confiance visible
**Justification** :
- Sécurité renforcée sans coût SMS
- UX : appareil de confiance évite friction quotidienne
- Zitadel natif (0€)
@@ -154,16 +174,19 @@
### 1.7 Tentatives de connexion
**Règles** :
- Maximum **5 tentatives** par période de **15 minutes**
- Blocage temporaire après 5 échecs
- Compteur reset automatique après 15 min
- Notification email si blocage (tentative suspecte)
**Déblocage** :
- Automatique après 15 min
- Ou via lien "Mot de passe oublié"
**Justification** :
- Anti brute-force
- Standard industrie (équilibre sécurité/UX)
- Zitadel natif (0€)
@@ -173,19 +196,23 @@
### 1.8 Sessions et refresh tokens
**Durée de vie** :
- **Access token** : 15 minutes
- **Refresh token** : 30 jours
**Rotation** :
- Refresh token rotatif (nouveau token à chaque refresh)
- Ancien token invalidé immédiatement
- Détection token replay attack
**Extension automatique** :
- Si app utilisée, session prolongée automatiquement
- Inactivité 30 jours → déconnexion
**Justification** :
- Sécurité (token court-vie)
- UX (pas de reconnexion fréquente)
- Standard OAuth2/OIDC
@@ -197,15 +224,18 @@
**Décision** : Sessions simultanées illimitées
**Gestion** :
- Liste des devices connectés visible (OS, navigateur, dernière connexion, IP/ville)
- Révocation individuelle possible
- Révocation globale "Déconnecter tous les appareils"
**Alertes** :
- Notification push + email si connexion depuis nouveau device
- Détection localisation suspecte (IP pays différent)
**Justification** :
- UX maximale (écoute voiture + tablette maison + web)
- Sécurité via transparence (utilisateur voit tout)
- Coût : table sessions PostgreSQL
@@ -224,13 +254,16 @@
5. Confirmation + déconnexion tous devices (sauf celui en cours)
**Notifications** :
- Email immédiat si changement mot de passe
- Push si changement depuis appareil non reconnu
**Limite** :
- Maximum **3 demandes/heure** (anti-spam)
**Justification** :
- Standard sécurité
- Pas de coût SMS
- Protection contre attaque sociale

View File

@@ -23,6 +23,7 @@
| **Contenu national** | "Aucun contenu local disponible. Voici du contenu national qui pourrait vous intéresser" |
**Justification** :
- **UX fluide** : pas de message d'erreur bloquant "Aucun contenu"
- **User ne reste jamais sans contenu**
- **Contenu national = filet de sécurité** : actualités Le Monde, podcasts génériques
@@ -44,10 +45,12 @@
```
**Si tentative "Précédent" manuellement** :
- Message : "Ce contenu n'est plus disponible"
- Retour au contenu actuel
**Justification** :
- **Sécurité routière** : pas d'interruption brutale pendant conduite
- **User informé mais pas alarmé** : message discret
- **Empêche réécoute** : contenu modéré inaccessible
@@ -67,30 +70,36 @@
**Comportement détaillé** :
**Phase 1 : Connexion instable** (latence élevée, paquets perdus)
- Aucun message immédiat
- Lecture continue sur buffer
- Si > 10s latence : toast discret "Connexion instable"
**Phase 2 : Perte totale réseau**
- Lecture continue jusqu'à épuisement buffer
- Toast : "Hors ligne, lecture sur buffer (30s restantes)"
- Compte à rebours visible
**Phase 3 : Buffer épuisé sans reconnexion**
- Pause automatique
- Overlay : "Connexion perdue. Reconnexion en cours..."
- Retry automatique toutes les 5s (max 6 tentatives = 30s)
**Phase 4 : Basculement mode offline** (après 30s échec)
- Popup : "Voulez-vous continuer avec vos contenus téléchargés ?"
- Boutons : "Réessayer" / "Mode offline"
- Si "Mode offline" → lecture contenus téléchargés
**Reconnexion réussie** :
- Reprise automatique lecture au point d'arrêt exact
- Toast : "Connexion rétablie"
**Justification** :
- **Expérience fluide zones blanches** (tunnels, campagne)
- **Buffer généreux** : absorbe fluctuations réseau mobile
- **Mode offline secours** : si coupure prolongée
@@ -113,19 +122,23 @@
| **Notifications push géo-déclenchées** | ❌ |
**Popup au lancement** :
- **Apparition** : Premier lancement après refus géolocalisation
- **Message** : "RoadWave fonctionne mieux avec la géolocalisation activée. Sans elle, seul le contenu national sera disponible."
- **Boutons** :
- "Activer" → Redirection paramètres OS
- "Continuer sans" → Mode dégradé
- **Checkbox** : "Ne plus me demander"
**Banner permanent si refus** :
- Bandeau haut écran : "Mode limité : géolocalisation désactivée. [Activer]"
- Pas intrusif mais rappel constant
- Disparaît si géolocalisation réactivée
**Justification** :
- **App reste fonctionnelle** sans GPS (pas de blocage)
- **Incitation forte** à activer (meilleure UX)
- **Respecte choix user** (RGPD : consentement libre)

View File

@@ -5,21 +5,25 @@
**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
@@ -37,10 +41,12 @@
4. Job quotidien automatique via cron
**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€
@@ -54,6 +60,7 @@
**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)
- Historique d'écoute (titres, dates, durées)
- Contenus créés (audio + métadonnées)
@@ -68,9 +75,11 @@
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
@@ -89,6 +98,7 @@
5. Après 30j sans annulation : suppression effective
**Suppression effective** :
- ✅ Compte utilisateur supprimé (données personnelles)
- ✅ Historique d'écoute supprimé
- ✅ GPS historique supprimé
@@ -97,11 +107,13 @@
- ⚠️ 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
@@ -121,16 +133,19 @@
| **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** :
- IP2Location Lite (gratuit, self-hosted, voir [ADR-019](../../../adr/019-geolocalisation-ip.md))
- 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)
@@ -150,15 +165,18 @@
| **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
@@ -178,17 +196,20 @@
| `_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
@@ -200,10 +221,12 @@
**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)
@@ -212,14 +235,17 @@
- 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€
@@ -240,6 +266,7 @@
| 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
@@ -248,10 +275,12 @@
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
@@ -263,25 +292,30 @@
**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é
@@ -293,6 +327,7 @@
**Décision** : Interface self-service + validation immédiate
**Données rectifiables** :
- Email (avec re-vérification)
- Pseudo (unique, disponibilité vérifiée)
- Bio / description
@@ -300,11 +335,13 @@
- 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€
@@ -323,6 +360,7 @@
| **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é
@@ -336,6 +374,7 @@
**Décision** : "Geler mon compte" temporaire
**Effets** :
- Compte gelé, contenus cachés, profil invisible
- Connexion lecture seule OK
- Réactivation à tout moment
@@ -349,6 +388,7 @@
**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)
@@ -450,6 +490,7 @@
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
@@ -458,6 +499,7 @@
- ⚠️ 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
@@ -466,6 +508,7 @@
- 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)
@@ -475,6 +518,7 @@
**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
@@ -484,6 +528,7 @@
- ✅ Contrôle parental obligatoire
**Contenus autorisés** :
- Contes audio enfants
- Guides touristiques famille
- Podcasts éducatifs labellisés
@@ -496,17 +541,20 @@
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)
@@ -537,6 +585,7 @@
**Décision** : DPIA obligatoire (GPS + profilage grande échelle)
**Raisons** :
- Traitement grande échelle données GPS sensibles
- Profilage automatisé recommandations
- Surveillance zones publiques

View File

@@ -49,6 +49,7 @@ sequenceDiagram
```
**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

View File

@@ -29,14 +29,17 @@ sequenceDiagram
## Légende
**Acteurs** :
- Zitadel : Gère l'authentification OAuth2/OIDC
- Backend API : Valide les tokens et accède aux données
**Tokens** :
- Access token : 15 min (JWT), utilisé pour chaque requête API
- Refresh token : 30 jours, permet renouvellement access token
**Sécurité** :
- Tokens stockés hashés (SHA256) en DB
- Device fingerprinting (OS, navigateur, IP)
- Notification si nouveau device

View File

@@ -38,6 +38,7 @@ sequenceDiagram
```
**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]`

View File

@@ -59,6 +59,7 @@ sequenceDiagram
```
**Légende** :
- Limite : 1 export / 30 jours (anti-abus)
- Délai génération : 48h maximum (conformité RGPD Article 20)
- Expiration lien : 7 jours

View File

@@ -56,6 +56,7 @@ sequenceDiagram
```
**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é)

View File

@@ -29,10 +29,12 @@ sequenceDiagram
## Légende
**Rotation** :
- Nouveau refresh_token à chaque refresh
- Ancien token invalidé immédiatement
- Prévient replay attack
**Sécurité** :
- Si ancien token réutilisé → révocation globale
- Logs sécurité + notification utilisateur

View File

@@ -46,6 +46,7 @@ sequenceDiagram
```
**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

View File

@@ -30,12 +30,14 @@ stateDiagram-v2
**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é

View File

@@ -47,6 +47,7 @@ stateDiagram-v2
| 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

View File

@@ -30,12 +30,14 @@ stateDiagram-v2
**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é

View File

@@ -22,6 +22,7 @@ Le domaine **Advertising** gère la diffusion de publicités audio ciblées. C'e
## Ubiquitous Language
**Termes métier du domaine** :
- **Ad Campaign** : Campagne publicitaire avec budget et durée
- **Ad Impression** : Affichage/lecture d'une publicité
- **Ad Targeting** : Critères de ciblage (geo + intérêts)

View File

@@ -63,6 +63,7 @@ if (campaign.hours.includes(userHour)) {
**Règle 2 : Ciblage "France" = Métropole + DOM**
**France entière inclut** :
- France métropolitaine (96 départements)
- Guadeloupe (971)
- Martinique (972)
@@ -71,6 +72,7 @@ if (campaign.hours.includes(userHour)) {
- Mayotte (976)
**Publicitaire peut affiner** :
- "Région Provence-Alpes-Côte d'Azur" → Métropole uniquement
- "Département 971" → Guadeloupe uniquement
- "Ville Pointe-à-Pitre" → Guadeloupe uniquement
@@ -102,6 +104,7 @@ if (campaign.hours.includes(userHour)) {
```
Restaurant à Pointe-à-Pitre
Campagne :
- Zone : Guadeloupe (département 971)
- Horaires : 12h-14h (rush déjeuner)
@@ -114,6 +117,7 @@ User Martinique à 12h30 locale → ❌ Pas diffusion (hors zone géo)
```
Assureur national
Campagne :
- Zone : France (nationale)
- Horaires : 7h-9h + 17h-19h
@@ -136,6 +140,7 @@ Filtrage pubs :
```
**Justification** :
-**UX intuitive pour publicitaires** : "7h-9h" = matin partout (pas besoin comprendre UTC)
-**Équité géographique** : pas de discrimination DOM-TOM, publicitaires locaux peuvent cibler local, campagnes nationales touchent tous Français
-**Simplicité technique** : détection fuseau automatique (GPS ou device), PostgreSQL `AT TIME ZONE` pour calculs backend
@@ -144,6 +149,7 @@ Filtrage pubs :
**Étalement budget** :
```
Exemple campagne :
- Budget : 300€
- Durée : 14 jours
- Zone : Département du Var
@@ -156,6 +162,7 @@ Calcul automatique :
```
**Mode de paiement** :
- ✅ Prépaiement obligatoire (évite impayés)
- ✅ Carte bancaire uniquement (Mangopay)
- ✅ Recharge automatique optionnelle (si budget <10%)
@@ -171,6 +178,7 @@ Calcul automatique :
4. Si refusé → email avec raison + remboursement automatique
**Contenus interdits en pub** :
- ❌ Alcool, tabac (réglementation française)
- ❌ Jeux d'argent
- ❌ Contenu politique (pendant campagnes électorales)
@@ -194,11 +202,13 @@ Calcul automatique :
| **Répartition horaire** | Graphique par heure | Optimisation horaires |
**Métriques engagement avancées** :
- **Taux complétion par tranche d'âge** : identifier audience réceptive
- **Carte de chaleur GPS** : visualiser zones forte écoute
- **Comparatif campagnes** : A/B testing créatifs publicitaires
**Export données** :
- ✅ CSV/Excel pour analyse externe
- ✅ Graphiques interactifs (Chart.js)
- ✅ Rapport PDF automatique fin de campagne
@@ -206,6 +216,7 @@ Calcul automatique :
#### Gestion budget et alertes
**Suivi temps réel** :
- Dashboard : Budget restant, % consommé, jours restants
- Projection : "À ce rythme, budget épuisé dans X jours"
- Alerte email/push si :
@@ -215,6 +226,7 @@ Calcul automatique :
- Campagne terminée (rapport final)
**Ajustements en cours** :
- ✅ Pause campagne (budget conservé)
- ✅ Prolonger campagne (recharge budget)
- ✅ Modifier ciblage horaire/géo (si <50% budget consommé)
@@ -223,12 +235,14 @@ Calcul automatique :
#### Système d'enchères (post-MVP)
**Optionnel future** :
- Enchère au CPM (coût pour 1000 impressions)
- Priorité selon prix : pub prix élevé → diffusion privilégiée
- Floor price : 2€ CPM minimum
- Évite surcharge pub : max 1 pub / 5 contenus stricte
**Justification décision MVP** :
- Tarif fixe simple : 0.05€/écoute complète
- Pas de complexité enchères immédiatement
- Scalable : passage enchères ultérieur si demande forte
@@ -240,22 +254,26 @@ Calcul automatique :
**Décision** : Paramétrable admin + respect expérience utilisateur
**Fréquence d'insertion** :
- **Défaut : 1 pub / 5 contenus** (utilisateurs gratuits)
- **Paramétrable admin** : curseur 1/3 à 1/10
- **Utilisateurs Premium** : 0 pub (modèle sans publicité)
**Règles strictes** :
- ⚠️ **Jamais d'interruption** contenu en cours
- Pub s'insère uniquement **entre deux contenus** (pendant délai 2s)
- Rotation : même pub max **3 fois/jour** par utilisateur (évite saturation)
- Limite : max **6 pubs/heure** par utilisateur (évite spam)
**Ciblage intelligent** :
- Géolocalisation prioritaire (point GPS > ville > département > région > national)
- Centres d'intérêt secondaires (tags utilisateur)
- Horaire (campagne 7h-9h → diffusion uniquement pendant plage **heure locale utilisateur**, voir section 6.1 pour détails fuseaux horaires et DOM-TOM)
**Volume audio normalisé** :
- Pub normalisée à **-14 LUFS** (standard broadcast)
- Évite effet "pub trop forte" (frustration utilisateur)
- Validation automatique via FFmpeg lors encodage
@@ -265,21 +283,25 @@ Calcul automatique :
### 6.3 Caractéristiques publicités
**Durée** :
- Minimum : **10 secondes**
- Maximum : **60 secondes**
- Recommandé : **15-30 secondes** (sweet spot engagement)
**Skippable** :
- Délai minimum obligatoire : **5 secondes** (paramétrable admin : 3-10s)
- Bouton "Passer la publicité" apparaît après délai
- Durée minimale comptabilisée pour facturation
**Facturation** :
- **Écoute complète** (>80%) : 0.05€ facturé publicitaire
- **Skip après délai min** : 0.02€ (exposition partielle)
- **Skip immédiat** (<5s) : 0€ (pas d'engagement)
**Justification modèle tarif** :
- Incitatif qualité : pub engageante = coût réduit
- Équitable : publicitaire paie pour attention réelle
- Transparent : dashboard montre écoutes complètes vs skips

View File

@@ -28,6 +28,7 @@ Le domaine **Content** gère toute la création, publication et diffusion des co
## Ubiquitous Language
**Termes métier du domaine** :
- **Audio Guide** : Contenu structuré en séquences géolocalisées
- **Guide Sequence** : Segment d'un audio-guide déclenché à un point GPS précis
- **Live Stream** : Diffusion audio en temps réel

View File

@@ -14,11 +14,13 @@
| **🚌 Transport** | Variable | Auto GPS + Manuel possible | Bus touristiques, trains panoramiques |
**Détection automatique** :
- Vitesse moyenne calculée sur 30 secondes
- Suggestion mode au démarrage : "Détection : 🚗 Voiture. Est-ce correct ? [Oui] [Changer]"
- User peut forcer mode manuellement (settings)
**Justification** :
- Flexibilité maximale créateurs et utilisateurs
- Expériences optimisées par type de déplacement
- Gestion cas limites (vélo lent vs piéton rapide)
@@ -93,12 +95,14 @@
| **Zone diffusion** | ✅ | Polygon géographique |
**Wizard de création** :
- Étape 1 : Infos générales (titre, description, mode)
- Étape 2 : Ajout séquences une par une
- Étape 3 : Preview carte (trace + points)
- Étape 4 : Validation modération (3 premiers audio-guides)
**Justification** :
- Contrôle total créateur sur expérience
- Carte preview aide visualiser parcours
- Wizard guidé = réduction friction création
@@ -133,10 +137,12 @@ Séquence 1 [fin] → PAUSE → User clique → Séquence 2 [fin] → PUB AUTO-P
```
**Fréquence pub** :
- Gratuits : 1 pub toutes les 5 séquences (paramétrable admin 1/3 à 1/10)
- Premium : 0 pub
**Justification** :
- Pub s'insère naturellement (pas d'attente utilisateur pour déclencher)
- User garde contrôle rythme visite (pause après pub)
- Monétisation effective créateurs
@@ -199,15 +205,18 @@ Séquence 1 [fin] → PAUSE → User clique → Séquence 2 [fin] → PUB AUTO-P
```
**Navigation libre** :
- User peut sauter séquences déjà connues
- User peut revenir en arrière à tout moment
- User peut aller directement à séquence 8 (même si 4-7 non écoutées)
**Sauvegarde progression** :
- Checkmarks ✅ sur séquences écoutées >80%
- Position exacte sauvegardée dans séquence en cours
**Justification** :
- Utilisateur contrôle 100% son rythme
- Adapté musées : visitor peut voir physiquement une œuvre lointaine et vouloir écouter sa description
- Pas de frustration (liberté totale)
@@ -241,6 +250,7 @@ Séquence 1 [fin] → PAUSE → User clique → Séquence 2 [fin] → PUB AUTO-P
8. Séquence suivante démarre immédiatement (pas de décompte)
**Pas de système "7 secondes avant" pour les audio-guides** :
- Contrairement aux contenus géolocalisés simples (voir [../../recommendation/rules/interactions-navigation.md](../../recommendation/rules/interactions-navigation.md#511-file-dattente-et-commande-suivant))
- Les séquences se déclenchent **au point GPS exact** (rayon 30m)
- Raison : expérience guidée continue, user sait qu'il suit un parcours
@@ -268,6 +278,7 @@ Séquence 1 [fin] → PAUSE → User clique → Séquence 2 [fin] → PUB AUTO-P
- Si vitesse **>10 km/h** ET user clique bouton (Suivant/Précédent) :
- Toast 3 secondes : "⚠️ Manipulation en conduite détectée. Pour votre sécurité, demandez à un passager."
- **Action quand même exécutée** (pas de blocage)
- Justification : sensibilisation sans bloquer (passager peut légitimement manipuler)
**Schéma flux** :
@@ -278,6 +289,7 @@ Point GPS 1 (30m) → Séquence 1 AUTO → User roule → Distance affichée →
```
**Justification** :
- Flexibilité maximale : GPS optimise expérience MAIS user garde contrôle
- Gestion cas limites : routes fermées, détours, embouteillages
- Sécurité : warning sensibilise sans bloquer (passager légitime)
@@ -361,12 +373,14 @@ Quand une séquence se termine et qu'il reste un point GPS suivant, l'interface
```
**Progress bar dynamique** :
- Se remplit au fur et à mesure qu'on se rapproche du point
- Calcul : `progress = 100 - (distance_actuelle / distance_initiale * 100)`
- Exemple : distance initiale 500m, distance actuelle 175m → progress = 65%
- Couleur : vert (#4CAF50) pour la partie remplie, gris (#E0E0E0) pour le reste
**Bouton "Rejouer séq."** :
- Permet de réécouter la séquence qui vient de se terminer
- User clique → séquence actuelle redémarre depuis 0:00
- Utile si distraction pendant l'écoute
@@ -414,6 +428,7 @@ if (currentSpeed > 5) {
```
**Justification** :
- Distance + ETA = info essentielle sans surcharge visuelle
- Direction (flèche) = aide se repérer sans carte complexe
- Simplicité = moins distraction conducteur
@@ -470,10 +485,12 @@ Popup 5 secondes :
| **Faire demi-tour** | Lance navigation GPS externe (Google Maps / Waze) vers point manqué |
**Si user au-delà rayon tolérance (>100m)** :
- Aucun popup (point trop loin, probablement hors itinéraire)
- User peut naviguer manuellement (bouton Suivant)
**Justification** :
- Flexibilité créateur (ajuste selon terrain, vitesse prévue)
- Gestion intelligente imprévus (détours, routes fermées)
- User pas bloqué (toujours moyen avancer)
@@ -489,6 +506,7 @@ Popup 5 secondes :
##### Comportement bouton [▶|] Suivant
**1. Premier clic (mode GPS auto actif)** :
- Désactive GPS automatique
- Passe à la séquence suivante immédiatement
- Bascule en **mode manuel**
@@ -496,12 +514,14 @@ Popup 5 secondes :
- Timer 10 secondes démarre
**2. Deuxième clic (dans les 10 secondes suivantes)** :
- Sort de l'audio-guide
- Audio-guide mis en **pause** (historique conservé)
- Retour au **flux normal** (algorithme de recommandation)
- Toast 2s : "Audio-guide en pause"
**3. Clics suivants (après 10 secondes)** :
- Passe à la séquence suivante (comportement standard mode manuel)
- Timer 10 secondes redémarre à chaque clic
@@ -584,6 +604,7 @@ function onSuivantClick() {
```
**Justification** :
- Résout le problème des embouteillages (30 min sans contenu)
- Double intention claire : désactiver GPS puis sortir
- User garde toujours le contrôle (peut reprendre audio-guide plus tard)
@@ -625,6 +646,7 @@ function onSuivantClick() {
- Pub entre séquences
**Justification** :
- Vélo : moins de contrôle qu'auto (obstacles, arrêts), nécessite tolérance
- Transport : moins de contrôle utilisateur (suit ligne fixe), rayon large compense
- Même UX globale = cohérence
@@ -677,6 +699,7 @@ Séquence 2 [fin]
| **Transport** | Attente GPS OU user clique Suivant | Attente GPS OU user clique Suivant |
**Justification** :
- Monétisation équitable créateurs (tous modes participent)
- Pub s'insère naturellement (auto-play, pas d'attente utilisateur)
- User garde contrôle : piéton clique Suivant, voiture peut skip manuel
@@ -697,10 +720,12 @@ Séquence 2 [fin]
| **Revenus pub audio-guides** | 3€ / 1000 écoutes complètes (6% CA pub) |
**Distinction contenus normaux vs audio-guides** :
- Dashboard sépare : "Revenus contenus classiques" / "Revenus audio-guides"
- Permet créateur voir performance par type
**Justification** :
- Transparence créateur (comprend revenus)
- Incite création audio-guides (nouvelle source revenus)
@@ -731,10 +756,12 @@ Séquence 2 [fin]
| **Cloud** | PostgreSQL (sync auto) | Multi-device (reprendre sur autre appareil) |
**Synchronisation** :
- Sauvegarde locale : chaque fin de séquence + chaque 30s
- Sync cloud : à la reconnexion réseau (batch)
**Justification** :
- Expérience fluide (pas de perte progression)
- Multi-device (démarrer sur iPhone, continuer sur iPad)
- Offline-first (fonctionne sans réseau)
@@ -744,6 +771,7 @@ Séquence 2 [fin]
#### 16.6.2 Interface de reprise
**Conditions popup** :
- Dernière écoute **<30 jours**
- Progression **>0%** et **<100%** (pas terminé)
@@ -776,11 +804,13 @@ Séquence 2 [fin]
| **Voir séquences** | Affiche liste complète, user choisit séquence départ |
**Expiration progression** :
- Progression conservée **30 jours**
- Après 30j : popup "Audio-guide expiré. Recommencez depuis le début ?"
- Suppression données progression (mais historique "écouté" préservé)
**Justification** :
- Contexte clair : user sait exactement où il en est
- Flexibilité : reprendre OU recommencer (choix utilisateur)
- 30 jours = raisonnable pour tourisme multi-jours ou retour ultérieur
@@ -798,10 +828,12 @@ Séquence 2 [fin]
5. User clique Reprendre → continue séquence 4
**Conflit de version** :
- Si modifications simultanées 2 appareils (rare) : **dernière modification gagne**
- Toast : "Progression mise à jour depuis votre autre appareil"
**Justification** :
- Confort utilisateur (change d'appareil librement)
- Use case réel : planning trajet sur tablette, écoute sur smartphone en voiture

View File

@@ -5,6 +5,7 @@
**Objectif** : Proposer des contenus audio au moment précis où l'utilisateur passe devant un point d'intérêt géographique, pour enrichir son trajet avec des informations contextuelles liées au paysage.
**Contrainte principale** : **Sécurité routière**
- Aucune distraction visuelle (pas de texte à lire)
- Notification sonore uniquement + icône minimale
- Validation par un seul bouton physique au volant ("Suivant")
@@ -26,6 +27,7 @@
**Méthode** : API GPS native iOS/Android
**Principe** :
- Calcul temps d'arrivée au point GPS basé sur vitesse actuelle et distance
- Notification déclenchée **7 secondes avant** d'atteindre le point
- Permet au conducteur d'avoir le temps de réagir (2s) + décompte (5s)
@@ -118,11 +120,13 @@ class GeoContentDetector(private val fusedLocationClient: FusedLocationProviderC
```
**Cas particulier : vitesse nulle ou très faible** :
- Si vitesse < 5 km/h (1.4 m/s) ET distance < 50m → notification immédiate
- Exemple : user arrêté à un feu rouge à 30m du point
- Évite notification trop tardive quand user redémarre
**Fréquence de vérification** :
- GPS updates : toutes les 1 seconde (balance batterie/précision)
- Calcul ETA : à chaque update GPS
- Notification : déclenchée immédiatement quand ETA ≤ 7s
@@ -134,6 +138,7 @@ class GeoContentDetector(private val fusedLocationClient: FusedLocationProviderC
**Philosophie** : **Minimalisme absolu** pour sécurité routière
**Pas de** :
- Titre texte à lire
- Description longue
- Bouton "Annuler" ou "Plus tard"
@@ -141,6 +146,7 @@ class GeoContentDetector(private val fusedLocationClient: FusedLocationProviderC
- Image/cover du contenu
**Uniquement** :
- Son bref (notification)
- Icône selon tag du contenu
- Compteur chiffres (7→1)
@@ -179,12 +185,14 @@ class GeoContentDetector(private val fusedLocationClient: FusedLocationProviderC
```
**Évolution du compteur** :
- Affichage pendant 7 secondes
- Compteur décrémente : 7 → 6 → 5 → 4 → 3 → 2 → 1 → disparaît
- Police grande (72pt), bold, couleur blanche
- Background semi-transparent (noir 50% opacity)
**Notification sonore** :
- **Son** : bip court (0.5s) ou "ding" doux personnalisé RoadWave
- **Volume** : suit le volume système notification (indépendant du volume media)
- **Pas de vibration** : inutile en voiture (téléphone sur support)
@@ -200,6 +208,7 @@ class GeoContentDetector(private val fusedLocationClient: FusedLocationProviderC
**Décision** : Notification sonore uniquement en mode CarPlay/Android Auto
**Contexte** :
- [CarPlay Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/carplay) interdisent les overlays qui "takeover" l'écran
- [Android Auto Media Apps Guidelines](https://developer.android.com/training/cars/media) imposent des interactions minimales
- Sécurité routière maximale = pas de distraction visuelle
@@ -207,11 +216,13 @@ class GeoContentDetector(private val fusedLocationClient: FusedLocationProviderC
**Comportement en mode CarPlay/Android Auto** :
**Désactivé** :
- Icône overlay
- Compteur visuel (7...6...5...)
- Tout élément graphique supplémentaire
**Activé uniquement** :
- Notification sonore (bip ou ding)
- Bouton "Suivant" standard (déjà présent)
@@ -280,12 +291,14 @@ class NotificationManager(private val context: Context) {
6. Contenu géolocalisé démarre après 5s
**Justification** :
- ✅ Conformité maximale CarPlay/Android Auto guidelines
- ✅ Sécurité routière (pas de distraction visuelle)
- ✅ User peut toujours valider via bouton "Suivant" standard
- ✅ Apps comparables (Waze, Apple Maps) utilisent alertes sonores similaires
**Alternative envisagée** : Mini-badge sur bouton "Suivant"
- Moins invasif qu'un compteur
- Mais toujours considéré comme overlay (zone grise)
- **Décision** : Privilégier conformité maximale (sonore uniquement)
@@ -297,15 +310,18 @@ class NotificationManager(private val context: Context) {
**User appuie sur "Suivant"** :
**Étape 1 : Transition visuelle (0.3s)**
- Icône + compteur "7" disparaissent avec fade out
- Nouveau compteur "5" apparaît (plus grand, centré)
**Étape 2 : Décompte 5 secondes**
- Compteur décrémente : 5 → 4 → 3 → 2 → 1
- Contenu actuel continue de jouer **normalement** (pas de baisse volume)
- User entend le contenu en cours pendant le décompte
**Étape 3 : Fin du décompte**
- Compteur atteint "0"
- Fade out 0.3s du contenu actuel
- Fade in 0.3s du contenu géolocalisé
@@ -327,6 +343,7 @@ T+5s : Décompte atteint 0
```
**Justification** :
- Évite silence inconfortable pendant décompte
- User continue d'écouter du contenu intéressant
- Transition naturelle
@@ -353,6 +370,7 @@ T+5s : Décompte atteint 0
### 17.3 Limitation anti-spam
**Problème identifié** :
- Routes riches en points d'intérêt (parcours touristiques)
- Risque de notifier toutes les 30 secondes
- Fatigue utilisateur + distraction conducteur
@@ -362,6 +380,7 @@ T+5s : Décompte atteint 0
#### 17.3.1 Quota : 6 contenus géolocalisés par heure
**Règle** :
- Maximum **6 contenus géolocalisés** notifiés par heure
- Fenêtre glissante : calcul sur les 60 dernières minutes (pas réinitialisation à 0h)
- Si quota atteint : notifications suivantes ignorées silencieusement
@@ -380,6 +399,7 @@ T+5s : Décompte atteint 0
```
**Exception : audio-guides multi-séquences** :
- Un audio-guide avec N séquences compte comme **1 seul contenu** dans le quota
- Une fois démarré, toutes ses séquences sont jouables (pas de limite)
- Exemple : audio-guide 8 séquences = 1 quota, contenus simples restants = 5
@@ -422,12 +442,14 @@ func RecordNotification(userID string, contentID string) {
#### 17.3.2 Cooldown : 10 minutes après notification ignorée
**Règle** :
- Si user ne clique pas sur "Suivant" pendant les 7 secondes
- → Cooldown de **10 minutes** activé
- → Aucune nouvelle notification pendant ce délai
- → Même si quota non atteint
**Justification** :
- User a probablement une raison de ne pas vouloir de contenu géolocalisé maintenant
- Évite harcèlement (notifications répétées ignorées)
- Respecte choix implicite de l'utilisateur
@@ -458,6 +480,7 @@ func ActivateCooldown(userID string) {
```
**Exception : notification validée (user a cliqué)** :
- Pas de cooldown si user a cliqué sur "Suivant"
- Même si user skip le contenu ensuite (pendant le décompte ou après)
- Cooldown = pénalité uniquement pour notification complètement ignorée
@@ -503,6 +526,7 @@ Timeline :
6. User appuie "Précédent" → **retour au contenu géolocalisé à 42s**
**Règle** : Comme décrit dans [../../recommendation/rules/interactions-navigation.md](../../recommendation/rules/interactions-navigation.md#52-commande-précédent) :
- Si temps écouté ≥ 10 secondes → replay contenu actuel depuis début
- Si temps écouté < 10 secondes → retour contenu précédent (position exacte)
@@ -567,6 +591,7 @@ if (avgSpeedKmh < 5) {
```
**Hysteresis (éviter basculements intempestifs)** :
- Nouvelle vitesse doit être stable pendant **10 secondes** avant basculement
- Exemple : user passe de 20 km/h à 3 km/h (arrêt feu rouge)
- Si vitesse remonte à 20 km/h après 8s → pas de basculement
@@ -595,6 +620,7 @@ if (avgSpeedKmh < 5) {
| **Type contenu** | Audio-guides uniquement | Tous contenus géolocalisés |
**Transition fluide** :
- Pas de popup ou message à l'utilisateur
- Basculement invisible et automatique
- Permissions ajustées automatiquement (si déjà accordées)
@@ -608,6 +634,7 @@ if (avgSpeedKmh < 5) {
**Scénario** : Autoroute A6, vitesse 130 km/h, contenu géolocalisé détecté.
**Calcul** :
- Vitesse : 130 km/h = 36.1 m/s
- ETA 7s → distance notification : 7 × 36.1 = **252 mètres** avant le point
- User a 7s pour cliquer "Suivant"
@@ -618,6 +645,7 @@ if (avgSpeedKmh < 5) {
**Conclusion** : Le système fonctionne même à très haute vitesse ✅
**Cas extrême : 180 km/h** (illégal mais théoriquement possible) :
- Vitesse : 180 km/h = 50 m/s
- ETA 7s → distance notification : 350m avant le point
- Décompte 5s : user parcourt 250m
@@ -655,6 +683,7 @@ T+57s : User clique "Suivant" → contenu Château B démarre
**Solution proposée** : **Ajuster le cooldown selon validation précédente**
Nouvelle règle :
- Notification validée (user a cliqué) : pas de cooldown
- Notification ignorée (user n'a pas cliqué) : cooldown 10 min
- Exception : si 2+ notifications validées consécutives, cooldown réduit à 5 min
@@ -687,18 +716,21 @@ func CalculateCooldown(userID string) time.Duration {
**Scénario** : User se gare à 30m d'un château, sort de voiture, visite 1h, revient.
**Problème** :
- Vitesse < 5 km/h + distance < 50m → notification immédiate
- Mais user en mode "stationnement", pas en mode "conduite"
**Solution** : **Détection mode stationnement**
Règle :
- Si vitesse < 1 km/h pendant **2 minutes** consécutives
- → Mode "stationnement" activé
- → Pas de notification de contenus géolocalisés
- → Basculement automatique en mode piéton (push arrière-plan)
**Reprise conduite** :
- Vitesse > 5 km/h pendant 10s
- → Mode "voiture" réactivé
- → Notifications reprennent (si quota non atteint)

View File

@@ -5,6 +5,7 @@
**Décision** : Formats universels avec encodage asynchrone
**Formats acceptés** :
- ✅ MP3 (`.mp3`)
- ✅ AAC (`.aac`, `.m4a`)
- ❌ WAV, FLAC (trop lourds, inutiles en voiture)
@@ -31,6 +32,7 @@
```
**Temps d'encodage estimé** :
- Contenu 5 min → ~30 secondes
- Podcast 1h → ~5 minutes
- Podcast 4h → ~20 minutes
@@ -54,11 +56,13 @@
| 2.0x | Survol rapide (modérateurs) |
**Disponible pour** :
- ✅ Modérateurs (validation rapide : 30s → 15s à 2x)
- ✅ Auditeurs (tous les contenus)
- ✅ Standard industrie (YouTube, Spotify, Apple Podcasts)
**Justification** :
- **Simplicité** : 2 formats couvrent 95% des cas d'usage
- **Coût optimisé** : pas de conversion WAV/FLAC lourds
- **Stockage réduit** : suppression original après encodage
@@ -84,6 +88,7 @@
**Zone de diffusion (obligatoire)** :
Options mutuellement exclusives :
- **Point GPS** : latitude + longitude + rayon (100m à 10km)
- **Ville** : sélection dans référentiel INSEE
- **Département** : sélection liste
@@ -91,6 +96,7 @@ Options mutuellement exclusives :
- **National** : France entière
**Tags disponibles** (1 à 3 obligatoires) :
- Automobile
- Voyage
- Famille
@@ -105,12 +111,14 @@ Options mutuellement exclusives :
- Santé
**Champs optionnels** :
- ❌ Description (ajout ultérieur)
- ❌ Image couverture (génération auto)
**Image de couverture par défaut** :
Génération automatique selon règles :
- Icône selon type géo : 📍 Ancré / 🌍 Contextuel / 🎧 Neutre
- Couleur selon tag principal : bleu (Auto), vert (Voyage), rouge (Musique), etc.
- Format 800×800px, PNG
@@ -127,6 +135,7 @@ Classification : Tout public
```
**Justification** :
- **Friction minimale** : 5 champs max = 2 min de publication
- **Publication rapide** : pas de blocage sur description/image
- **Coût 0** : pas de génération IA au MVP
@@ -161,6 +170,7 @@ Classification : Tout public
| **Zone diffusion** | Cohérente (pas "Tour Eiffel" avec zone "National") |
**Délai de validation** :
- Objectif : **24-48h** (jours ouvrés)
- Priorité : FIFO (First In First Out)
- Weekend : délai peut atteindre 72h
@@ -169,11 +179,13 @@ Classification : Tout public
**Notification créateur** :
**Si accepté** :
- Email + push : "✅ Votre contenu '[Titre]' est en ligne !"
- Lien direct vers le contenu
- Compteur : "2/3 contenus validés pour devenir créateur vérifié"
**Si refusé** :
- Email + push : "❌ Contenu '[Titre]' refusé"
- Raison détaillée : "Qualité audio insuffisante" / "Tags non pertinents" / "Classification incorrecte" / etc.
- Lien vers règles de publication
@@ -182,11 +194,13 @@ Classification : Tout public
**Après 3 validations** :
Créateur obtient **statut "Vérifié"** :
- Badge ✓ visible sur profil
- Contenus futurs publiés **immédiatement** (modération a posteriori uniquement)
- Modération seulement si signalé par utilisateurs
**Outils modérateur** :
- Écoute accélérée (1.5x ou 2x) = double productivité
- Interface dédiée : queue de contenus à valider
- Raccourcis clavier : A (Accepter), R (Rejeter), Espace (Pause)
@@ -197,6 +211,7 @@ Créateur obtient **statut "Vérifié"** :
⚠️ **Non implémenté au MVP** (complexité juridique)
Vision future (envisageable) :
- Créateurs établis peuvent opt-in "Modérateur communautaire"
- Formation obligatoire (30 min) + quiz (80%)
- Pré-validation uniquement (validation finale toujours par équipe RoadWave)
@@ -204,6 +219,7 @@ Vision future (envisageable) :
- Attribution aléatoire (pas de collusion)
**Justification décision MVP** :
- **Responsabilité juridique** : plateforme reste responsable (DSA EU)
- **Qualité garantie** : modérateurs formés et mandatés
- **Anti-spam efficace** : bloque 95% des abus dès le début
@@ -233,18 +249,22 @@ Vision future (envisageable) :
**Raisons restrictions** :
**Audio non modifiable** :
- Évite fraude : uploader contenu validé → remplacer par spam
- Intégrité : auditeurs doivent écouter ce qui a été validé
**Zone/Type non modifiables** :
- Évite manipulation : créer "Local Paris" → changer en "National" pour boost visibilité
- Évite abus : créer "Neutre" (faible pondération géo) → changer en "Ancré" (forte pondération)
**Classification non modifiable** :
- Évite contournement : uploader "Tout public" → passer en "18+" sans revalidation
- Sécurité : garantit que classification a été vérifiée
**Si besoin de changer audio/zone/classification** :
- Action : **Supprimer contenu + republier**
- Si créateur <3 contenus validés : retourne en file validation
- Si créateur ≥3 contenus validés : publication immédiate
@@ -269,11 +289,13 @@ Créateur supprime podcast écouté par 1000 personnes
```
**Notifications suppression** :
- Pas de notification aux auditeurs (pour éviter effet Streisand)
- Historique reste consultable : "Vous avez écouté ce contenu le [date]"
- Si auditeur tente de réécouter : "Ce contenu n'est plus disponible"
**Justification** :
- **Simplicité** : règles claires et non-ambiguës
- **Sécurité** : évite manipulations algorithme et contournements modération
- **Contrôle créateur** : liberté totale de supprimer (RGPD)

View File

@@ -60,6 +60,7 @@
4. Mention titre + artiste dans métadonnées (recommandé)
**Justification juridique** :
- Directive UE 2019/790 : exception citation à des fins de critique
- Jurisprudence FR : citation courte autorisée si justifiée
- 30s = standard industrie (YouTube, TikTok)
@@ -108,6 +109,7 @@ Validation normale continue
- ✅ Modération **a posteriori uniquement** (si signalé)
**Justification** :
- **Coût 0€** : réutilise écoute 30s déjà effectuée
- **Scalable** : pas de validation pour créateurs établis
- **Pragmatique** : détecte violations évidentes (90% des cas)
@@ -175,6 +177,7 @@ Validation normale continue
**Détail sanctions** :
**Avertissement (1ère fois)** :
- Suppression contenu immédiate
- Email + push + in-app : "⚠️ Contenu retiré pour violation droits d'auteur"
- Explication pédagogique : règles musique, lien vers CGU
@@ -182,22 +185,26 @@ Validation normale continue
- Créateur peut republier version corrigée
**Strike 1 (2e fois)** :
- Suppression contenu
- Strike ajouté au compteur (visible profil créateur)
- Suspension upload **3 jours**
- Email détaillé : titre détecté, timestamp, règle violée
**Strike 2 (3e fois)** :
- Idem Strike 1
- Suspension upload **7 jours**
- Warning : "Strike 2/4 - Vous approchez du seuil critique"
**Strike 3 (4e fois)** :
- Idem Strike 2
- Suspension upload **30 jours**
- Warning : "Strike 3/4 - Prochaine violation = ban définitif"
**Strike 4 - Ban définitif (5e fois)** :
- Désactivation compte créateur
- Tous contenus dépubliés
- Pas de création nouveau compte (email/téléphone blacklisté)
@@ -226,6 +233,7 @@ Créateur a Strike 2 (7 jours de suspension)
```
**Justification** :
- **Tolérance 1ère fois** : évite punir erreurs honnêtes
- **Escalade progressive** : dissuasion sans brutalité
- **4 strikes avant ban** : cohérent avec système global (sections 9, 14)
@@ -239,6 +247,7 @@ Créateur a Strike 2 (7 jours de suspension)
**Décision** : Réutilise système existant section 14.3.3
**Accès** :
- Bouton "Contester cette décision" dans notification sanction
- Délai : **7 jours** après notification
@@ -266,11 +275,13 @@ Champs standards (voir section 14) **+** champs spécifiques :
**Cas particulier : Musique libre mal détectée**
Si créateur prouve musique = licence Epidemic Sound / Artlist :
- ✅ Appel automatiquement accepté
- ✅ Ajout titre à **whitelist interne** (évite futures erreurs)
- ✅ Excuse + compensation (ex: 1 mois Premium offert)
**Justification** :
- Réutilise processus éprouvé (section 14)
- Preuve licence = résout 90% des cas
- Délai 72h acceptable (pas de suspension immédiate sur appel)
@@ -309,6 +320,7 @@ Interdit :
```
**Justification** :
- Prévention > sanction (économie modération)
- Créateurs informés = moins de violations
- Coût : 0€ (documentation statique)
@@ -382,12 +394,14 @@ Modérateur humain vérifie :
**Coût total MVP** : **0€** (validation manuelle intégrée)
**Conformité juridique** :
- ✅ Directive UE 2019/790 (droit d'auteur + exception citation)
- ✅ DSA (Digital Services Act) : modération réactive + droit d'appel
- ✅ SACEM/SDRM : protection ayants droit + processus contentieux
- ✅ Fair use : tolérance 30s conforme jurisprudence FR/UE
**Scalabilité** :
- 0-1000 contenus/mois : validation manuelle suffisante (3h/mois modération)
- 1000-10K contenus/mois : fingerprinting open-source requis
- 10K+ contenus/mois : API commerciale à considérer (ACRCloud)
@@ -404,6 +418,7 @@ Modérateur humain vérifie :
---
**Lien avec autres sections** :
- Section 4.3 : Validation des 3 premiers contenus (workflow intégré)
- Section 7.2 : Interdictions lives + fingerprinting post-MVP
- Section 14 : Système modération (signalements, sanctions, appels)

View File

@@ -18,12 +18,14 @@
4. Après 15s → **Live public**, auditeurs peuvent rejoindre
**Notification abonnés** :
-**Push notification immédiate** à tous les abonnés dans la zone géographique
- Message : "🔴 [Nom créateur] est en direct : [Titre live]"
- Tap notification → ouverture app + lecture live immédiate
- **Filtrage géographique** : si abonné hors zone, pas de notif (évite frustration)
**Limite de durée** :
- **Maximum 8 heures** par session live
- Warning créateur à 7h30 : "Votre live se terminera dans 30 min"
- Si besoin continuer → arrêt + redémarrage nouveau live (évite abus ressources serveur)
@@ -56,12 +58,14 @@
```
**Détection violations** :
- **Signalement utilisateurs** : bouton "Signaler" accessible pendant live
- **IA audio fingerprint** : détection musique protégée en arrière-plan (post-MVP, voir [Section 18](detection-contenu-protege.md))
- **Modération réactive** : modérateurs peuvent écouter lives signalés en temps réel
- **Coupure immédiate** : modérateur peut arrêter live si contenu illégal évident
**Justification** :
- **Buffer 15s** : équilibre entre test qualité et friction minimale
- **Notification abonnés** : engagement maximal, valeur ajoutée live
- **8h max** : couvre 99% cas usage (podcasts longs, émissions radio) sans abus
@@ -117,11 +121,13 @@
| **Modifier replay** | ❌ Non | Intégrité enregistrement |
**Conservation fichier source** :
- Opus raw conservé **7 jours** après fin live (backup)
- Suppression automatique après 7j (économie stockage)
- Si replay supprimé par créateur → fichier raw supprimé immédiatement
**Justification** :
- **Compte à rebours 5s** : outro propre, pas de coupure brutale
- **Tolérance 60s** : évite arrêts intempestifs (tunnel, changement cellule)
- **Enregistrement auto** : valorisation contenu éphémère, génération contenu pérenne
@@ -172,6 +178,7 @@
**Décision ferme** : ❌ **Aucun chat en direct, ni maintenant ni dans le futur**
**Raisons** :
- **Sécurité routière** : pas de distraction en voiture (focus UX)
- **Harcèlement** : évite contenu haineux, insultes, trolling
- **Modération** : pas de coût modération temps réel (impossible à scale)
@@ -189,9 +196,11 @@
| **Réactions emoji** | ❌ | Jamais implémenté (décision définitive) |
**Messages utilisateur** :
- "💬 Les discussions ne sont pas disponibles sur RoadWave pour garantir votre sécurité en voiture et éviter le harcèlement."
**Justification décision définitive** :
- **UX cohérente** : RoadWave = écoute en conduisant, pas réseau social interactif
- **Bien-être** : évite toxicité, harcèlement, haine (fléau réseaux sociaux)
- **Juridique** : pas de risque contentieux modération chat (DSA EU)
@@ -223,6 +232,7 @@ Auditeurs (App mobile, HLS natif)
6. **Post-live** → Job async : Opus → MP3 256 kbps → Publication replay
**Dépendances** :
-**Pion WebRTC** (Go library, open source, MIT license)
-**FFmpeg** (conversion audio, LGPL/GPL)
-**NGINX** (cache et distribution HLS, open source)
@@ -230,6 +240,7 @@ Auditeurs (App mobile, HLS natif)
-**PostgreSQL + Redis** (métadonnées live + cache)
**Avantages** :
- ✅ Pas de dépendance Google/Facebook/Cloudflare (souveraineté)
- ✅ WebRTC standard ouvert (Pion = lib Go pure)
- ✅ Réutilise infra HLS existante (pas de doublon)
@@ -245,6 +256,7 @@ Auditeurs (App mobile, HLS natif)
| **Scale** | 1M-10M | Kubernetes auto-scale (2000+ lives) | +1K€ + bande passante |
**Bande passante** :
- Live : 48 kbps × nb_auditeurs (via NGINX Cache, segments)
- Exemple : 100 auditeurs = 4.8 Mbps = ~2 Go/heure via cache
- Coût estimé : ~0.02€/heure pour 100 auditeurs

View File

@@ -35,6 +35,7 @@ Le domaine **Moderation** gère la modération des contenus et des utilisateurs,
## Ubiquitous Language
**Termes métier du domaine** :
- **Report** : Signalement d'un contenu ou utilisateur problématique
- **Strike** : Avertissement comptabilisé (3 strikes = ban)
- **Sanction** : Mesure disciplinaire (warning, suspension, ban)

View File

@@ -67,6 +67,7 @@ flowchart TD
## Légende
**Priorités de traitement** :
- 🔴 **CRITIQUE** (score ≥90) : <2h - Violence, suicide, danger immédiat
- 🟠 **HAUTE** (70-89) : <24h - Haine, harcèlement
- 🟡 **MOYENNE** (40-69) : <24h - Spam, contenu inapproprié

View File

@@ -9,6 +9,7 @@
**Disponibilité** : Partout dans l'application
**Emplacements** :
- Player en lecture (bouton dans contrôles)
- Page profil créateur (sur chaque contenu)
- Liste de recherche (menu contextuel)
@@ -17,6 +18,7 @@
**Icône** : ⬆️ (universelle iOS/Android)
**Menu options** :
- Copier le lien
- WhatsApp
- Email
@@ -24,6 +26,7 @@
- Plus... (sheet natif OS)
**Justification** :
- Viralité = croissance organique gratuite
- Aucune friction, partage universel
@@ -93,11 +96,13 @@ Page web responsive
```
**Deep linking** :
- iOS : Universal Links (configuration `apple-app-site-association`)
- Android : App Links (configuration `assetlinks.json`)
- URL scheme : `roadwave://content/[content_id]`
**Justification** :
- Meilleure viralité (partage social optimisé)
- SEO (contenus indexés Google)
- UX optimale (web + app)
@@ -137,10 +142,12 @@ Page web responsive
- Rejouer les 30 premières secondes (illimité)
**Tracking** :
- Métriques créateur : "Partages Premium" + "Conversions Premium"
- Créateur touche sa part si conversion (70%)
**Justification** :
- Équilibre viralité / monétisation
- 30s = assez pour donner envie, pas assez pour satisfaire
- Protège revenus créateurs
@@ -219,10 +226,12 @@ Page web responsive
| **Par tag** | Filtre multi-sélection tags |
**Recherche locale** :
- Barre recherche dans profil : "Rechercher dans les contenus de @pseudo"
- Recherche full-text sur titres + descriptions
**Actions menu [•••]** :
- Partager profil
- Signaler profil (spam, usurpation)
- Bloquer créateur (masque tous ses contenus)
@@ -254,6 +263,7 @@ Page web responsive
| **Démographie** | Âge / zone géo (agrégée, anonymisée) |
**Justification** :
- Arrondi = évite comparaisons anxiogènes
- Preuve sociale pour nouveaux auditeurs (trust)
- Gamification douce (motivation créateurs)
@@ -272,6 +282,7 @@ Page web responsive
3. **Communauté significative** : ≥10K abonnés + compte actif >6 mois
**Affichage** :
- Badge bleu **✓** accolé au pseudo (partout : profil, player, recherche)
- Tooltip au survol/appui long : "Compte vérifié"
@@ -284,11 +295,13 @@ Page web responsive
| **Automatique (10K)** | Badge attribué automatiquement à 10K abonnés si compte >6 mois |
**Retrait du badge** :
- Suspension monétisation → badge retiré temporairement
- Strikes multiples → badge retiré définitivement
- Usurpation identité détectée → ban + retrait
**Justification** :
- Combat usurpations d'identité
- Trust auditeurs (surtout pour médias/personnalités)
- Simplicité (1 seul badge, pas de gamification excessive)
@@ -332,6 +345,7 @@ LIMIT 20;
```
**Champs indexés** :
- Titre du contenu (poids × 3)
- Description (poids × 1)
- Pseudo créateur (poids × 2)
@@ -350,10 +364,12 @@ LIMIT 20;
**Coût** : 0€ (PostgreSQL natif)
**Migration future** :
- Si >100K contenus : Meilisearch (typo-tolerance avancée, ~20-50€/mois)
- Si >1M contenus : Elasticsearch cluster
**Justification** :
- PostgreSQL full-text = performant jusqu'à 500K contenus
- Stemming français natif
- 0€, aucune dépendance externe
@@ -411,15 +427,18 @@ ORDER BY distance ASC;
```
**Affichage résultats** :
- Tri par défaut : distance croissante
- Indication distance : "À 2.3 km" / "À 15 km" / "À 142 km"
- Option carte : markers cliquables (clustering si >50 résultats)
**Coût** :
- MVP : 0€ (Nominatim public)
- Scale : 20-50€/mois (Nominatim self-hosted Docker)
**Justification** :
- Essentiel pour tourisme / planification trajet
- OpenStreetMap = pas de dépendance Google
- PostGIS = performant (index GIST natif)
@@ -520,6 +539,7 @@ CREATE INDEX idx_content_tags ON contents USING GIN(tags);
**Coût** : 0€ (PostgreSQL + index standards)
**Justification** :
- Filtres essentiels pour découvrabilité
- Combinables = puissance maximale
- Sauvegarde = gain temps utilisateurs réguliers
@@ -575,17 +595,20 @@ CREATE INDEX idx_content_tags ON contents USING GIN(tags);
| **Distance** | Si recherche géo : "À 2.3 km" |
**Actions contextuelles [⋮]** :
- Partager
- Ajouter à une playlist (future feature)
- Télécharger (offline)
- Signaler
**Pagination** :
- **20 résultats** par page
- Infinite scroll (charger automatiquement si scroll >80%)
- Bouton "Charger 20 suivants" en bas (fallback si scroll auto désactivé)
**Vue carte (alternative)** :
- Bouton toggle "Liste / Carte"
- Map Leaflet (OpenStreetMap)
- Markers cliquables → popup avec preview
@@ -594,6 +617,7 @@ CREATE INDEX idx_content_tags ON contents USING GIN(tags);
**Coût** : 0€ (Leaflet open source + OSM tiles gratuit)
**Justification** :
- Équilibre information / compacité
- Lazy loading = performances
- Infinite scroll = UX moderne

View File

@@ -3,6 +3,7 @@
**Contexte** : Système de gamification pour encourager les utilisateurs à signaler du contenu inapproprié de manière pertinente et qualitative.
**Objectifs** :
- Améliorer la qualité des signalements (réduire les signalements abusifs)
- Réduire la charge de travail des modérateurs (priorisation automatique)
- Récompenser les contributeurs actifs et fiables
@@ -22,6 +23,7 @@
| 🥇 | **Contributeur Or** | 50 signalements validés + 90% taux pertinence | Signalements prioritaires (+30 points) + Badge visible + Réduction Premium |
**Règles d'éligibilité** :
- Minimum **10 signalements envoyés** pour être éligible aux badges
- Les signalements "En cours" ne comptent pas dans le calcul
- Les signalements rejetés font baisser le taux de pertinence
@@ -32,10 +34,12 @@ Taux de pertinence = (Signalements validés / Total signalements envoyés) × 10
```
**Période de calcul** :
- Seuls les **6 derniers mois** comptent (période glissante)
- Évite que les utilisateurs se reposent sur leurs lauriers
**Justification** :
- **Simple** : 3 niveaux seulement (pas d'over-engineering)
- **Gratuit** : logique backend + affichage frontend
- **Efficace** : incite la qualité plutôt que la quantité
@@ -52,6 +56,7 @@ Taux de pertinence = (Signalements validés / Total signalements envoyés) × 10
| **Argent → Or** | 60 jours |
**Justification** :
- Évite la montée en badge trop rapide (anti-farming)
- Force une contribution régulière sur la durée
- Détecte les patterns suspects (audit modérateur si trop rapide)
@@ -63,6 +68,7 @@ Taux de pertinence = (Signalements validés / Total signalements envoyés) × 10
**IMPORTANT** : L'utilisateur doit être informé du système de récompenses **dès son premier signalement**.
**Moment d'affichage** :
- Après avoir envoyé le **premier signalement**
- Juste après le toast de confirmation standard
- **2 secondes de délai** avant affichage de la modal
@@ -102,6 +108,7 @@ Taux de pertinence = (Signalements validés / Total signalements envoyés) × 10
```
**Lien "En savoir plus"** :
- Redirection vers page dédiée expliquant :
- Calcul détaillé du taux de pertinence
- Critères d'obtention pour chaque badge
@@ -116,6 +123,7 @@ Taux de pertinence = (Signalements validés / Total signalements envoyés) × 10
#### 19.1.4 Affichage badges et statistiques
**Badge visible** :
- **Profil utilisateur** : visible par tous les autres utilisateurs
- **Historique signalements** : visible uniquement par l'utilisateur lui-même
- **Toast après obtention** :
@@ -136,10 +144,12 @@ Prochain palier : 🥇 Contributeur Or (30 signalements validés restants)
```
**Toast après traitement signalement** :
- Si validé : "✅ Bravo ! Votre signalement a aidé la communauté. Progression : 3/5 pour badge Bronze 🥉"
- Si rejeté : "❌ Signalement non retenu. Taux de pertinence : 60%. Continuez vos efforts !"
**Justification** :
- **Transparence totale** : l'utilisateur voit sa progression en temps réel
- **Motivation** : gamification saine (pas de pression, juste encouragement)
- **Gratifiant** : messages positifs valorisant la contribution
@@ -157,6 +167,7 @@ Score fiabilité = min(100, (Validés × 10 - Rejetés × 5 + Bonus_Or × 20))
```
**Détails** :
- **Validés** : nombre de signalements validés par modérateurs
- **Rejetés** : nombre de signalements rejetés
- **Bonus_Or** : +20 points si badge Or actif
@@ -181,10 +192,12 @@ Priorité = (Score_IA × 0.7) + (Signalements_cumulés × 0.2) + (Fiabilité_sig
```
**Intégration** :
- **Fiabilité_signaleur** = Score fiabilité / 100 (normalisé 0-1)
- Les signalements des utilisateurs avec badge Argent/Or passent automatiquement devant les autres (même score IA)
**Affichage à l'utilisateur** :
- **NON affiché** publiquement (risque de gamification abusive)
- **Visible** uniquement dans les stats personnelles :
```
@@ -201,6 +214,7 @@ Priorité = (Score_IA × 0.7) + (Signalements_cumulés × 0.2) + (Fiabilité_sig
**Décision** : Statut automatique pour utilisateurs Badge Argent ou Or
**Critère** :
- Badge **Argent OU Or** actif = automatiquement "Utilisateur de confiance"
**Avantages** :
@@ -209,6 +223,7 @@ Priorité = (Score_IA × 0.7) + (Signalements_cumulés × 0.2) + (Fiabilité_sig
3. **Notification différée** : résultats sous 12h (au lieu de 24-48h standards)
**Révocation** :
- Perte badge Argent/Or → perte statut confiance automatique
- Retour au statut normal, aucune sanction supplémentaire
@@ -259,10 +274,12 @@ Merci de contribuer à rendre RoadWave meilleur chaque jour !
```
**Rappels** :
- Email + Push J-7 : "Il vous reste 7 jours pour profiter de votre réduction Premium -50%"
- Email + Push J-1 : "Dernière chance ! Votre réduction Premium -50% expire demain"
**Si non activée après 30 jours** :
- Offre expirée (notification : "Votre offre Premium -50% a expiré")
- Badge Or conservé (seule l'offre expire, pas le badge)
@@ -271,16 +288,19 @@ Merci de contribuer à rendre RoadWave meilleur chaque jour !
#### 19.4.3 Perte du badge Or
**Conditions** :
- Taux de pertinence descend sous **90%** après audit trimestriel
- Signalements abusifs détectés (voir Section 19.5)
**Conséquences** :
- **Badge Or révoqué** immédiatement
- **Abonnement Premium en cours** reste actif jusqu'à sa fin normale
- **Nouvelle souscription** à prix normal (4.99€/mois)
- **Pas de nouvelle offre -50%** même si badge Or réobtenu ultérieurement
**Justification** :
- Maintien qualité badges sur le long terme
- Évite abus système
@@ -291,11 +311,13 @@ Merci de contribuer à rendre RoadWave meilleur chaque jour !
**Coût maximum** : **200€/mois** (si 50 utilisateurs Or simultanés avec réduction active)
**ROI attendu** :
- **1 utilisateur Or** = économie ~5-10h modération/mois = 75-150€ économisés (taux horaire modérateur ~15€/h)
- **10 utilisateurs Or actifs** = 750-1500€ économisés > 200€ coût réductions
- **ROI positif dès 2-3 utilisateurs Or actifs**
**Justification** :
- **Incitation forte** pour meilleurs contributeurs uniquement
- **Conversion** : utilisateurs gratuits très engagés → Premium payant après 3 mois
- **Risque limité** : coût max plafonné, largement compensé par économie modération
@@ -311,11 +333,13 @@ Merci de contribuer à rendre RoadWave meilleur chaque jour !
**Décision** : Maximum 10 signalements / 24h par utilisateur
**Règles** :
- Au-delà de 10 signalements/24h → signalements automatiquement rejetés
- Alerte modérateur automatique (enquête manuelle)
- Message utilisateur : "Limite quotidienne atteinte (10 signalements/24h). Réessayez demain."
**Justification** :
- Évite signalement massif (farming)
- 10/jour = largement suffisant pour usage légitime
- Coût : 0€
@@ -336,10 +360,12 @@ HAVING COUNT(*) > 30
```
**Action** :
- Enquête manuelle modérateur
- Révocation badge si abus confirmé
**Patterns détectés** :
- Signalement massif (>30/semaine)
- Taux de pertinence <50% malgré volume élevé
- Signalements tous rejetés sur période 7 jours
@@ -368,10 +394,12 @@ HAVING COUNT(*) > 30
```
**Après audit** :
- Email résultat : "Badge conservé ✓" ou "Badge révoqué ✗"
- Possibilité de réobtenir badge ultérieurement (pas de ban)
**Justification** :
- Maintien qualité badges sur le long terme
- Évite repos sur lauriers
- Coût : 0€ (script automatique)
@@ -387,6 +415,7 @@ HAVING COUNT(*) > 30
| **Grave** | Signalements massifs coordonnés (farming) | Ban permanent fonctionnalité signalement + révocation tous badges |
**Notification sanction** :
- Email + Push + In-app
- Explication détaillée de l'abus détecté
- Durée sanction
@@ -416,11 +445,13 @@ HAVING COUNT(*) > 30
---
**Conformité** :
- ✅ RGPD : données modération anonymisées après 3 ans
- ✅ Transparence : utilisateur informé dès le 1er signalement
- ✅ Anti-discrimination : système accessible à tous, basé uniquement sur pertinence
**Scalabilité** :
- 0-100 utilisateurs actifs : système automatique, 0€
- 100-1000 utilisateurs actifs : 0-50€/mois (quelques badges Or)
- 1000+ utilisateurs actifs : 50-200€/mois (max 50 badges Or simultanés)

View File

@@ -19,6 +19,7 @@ Liste déroulante avec 7 options :
| 🔧 **Autre** | Champ texte obligatoire si sélectionné |
**Justification** :
- Équilibre entre simplicité (pas trop de choix) et précision (aide les modérateurs)
- Coût : 0€ (liste déroulante standard)
@@ -33,6 +34,7 @@ Liste déroulante avec 7 options :
- Non bloquant : le signalement peut être envoyé sans commentaire
**Justification** :
- Encourage la qualité des signalements sans créer de friction
- Aide les modérateurs à comprendre le contexte
- Pas de risque d'abandon du processus
@@ -44,16 +46,19 @@ Liste déroulante avec 7 options :
**Décision** : Toast in-app avec lien historique
**Affichage** :
- Toast notification : "✓ Signalement envoyé. Nous l'examinerons sous 24-48h."
- Durée affichage : 5 secondes
- Bouton optionnel "Voir mes signalements" (accès historique)
**Historique personnel** :
- Liste des signalements envoyés par l'utilisateur
- Statut : En cours / Traité / Rejeté
- Notification in-app si action prise (contenu retiré, signalement rejeté)
**Justification** :
- Transparence maximale
- Coût : 0€ (aucun email automatique)
- Bonne UX
@@ -85,15 +90,18 @@ Liste déroulante avec 7 options :
4. Priorisation automatique selon score
**Délais** :
- Audio <5 min : 1-3 minutes
- Audio 5-30 min : 3-10 minutes
- Audio >30 min : 10-20 minutes
**Coût** :
- **MVP** : 0€ (CPU standard, processing asynchrone)
- **Scale** : 50-200€/mois (GPU VPS si >1000 signalements/jour)
**Justification** :
- 100% open source, pas de dépendance GAFAM
- Coût maîtrisé (scaling progressif)
- Gain productivité modérateurs ×3-5
@@ -112,10 +120,12 @@ Liste déroulante avec 7 options :
| **BASSE** | <72h (jours ouvrés) | Qualité audio, tags incorrects → Modérateur junior |
**Traitement automatique** :
- Score IA >95% + catégorie évidente (ex: spam répété) → Action automatique immédiate
- Notification créateur + possibilité d'appel
**Justification** :
- Réaliste et conforme DSA (Digital Services Act)
- Scalable : priorisation automatique
- Ressources humaines optimisées
@@ -133,17 +143,20 @@ Priorité = (Score_IA × 0.7) + (Signalements_cumulés × 0.2) + (Fiabilité_sig
```
**Détails** :
- **Score_IA** : 0-100% (confiance analyse automatique)
- **Signalements_cumulés** : nombre de signalements du même contenu (boost priorité)
- **Fiabilité_signaleur** : score utilisateur (historique signalements pertinents)
**Classification résultante** :
- Priorité ≥90 → **CRITIQUE** (traitement immédiat)
- Priorité 70-89 → **HAUTE** (file prioritaire)
- Priorité 40-69 → **MOYENNE** (file normale)
- Priorité <40 → **BASSE** (file différée)
**Justification** :
- Optimise le temps des modérateurs
- Traite les cas graves en priorité
- Coût : 0€ (algorithme simple)
@@ -186,11 +199,13 @@ L'équipe RoadWave
```
**Coût** :
- Email : ~0.001€/notification (Brevo, Resend)
- Push : 0€ (APNS / FCM natifs)
- In-app : 0€
**Justification** :
- Conformité DSA (transparence obligatoire)
- Multi-canal garantit réception
- Coût négligeable
@@ -232,6 +247,7 @@ L'équipe RoadWave
```
**Justification** :
- Transparence maximale (obligation DSA)
- Créateur comprend l'erreur → amélioration future
- Réduit les appels non fondés
@@ -243,6 +259,7 @@ L'équipe RoadWave
**Décision** : Formulaire in-app structuré
**Accès** :
- Bouton "Contester cette décision" dans notification
- Section "Mes sanctions" dans profil créateur
@@ -256,15 +273,18 @@ L'équipe RoadWave
| **Preuves** | Upload fichiers (max 5, 10 MB total) | ❌ |
**Après soumission** :
- Génération numéro de ticket unique (ex: `#MOD-2026-00142`)
- Email confirmation : "Votre appel sera traité sous 72h"
- Statut visible dans l'app : "En cours d'examen"
**Délai de soumission** :
- Maximum **7 jours** après notification de sanction
- Après 7 jours : appel automatiquement refusé
**Justification** :
- Professionnel et traçable
- Intégration complète avec système modération
- Coût : 0€ (formulaire custom backend)
@@ -284,6 +304,7 @@ L'équipe RoadWave
| **Critique** | 24h (cas suspension longue/ban) | Admin modération |
**Notification intermédiaire** (si délai >72h) :
- Email J+3 : "Votre appel #MOD-XXX est en cours d'examen approfondi. Réponse sous 2 jours."
**Réponse finale** :
@@ -295,10 +316,12 @@ Email détaillé avec :
4. **Définitif** : mention "Cette décision est définitive" (pas de second appel)
**Suivi in-app** :
- Mise à jour statut : "Appel accepté ✓" ou "Appel rejeté ✗"
- Badge notification
**Justification** :
- Équilibre entre rapidité et qualité de traitement
- Conforme pratiques industrie (YouTube, TikTok : 5-7 jours)
- Ressources humaines réalistes
@@ -329,6 +352,7 @@ Email détaillé avec :
5. **Fil d'activité** : actions récentes équipe (temps réel)
**Coût infrastructure** :
- MVP : 0-50€/mois (serveur CPU)
- Scale : 50-200€/mois (GPU + Redis Cluster)
@@ -337,20 +361,24 @@ Email détaillé avec :
### 14.5 Modération préventive (rappel)
**Nouveaux créateurs** :
- Validation manuelle des **3 premiers contenus**
- Délai : 24-48h (jours ouvrés)
- Transcription automatique pour aide modérateur
**Score de confiance** :
- Évolution dynamique selon historique
- Créateur fiable (0 strike depuis 6 mois) → validation automatique
- Créateur suspect (strikes récents) → validation manuelle systématique
**Publicités** :
- Validation manuelle obligatoire 24-48h (responsabilité juridique)
- Transcription + analyse métadonnées (ciblage, durée, volume)
**Justification** :
- Prévention > réaction (économie modération)
- Qualité plateforme préservée dès le début
@@ -375,11 +403,13 @@ Email détaillé avec :
**Coût total MVP** : **0-200€/mois** (infrastructure IA optionnelle)
**Conformité** :
- ✅ DSA (Digital Services Act) : transparence, traçabilité, délais
- ✅ RGPD : données modération anonymisées après 3 ans
- ✅ Logs audit : toutes actions tracées (obligation légale plateforme)
**Scalabilité** :
- 0-1000 signalements/mois : équipe 1-2 modérateurs junior + 1 senior
- 1000-10K signalements/mois : équipe 5-10 modérateurs + IA GPU
- 10K+ signalements/mois : équipe dédiée + IA optimisée + modération communautaire

View File

@@ -64,6 +64,7 @@ stateDiagram-v2
## Légende
**États principaux** :
- **Reçu** : Signalement initial (<1s)
- **EnTranscription** : Whisper large-v3 (1-20 min)
- **EnAnalyseIA** : Score confiance 0-100% (<1 min)

View File

@@ -22,6 +22,7 @@ Le domaine **Monetization** gère la monétisation des créateurs de contenu via
## Ubiquitous Language
**Termes métier du domaine** :
- **Creator Monetization** : Activation de la monétisation pour un créateur
- **KYC Verification** : Vérification d'identité requise pour versements
- **Revenue Share** : Partage de revenus (70% créateur / 30% plateforme)

View File

@@ -5,6 +5,7 @@
**Décision** : ❌ Fonctionnalité abandonnée pour le MVP
**Raisons** :
- Complexité juridique (collecte pour compte de tiers, TVA variable)
- Frais de transaction élevés sur petits montants (Mangopay ~1.8% + 0.18€)
- UX additionnelle à développer (wallet, transactions, confirmations)
@@ -29,11 +30,13 @@
**Vérification** : Automatique via requêtes SQL lors de la demande d'activation
**Affichage** :
- Bouton "Demander la monétisation" dans profil créateur
- Si critères non remplis → affichage progression vers objectifs
- Si critères remplis → redirection vers KYC Mangopay
**Justification** :
- **Anti-fraude** : Le délai de 3 mois permet de détecter les comptes suspects
- **Qualité** : Seuls les créateurs sérieux avec audience réelle sont monétisés
- **Coût administratif** : Réduit le nombre de comptes à gérer (KYC, comptabilité, virements)
@@ -46,6 +49,7 @@
**Décision** : Statut juridique professionnel obligatoire
**Statuts acceptés** :
- Auto-entrepreneur (micro-BNC pour artistes/créateurs de contenu)
- SARL/SAS/SASU (sociétés)
@@ -64,17 +68,20 @@
**Délai** : 24-72h si documents conformes
**Rejet possible si** :
- Documents invalides/illisibles
- Identité ne correspond pas au compte RoadWave
- Liste noire anti-blanchiment (vérification automatique Mangopay)
- RIB non professionnel (particulier)
**Base légale** :
- **Conformité fiscale** : L'État français impose déclaration revenus >1200€/an (DAS2)
- **Anti-blanchiment** : Directive EU 2018/843 (5ème directive LCB-FT)
- **RGPD** : Données hébergées EU via Mangopay (conforme)
**Justification** :
- **Responsabilité légale** : RoadWave doit pouvoir prouver identité réelle créateurs monétisés
- **Automatisation** : Mangopay gère tout (KYC, vérifications, conformité, e-wallets)
- **KYC gratuit** : inclus dans l'offre Mangopay (vs 1.20€ chez Stripe)
@@ -101,16 +108,19 @@ Publicité facturée par RoadWave : 0.05€/écoute complète = 50€ CPM
```
**Exemple concret** :
- 10 000 écoutes/mois → créateur touche **30€**
- 50 000 écoutes/mois → créateur touche **150€**
- 100 000 écoutes/mois → créateur touche **300€**
**Comparaison industrie** :
- YouTube : 3-5€/1000 vues
- Spotify : 3-4€/1000 écoutes
- RoadWave : 3€/1000 écoutes (aligné)
**Règles comptabilisation** :
- ✅ Écoute complète = ≥80% du contenu écouté
- ✅ Utilisateur gratuit uniquement
- ❌ Écoutes Premium ne comptent pas ici (autre système)
@@ -130,6 +140,7 @@ Utilisateur Premium = 4.99€/mois
└─ 1.50€ gardés par plateforme (30%)
Si l'utilisateur écoute 3 créateurs ce mois :
- Créateur A : 10h d'écoute (50%) → 1.75€
- Créateur B : 6h d'écoute (30%) → 1.05€
- Créateur C : 4h d'écoute (20%) → 0.70€
@@ -151,12 +162,14 @@ GROUP BY creator_id;
```
**Comparaison industrie** :
- YouTube Premium : 70/30
- Spotify : 70/30
- Apple Music : 52/48 (moins avantageux)
- RoadWave : 70/30 (standard)
**Justification** :
- **Standard industrie** : ratio équitable éprouvé
- **Incitation qualité** : créateurs les plus écoutés gagnent plus
- **Équité** : pas de "winner takes all", chaque créateur écouté reçoit sa part
@@ -178,6 +191,7 @@ GROUP BY creator_id;
- Solde conservé **indéfiniment** SI créateur actif
- Critère activité : >0 écoute/mois OU connexion dashboard/mois
- Solde visible en temps réel dans dashboard créateur
**Créateur inactif** (0 écoute/mois + 0 connexion dashboard) :
@@ -191,11 +205,13 @@ GROUP BY creator_id;
| **18 mois + 37j** | Purge données comptables | (Conservation logs 10 ans RGPD) |
**Exception soldes <10€** :
- Si solde <10€ après 18 mois → Frais bancaires (0.36€) > 3.6% du montant
- Proposition email : "Don association ou conservation jusqu'à 50€"
- Si don refusé + inactivité continue → versement forcé quand même (équité)
**Frais bancaires assumés par créateur** :
- Mangopay SEPA : 1.8% + 0.18€
- Exemple : 45€ → versement **44.64€** net
- Transparence totale dans email préavis
@@ -215,6 +231,7 @@ Votre solde actuel : XX.XX€
→ Montant net estimé : XX.XX€
💡 Pour éviter le versement anticipé :
- Publiez un nouveau contenu, OU
- Connectez-vous à votre dashboard créateur
@@ -234,6 +251,7 @@ L'équipe RoadWave
| **Frais bancaires** | ❓ Non documenté | Déduits + annoncés | ✅ RoadWave transparent |
**Justification** :
- **Plus équitable que Twitch** : versement forcé au lieu de forfeiture (créateur récupère son argent)
- **Emails préventifs** : 3 relances (12 mois, 18 mois, 18 mois + 30j) avant action
- **Transparence** : frais bancaires annoncés clairement dans emails
@@ -253,6 +271,7 @@ L'équipe RoadWave
| **16-18 du mois suivant** | Réception virement (1-3 jours ouvrés SEPA) |
**Virement via Mangopay** :
- SEPA pour comptes EU (gratuit, 1-3 jours)
- Virement international hors EU (frais variables selon pays, rare en pratique)
- **E-wallets automatiques** : chaque créateur possède un wallet Mangopay où ses revenus sont transférés automatiquement
@@ -281,27 +300,32 @@ L'équipe RoadWave
**Décision** : Créateur décide individuellement pour chaque contenu
**Fonctionnement** :
- Toggle "Réservé Premium" lors création/édition contenu
- **Aucune limite imposée** : créateur peut mettre 0%, 50% ou 100% en premium
- Badge 👑 visible sur interface utilisateur
**Comportement utilisateurs gratuits** :
- Contenu premium visible dans liste/algo
- Tentative lecture → overlay bloquant
- Message : "Ce contenu est réservé aux abonnés Premium"
- CTA : "Passez Premium pour 4.99€/mois"
**Comportement algorithme** :
- Contenus premium inclus dans recommandations
- Si user gratuit → contenu skippé automatiquement (ne consomme pas de slot)
- Si user premium → diffusé normalement
**Métadonnées** :
- Champ `is_premium` (boolean) en base
- Index sur ce champ pour requêtes rapides
- Cache Redis : `content:{id}:premium` (TTL 1h)
**Justification** :
- **Liberté créateur** : chaque créateur choisit sa stratégie (freemium, tout gratuit, tout premium)
- **Incitation Premium** : contenu exclusif = argument fort pour s'abonner
- **Équité** : un petit créateur peut tout mettre en premium, un gros peut tout offrir gratuitement
@@ -330,6 +354,7 @@ L'équipe RoadWave
> Bien que le seuil légal DAS2 soit 1200€/an, rien n'interdit de déclarer les montants inférieurs. Au contraire, cela renforce la transparence et protège RoadWave en cas de contrôle fiscal.
**Avantages** :
-**Conformité maximale** : aucune zone grise
-**Protection juridique RoadWave** : traçabilité totale
-**Simplicité technique** : même processus pour tous
@@ -344,6 +369,7 @@ Objet : Votre déclaration fiscale 2026 RoadWave
Bonjour [Créateur],
Vos revenus RoadWave 2026 ont été déclarés aux impôts (DAS2) :
- Revenus publicité : XXX.XX€
- Revenus Premium : XXX.XX€
- Total déclaré : XXX.XX€
@@ -358,12 +384,14 @@ L'équipe RoadWave
```
**Créateur responsable de** :
- Déclarer ses revenus à l'URSSAF (cotisations sociales auto-entrepreneur ou IS/IR)
- Déclarer ses revenus aux impôts (IR ou IS selon statut)
- Gérer sa TVA si applicable (franchise en base jusqu'à ~37K€/an en micro-BNC)
- Conserver justificatifs **10 ans** (obligation légale comptable)
**Mangopay transmet automatiquement** :
- Données aux autorités fiscales EU via **DAC7** (directive 2021/514)
- Justificatif de chaque virement (preuve bancaire pour comptabilité créateur)
@@ -376,6 +404,7 @@ Si créateur a touché 2500€ en 2026 :
```
**Justification** :
- **Conformité légale** : RoadWave doit déclarer revenus versés (DAS2, DAC7)
- **Responsabilité fiscale** : Le créateur reste responsable de sa déclaration (impossible de gérer pour lui)
- **Automatisation** : Minimise charge administrative côtés créateur et plateforme
@@ -385,6 +414,7 @@ Si créateur a touché 2500€ en 2026 :
### 9.8 Désactivation et suspension monétisation
**Créateur peut** :
- Désactiver temporairement (vacances, pause création)
- Réactiver sans refaire KYC si données à jour (<2 ans)
- Solde conservé pendant désactivation
@@ -399,16 +429,19 @@ Si créateur a touché 2500€ en 2026 :
| **Fraude détectée** | Suspension immédiate + enquête | Cas par cas |
**Suppression définitive si** :
- Demande du créateur (solde versé sous 30 jours)
- Inactivité 24 mois + solde <50€ (purge RGPD)
- Ban définitif compte (Strike 4)
**Notification** :
- Email + in-app pour toute suspension
- Raison explicite fournie
- Procédure de réactivation indiquée
**Justification** :
- **Flexibilité** : créateur peut faire pause sans perdre statut
- **Sécurité** : plateforme doit pouvoir suspendre en cas problème légal/technique
- **RGPD** : suppression auto données inactives après délai raisonnable

View File

@@ -24,6 +24,7 @@ Le domaine **Premium** gère les abonnements payants et les fonctionnalités exc
## Ubiquitous Language
**Termes métier du domaine** :
- **Premium Subscription** : Abonnement payant mensuel ou annuel
- **Offline Download** : Téléchargement pour écoute hors-ligne
- **Sync Queue** : File d'attente de synchronisation offline

View File

@@ -5,6 +5,7 @@
**Décision** : Boost +30% au score + reste dans le mix
**Boost de score abonnements** :
- **+30% au score final** pour contenus d'un créateur suivi
- Application : multiplicateur sur le score calculé
@@ -13,6 +14,7 @@ score_final_avec_boost = score_final × 1.3
```
**Reste dans le mix** :
-**Pas de priorité absolue** (pas de file dédiée abonnements)
- ✅ Contenu suivi entre en **compétition avec autres contenus**
- ✅ Si créateur suivi publie contenu faible engagement → peut être battu par contenu viral non-suivi
@@ -22,12 +24,14 @@ score_final_avec_boost = score_final × 1.3
Utilisateur à Paris, 2 contenus disponibles :
Contenu A (créateur NON suivi) :
- Score géo : 0.9 (très proche)
- Score intérêts : 0.8
- Score engagement : 0.7
→ Score final : 0.80
Contenu B (créateur suivi) :
- Score géo : 0.5 (moyennement proche)
- Score intérêts : 0.6
- Score engagement : 0.5
@@ -45,6 +49,7 @@ Contenu B (suivi) : score 0.60 → avec boost 0.78
```
**Justification** :
- **Équilibre** : valorise abonnements sans enfermer utilisateur
- **Découverte** : contenus viraux/locaux peuvent toujours émerger
- **Prévisible** : boost fixe, pas de logique opaque
@@ -104,16 +109,19 @@ Tap pour explorer
```
**Filtrage géographique** :
- Si contenu/live hors zone utilisateur → **pas de notification**
- Évite frustration : "notification pour contenu que je ne peux pas écouter"
- Exception : contenu national → notifie tous les abonnés
**Fréquence maximale** :
- **Maximum 10 notifications push/jour** par utilisateur (tous types confondus)
- Si dépassement : notifications regroupées
- Message groupé : "🎧 3 nouveaux contenus de créateurs suivis"
**Plages horaires** :
- **Mode silencieux** : 22h-8h (pas de push, sauf live)
- Paramétrable utilisateur (désactivation totale possible)
- Option "Notifications importantes uniquement" (lives uniquement)
@@ -129,6 +137,7 @@ Tap pour explorer
| **Limite quotidienne** | 10 | Modifiable 5-20 |
**Justification** :
- **Sécurité routière** : pas de push en conduite (distraction)
- **Engagement piéton** : push actifs pour audio-guides (valeur ajoutée tourisme)
- **Pas de spam** : limite 10/jour + mode silencieux
@@ -207,10 +216,12 @@ Liste des séquences :
| **Quitter** | Tap "×" | Sauvegarde progression, sortie guide |
**Guidage vocal automatique** :
- Entre 2 séquences : "Vous avez terminé la séquence 2. Dirigez-vous vers la Vénus de Milo pour la séquence 3."
- Si utilisateur s'éloigne (>50m de la prochaine pièce) : "Vous vous éloignez de la prochaine étape. Consultez le plan."
**Sauvegarde progression** :
- Position dans guide sauvegardée automatiquement
- Retour ultérieur : "Reprendre à la séquence 5 ?" ou "Recommencer depuis le début"
- Historique : guide marqué "Terminé" si toutes séquences écoutées
@@ -251,6 +262,7 @@ Liste des séquences :
```
**Justification** :
- **UX piéton** : navigation tactile adaptée (pas de commandes volant)
- **Autonomie** : utilisateur maître de son rythme (pas d'enchaînement forcé)
- **Choix** : plusieurs guides = diversité styles (famille, expert, rapide)
@@ -264,6 +276,7 @@ Liste des séquences :
**Décision** : 200 abonnements max + désabonnement -5% jauges
**Nombre maximum d'abonnements** :
- **200 créateurs maximum** par utilisateur
- Raisons :
- **Évite spam** : au-delà de 200, notifications ingérables
@@ -271,16 +284,19 @@ Liste des séquences :
- **Performance** : requêtes SQL optimisées (index sur 200 max)
**Si limite atteinte** :
- Message : "Vous suivez déjà 200 créateurs. Désabonnez-vous d'un créateur pour en suivre un nouveau."
- Liste triable : par date abonnement, nb contenus écoutés, dernière activité
- Suggestion : "Vous n'avez pas écouté [Créateur X] depuis 6 mois, le désabonner ?"
**Abonnement initial** :
- Impact : **+5% toutes jauges tags du créateur** (voir [Règle 05 - Section 5.3](../../recommendation/rules/interactions-navigation.md#actions-complémentaires-mode-piéton-uniquement))
- Action : Bouton "S'abonner" dans profil créateur (interface mobile)
- Immédiat à l'action
**Désabonnement** :
- Impact : **-5% toutes jauges tags du créateur** (symétrique)
- Action : Bouton "Se désabonner" dans profil créateur
- Immédiat à l'action
@@ -300,15 +316,18 @@ Abonnement :
```
**Gestion multi-tags** :
- Si créateur a 3 tags → **+5% sur chacun des 3 tags**
- Logique : abonnement = signal fort d'affinité à TOUS les sujets du créateur
**Abonnements réciproques** :
-**Pas d'abonnement mutuel visible**
- Créateur ne voit pas qui est abonné (privacy)
- Créateur voit uniquement : nombre total abonnés (métrique globale)
**Justification** :
- **Limite 200** : équilibre entre liberté et gestion spam
- **Symétrie +5%/-5%** : cohérence mathématique, prévisibilité
- **Privacy** : pas de liste publique abonnés (évite stalking)

View File

@@ -5,6 +5,7 @@
**Zone géographique** : Choix manuel utilisateur
**Options prédéfinies** :
- "Autour de moi" (rayon 50 km position actuelle)
- "Ma ville" (limite administrative détectée)
- "Mon département" (sélection liste)
@@ -19,6 +20,7 @@
| **Premium** | Illimité | "245 contenus (3.2 GB)" |
**Calcul temps disponible** :
- 50 contenus × 5 min moyenne = 250 min = **4h d'écoute** (suffisant pour gratuits)
- Premium illimité = limité uniquement par espace disque device
@@ -47,6 +49,7 @@ Exemple : 20 contenus × 5 min × 48 kbps = ~72 MB
| **Haute** | 64 kbps | ~30 MB/h | **Premium uniquement** |
**Justification** :
- Standard = bon compromis qualité/taille (Opus 48 kbps = très correct pour voix)
- Haute réservée Premium = incitation upgrade
- User peut réduire à "basse" si espace limité
@@ -58,6 +61,7 @@ Exemple : 20 contenus × 5 min × 48 kbps = ~72 MB
**Durée de validité** : 30 jours après téléchargement
**Standard industrie** :
- Spotify : 30 jours
- YouTube Music : 30 jours
- Deezer : 30 jours
@@ -77,11 +81,13 @@ App détecte WiFi + contenus >25 jours
```
**Notification avant expiration** :
- **J-3** : "X contenus expirent dans 3 jours. Connectez-vous en WiFi pour les renouveler"
- **J-0** : Suppression automatique
- **J+0** : Toast "15 contenus expirés ont été supprimés"
**Justification** :
- **Force reconnexion** : vérifier abonnement actif, contenus légaux
- **Évite stockage obsolète** : contenus supprimés/modérés ne restent pas
- **UX transparente** : renouvellement silencieux si WiFi régulier
@@ -91,6 +97,7 @@ App détecte WiFi + contenus >25 jours
### 11.3 Synchronisation actions offline
**Actions stockées localement (SQLite)** :
- Likes/unlikes
- Abonnements/désabonnements
- Signalements
@@ -108,11 +115,13 @@ App détecte WiFi + contenus >25 jours
```
**Gestion erreurs sync** :
- Si échec après 3 tentatives → notification : "Impossible de synchroniser. Réessayez plus tard"
- Actions conservées jusqu'à sync réussie (pas de perte)
- **Rétention max 7 jours** : après = purge (évite queue infinie)
**Justification** :
- **Pas de conflit possible** : actions unilatérales user (likes/abonnements)
- **UX fluide** : pas de blocage offline
- **Batch = économie** : requêtes HTTP groupées
@@ -187,17 +196,20 @@ User se reconnecte (WiFi détecté)
```
**Bouton "Voir la liste"** :
- Affiche titres + créateurs des contenus supprimés
- Permet comprendre ce qui a disparu
- Historique conservé 7 jours (puis purge)
**Justification KISS** :
-**Simplicité technique** : pas de grace period complexe, pas de gestion d'états intermédiaires
-**Respect créateur** : si créateur supprime = volonté claire immédiate, pas de diffusion prolongée
-**Conformité légale** : contenu modéré (illégal, violation CGU) retiré immédiatement, pas de risque juridique
-**Cas rare** : peu de créateurs suppriment contenus après publication, impact user limité
**Post-MVP** : Si feedback négatifs users ("J'étais en train d'écouter et ça s'est coupé brutalement !"), ajouter grace period UNIQUEMENT pour suppression créateur volontaire :
- Motif suppression = "modération RoadWave" → Suppression immédiate (sécurité/légalité)
- Motif suppression = "créateur volontaire" → Grace period 7 jours + badge "Bientôt retiré"
- Motif suppression = "passage Premium" → Si user Premium : conserve accès, si gratuit : grace period 7j

View File

@@ -12,6 +12,7 @@
**❌ Pas d'essai gratuit**
**Raisons** :
- **Anti-abus vacances** : évite inscriptions opportunistes (essai 14j avant road trip vacances, puis annulation)
- **Protection revenus créateurs** : les écoutes Premium rémunèrent créateurs dès jour 1
- **Simplicité** : pas de gestion période trial + conversion
@@ -20,6 +21,7 @@
**❌ Pas de partage familial (MVP)**
**Raisons** :
- Complexité technique (gestion invitations, validation liens, limite devices)
- Risque abus ("familles" de 6 inconnus)
- Coût dev/support élevé pour ROI incertain
@@ -27,6 +29,7 @@
- **Post-MVP** : Si forte demande, offre "Famille" à 9.99€/mois pour 5 comptes
**Justification tarif** :
- **Aligné marché bas** : Spotify = 10.99€, YouTube Premium = 11.99€, Apple Music = 10.99€
- **Prix accessible** : cible conducteurs quotidiens (budget raisonnable)
- **Incitation annuel** : 2 mois offerts = engagement long terme + réduction churn
@@ -100,6 +103,7 @@ Device 1 vraiment offline (mode avion, tunnel)
```
**Boutons** :
- **Reprendre ici** : Coupe l'autre device, reprend lecture sur ce device
- **Sécuriser mon compte** : Lien vers changement mot de passe + déconnexion tous devices
@@ -119,6 +123,7 @@ Contenus téléchargés valides 30 jours
#### Détection abus (post-MVP)
Monitoring patterns suspects (backend analytics) :
- >10 changements devices/jour (suspect)
- Connexions alternées 2 villes éloignées répétées
- Signalements users : "je n'ai jamais été à Marseille"
@@ -131,6 +136,7 @@ Action :
**Pas d'action automatique** (évite faux positifs), juste flag modération manuelle.
**Justification KISS** :
-**Simplicité technique** : pas de tracking GPS précis, pas de calcul distances, pas de faux positifs (TGV Paris→Lyon = légitime)
-**Assume bonne foi** : majorité users honnêtes, partage compte = minorité, gestion réactive suffit
-**Message dissuasif clair** : avertissement CGU dans message coupure, possibilité "Sécuriser compte" si suspicion piratage
@@ -144,12 +150,14 @@ Action :
**Décision** : Créateur décide (déjà couvert section 9.6)
**Rappel règles** :
- Toggle "Réservé Premium" par contenu
- Aucune limite de ratio gratuit/premium
- Badge 👑 visible
- Users gratuits : lecture bloquée avec CTA "Passez Premium"
**Impact algorithme** :
- Contenus premium inclus dans recommandations
- Si user gratuit → skip automatique (ne consomme pas slot)
- Si user premium → diffusé normalement selon score
@@ -169,10 +177,12 @@ Action :
| **Historique écoute** | 100 derniers | Illimité |
**Qualité audio** :
- Gratuit : 48 kbps Opus (~20 MB/h) = très correct pour voix
- Premium : 64 kbps Opus (~30 MB/h) = excellente qualité
**Justification différences** :
- **0 pub** = argument principal (confort écoute)
- **Qualité audio** = avantage tangible audiophiles
- **Offline illimité** = use case road trips longs
@@ -191,23 +201,27 @@ Action :
| **Android App** | Google Play Billing | 5.99€ | 30% (Google) |
**Majoration mobile (5.99€)** :
- Apple/Google prennent 30% de commission
- RoadWave majore prix de 20% pour compenser
- **Incitation web** : Email aux users "Abonnez-vous sur roadwave.com pour 4.99€/mois" (38% moins cher en frais !)
**Renouvellement automatique** :
- Email rappel **7 jours avant** renouvellement
- Email confirmation **après** renouvellement réussi
- Retry automatique si échec paiement (3 tentatives sur 7 jours)
- Annulation automatique après 3 échecs
**Annulation** :
- Self-service dans Settings app : "Abonnement > Annuler"
- Accès Premium maintenu jusqu'à **fin période payée**
- Pas de remboursement prorata (standard industrie)
- Email confirmation annulation avec date fin d'accès
**Réabonnement** :
- Possibilité immédiate
- ❌ Pas de nouvelle période d'essai (pas d'essai du tout)
@@ -235,6 +249,7 @@ CREATE TABLE subscriptions (
```
Cache Redis : premium:{user_id} → boolean (TTL 1h)
Refresh via webhooks :
- Mangopay : PAYIN_NORMAL_SUCCEEDED, PAYIN_NORMAL_FAILED
- Apple : App Store Server Notifications
- Google : Real-time Developer Notifications

View File

@@ -31,6 +31,7 @@ Le domaine **Recommendation** gère le système de recommandation de contenus ba
## Ubiquitous Language
**Termes métier du domaine** :
- **Interest Gauge** : Jauge de centre d'intérêt (score de 0 à 100)
- **Interest Category** : Catégorie d'intérêt (automobile, voyage, musique, etc.)
- **Recommendation Score** : Score combinant distance géographique et affinité d'intérêt

View File

@@ -204,6 +204,7 @@ godog run features/recommendation/scoring-recommandation.feature --tags=@calcul
## CI/CD
Ces tests sont exécutés :
- ✅ Avant chaque release
- ✅ Sur les PRs modifiant l'algorithme de recommandation
- ✅ Nightly builds (tous les tests)

View File

@@ -11,11 +11,13 @@
| **Géo-neutre** | Universel, pas de lien géo | Podcast philosophie, musique | 20% |
**Qui décide** :
- ✅ Créateur choisit le type à la publication
- ✅ Modération peut reclassifier après validation
- ✅ Modification possible après publication (tout le monde a le droit de se tromper)
**Justification** :
- Différencie audio-guide (hyper-local) des podcasts génériques
- Algorithme adapte automatiquement la pondération
- Coût : champ supplémentaire en DB + règle algo
@@ -33,6 +35,7 @@ score_final = (score_geo * poids_geo_type)
+ (bonus_aleatoire)
où :
- score_geo = 1 - (distance_km / distance_max_km)
- score_interets = moyenne des jauges utilisateur pour les tags du contenu
- score_engagement = (taux_completion * 0.5) + (ratio_likes * 0.3) + (ratio_abonnements * 0.2)
@@ -42,6 +45,7 @@ où :
#### Calcul détaillé du score_interets
**Domaine des données** :
- Jauges utilisateur : stockées en pourcentage [0-100]
- score_interets : normalisé dans l'intervalle [0.0-1.0] pour pondération
@@ -50,6 +54,7 @@ où :
score_interets = (SUM(gauge_values_for_tags) / NB_TAGS) / 100
où :
- gauge_values_for_tags = valeurs des jauges correspondant aux tags du contenu
- NB_TAGS = nombre de tags du contenu (minimum 1, maximum 3)
- Division par 100 pour normaliser [0-100] → [0.0-1.0]
@@ -61,6 +66,7 @@ Contenu : "Visite du Louvre"
Tags : ["Musique", "Tourisme"]
Utilisateur :
- Jauge "Musique" = 75%
- Jauge "Tourisme" = 60%
- Jauge "Automobile" = 40% (non pertinente, ignorée)
@@ -79,6 +85,7 @@ score_final = (score_geo * 0.5) + (score_interets * 0.3) + (score_engagement * 0
```
**Cas limites** :
- Utilisateur n'a aucune jauge pour les tags du contenu → score_interets = 0.5 (valeur neutre par défaut)
- Contenu avec 1 seul tag → score_interets = gauge_value / 100
- Jauges multiples → moyenne arithmétique simple (pas de pondération différente par tag)
@@ -93,6 +100,7 @@ score_final = (score_geo * 0.5) + (score_interets * 0.3) + (score_engagement * 0
| Géo-neutre | 0.2 | 0.6 |
**Paramètres** :
- Distance max recommandée : **200 km**
- Dégradation : **linéaire** (1 - distance/200km)
- Rayon point GPS : **500m** (adapté au volume de contenu local)
@@ -100,6 +108,7 @@ score_final = (score_geo * 0.5) + (score_interets * 0.3) + (score_engagement * 0
**Tous ces paramètres sont configurables à chaud via interface admin.**
**Justification** :
- Flexibilité totale selon type de contenu
- Linéaire = rattrapage naturel du contenu viral ancien
- Auditable via métriques engagement (moyenne/médiane)
@@ -111,6 +120,7 @@ score_final = (score_geo * 0.5) + (score_interets * 0.3) + (score_engagement * 0
**Décision** : Intégration popularité avec poids 0.2
**Métriques** :
- **Taux de complétion** : écoutes >80% / total écoutes pertinentes (poids 0.5)
- **Ratio likes** : likes / écoutes (poids 0.3)
- **Ratio abonnements** : nouveaux abonnés après écoute / écoutes (poids 0.2)
@@ -145,19 +155,23 @@ GROUP BY content_id;
```
**Seuil minimum** :
- Minimum **50 écoutes pertinentes** avant de considérer l'engagement
- Contenu <50 écoutes : score engagement = 0.5 (neutre)
**Contenu viral** :
- Un contenu viral à Paris **peut** être proposé à Marseille
- Score géo faible compensé par score engagement élevé
- Paramétrable admin
**Dépréciation temporelle** :
- Pas de dépréciation automatique
- Ratio linéaire = contenu ancien mais toujours apprécié reste pertinent
**Justification** :
- Équilibre découverte / qualité
- **Protection créateur** : abonnés fidèles ne pénalisent pas les métriques
- **Anti-raid naturel** : skips via search/direct_link ne comptent pas (raid inefficace)
@@ -172,16 +186,19 @@ GROUP BY content_id;
**Décision** : 10% par défaut, paramétrable utilisateur
**Fonctionnement** :
- 1 contenu sur 10 = tirage aléatoire (hors historique déjà écouté)
- Utilisateur peut ajuster : curseur 0% (aucun aléatoire) à 50% (exploration max)
**Curseur utilisateur** :
- 🎯 **0%** : Personnalisé max (recommandations strictes)
- ⚖️ **10%** : Équilibré (défaut)
- 🎲 **30%** : Découverte élevée
- 🌍 **50%** : Découverte max (équivaut à national = découverte)
**Justification** :
- Évite la bulle de filtre
- Laisse l'utilisateur maître de son expérience
- Coût : variable aléatoire en algo
@@ -195,23 +212,27 @@ GROUP BY content_id;
**Décision MVP** : Tag simple "Politique" sans classification idéologique
**Tagging** :
- Créateur peut taguer son contenu comme "Politique" (optionnel)
- Tag "Politique" au même niveau que "Économie", "Sport", "Culture", etc.
- **Pas de classification gauche/droite**
- **Pas d'équilibrage imposé**
**Filtrage utilisateur** :
- Option paramètres : **"Masquer contenu politique"**
- Si activé → 0% de contenus tagués "Politique" dans le feed
- Par défaut : désactivé (tous contenus visibles)
**Justification MVP** :
- **Simplicité** : Pas de modération politique coûteuse (~2000€/mois économisés)
- **Neutralité technique** : Aucun jugement éditorial sur orientation
- **Risque minimal** : Évite controverses et contentieux DSA au lancement
- **Fonctionnel** : Utilisateurs peuvent filtrer si souhaité
**Post-MVP** :
- Classification avancée possible si forte demande utilisateurs
- Nécessite ressources modération dédiées et audit DSA
@@ -230,22 +251,26 @@ GROUP BY content_id;
| **13-15 ans** | Collège | Contenus "Tous publics" uniquement | Filtrage 16+ et 18+ |
**Activation** :
-**Pas d'activation automatique** (tous les utilisateurs ont ≥13 ans)
-**Activation manuelle** via toggle paramètres
- ✅ Parents peuvent activer pour leurs enfants 13-15 ans
- ✅ Utilisateur peut désactiver à tout moment
**Filtrage quand Mode Kids activé** :
- ✅ Contenus "Tous publics" uniquement
- ❌ Exclusion contenus 16+ et 18+
- ❌ Pas de contenu politique (automatiquement filtré)
- ❌ Pas de publicité (ou uniquement pub validée manuellement)
**Interface** :
- Interface standard (pas d'interface dédiée enfants pour MVP)
- Filtrage algorithmique des contenus inappropriés
**Justification** :
- **Conformité légale** : Âge minimum 13 ans (RGPD, DSA)
- **Simplicité MVP** : Un seul mode optionnel vs 4 tranches d'âge
- **Protection mineurs** : Filtrage contenus adultes pour 13-15 ans
@@ -266,15 +291,18 @@ GROUP BY content_id;
6. Si ignoré → contenu proposé normalement en file d'attente
**Publicités** :
- ⚠️ **Jamais d'interruption** de contenu en cours
- Pub s'intercale **entre deux séquences** uniquement
- Notification pub : son différent (facultatif selon paramètres)
**Gestion demi-tour** :
- Si utilisateur repart du point après notification → pas de nouvelle notification (déjà proposé)
- Réinitialisation après 24h
**Justification** :
- Respect écoute en cours (pas de coupure brutale)
- UX fluide (utilisateur garde contrôle)
- Simplicité technique (pas de prédiction trajectoire)
@@ -295,17 +323,20 @@ GROUP BY content_id;
| **Partiellement écouté** | 10-80% | Peu importe | ✅ Reproposer avec reprise position (`last_position_seconds`) |
**Stockage historique** :
- Table `user_content_history` (user_id, content_id, creator_id, **is_subscribed**, completion_rate, last_position, listened_at)
- Historique **illimité** (PostgreSQL)
- Algorithme considère les **100 derniers** pour optimisation requêtes
- Export complet disponible (RGPD)
**Colonne `is_subscribed`** :
- Booléen stockant si l'utilisateur était abonné au créateur **au moment de l'écoute**
- Permet de distinguer les skips d'abonnés (contextuels) des skips de non-abonnés (désintérêt)
- Utilisé pour décisions de reproposition et calculs d'engagement
**Justification** :
- Découverte maximale (pas de redites)
- **Cohérence abonnement** : un skip ponctuel d'un abonné ≠ rejet du créateur (peut être contextuel : "pas maintenant", "pas ce sujet", "mauvais timing")
- Respect erreurs de clic (contenu partiel = 2nde chance)
@@ -331,23 +362,27 @@ GROUP BY content_id;
| `seuil_min_ecoutes_engagement` | 10 - 200 | 50 | nb |
**Application changements** :
- Immédiat : nouveaux calculs utilisent nouvelle config
- Aucun recalcul batch (coût CPU)
- Version config trackée (git-like)
- Rollback 1 clic
**A/B Testing** :
- Création variantes (Config A vs Config B)
- Split utilisateurs 50/50 aléatoire
- Métriques comparatives : taux complétion, engagement, session duration
- Dashboard graphique temps réel
**Audit engagement** :
- Métriques clés : moyenne/médiane temps d'écoute par session
- Graphiques : évolution engagement selon config
- Export CSV pour analyse externe
**Justification** :
- Optimisation continue sans redéploiement
- Data-driven decisions (métriques objectives)
- Coût : dashboard admin à développer (one-time)
@@ -361,26 +396,31 @@ GROUP BY content_id;
**Niveaux de personnalisation** :
**Curseurs disponibles** :
- 📍 **Géolocalisation** : Local ← slider → National (découverte = national)
- 🎲 **Découverte** : 0% ← slider → 50% (part aléatoire)
- ⚖️ **Politique** : Masquer / Équilibré / Mes préférences
**Profils sauvegardables** :
- 🚗 Trajet quotidien (boulot) : géo local, découverte 5%, politique masqué
- 🛣️ Road trip : géo régional, découverte 30%, politique équilibré
- 👶 Enfants : Mode Kids activé
**Synchronisation** :
- ✅ Sync profils entre devices (cloud PostgreSQL)
- ❌ Pas de partage profils entre utilisateurs (famille)
- Auto-switch selon context (détection trajet récurrent via GPS)
**Sécurité conduite** :
- ⚠️ **Blocage modification si vitesse GPS >10 km/h**
- Warning au lancement app : "Configurez avant de prendre la route"
- Modifications uniquement app arrêtée/passager
**Justification** :
- Utilisateur maître de son expérience
- Contextes d'usage différents (quotidien vs voyage)
- Sécurité routière (pas de distraction)
@@ -392,25 +432,30 @@ GROUP BY content_id;
**Décision** : Ouverture aux médias établis
**Médias autorisés** :
- Presse nationale : Le Monde, Le Parisien, Libération, Le Figaro, etc.
- Radios : France Inter, RTL, Europe 1, etc.
- Médias régionaux : Ouest-France, Sud-Ouest, etc.
**Format contenus** :
- Flashs info géolocalisés (actualité régionale)
- Chroniques thématiques (culture, économie, sport)
- Éditos et débats (classification politique appliquée)
**Validation** :
- Compte média vérifié (badge ✓)
- Pas de validation 3 premiers contenus (confiance établie)
- Modération a posteriori uniquement
**Monétisation** :
- Partage revenus pub standard (même conditions créateurs)
- Possibilité sponsoring direct (pas via plateforme)
**Justification** :
- Crédibilité plateforme (contenus professionnels)
- Diversité éditoriale
- Attractivité grand public (noms reconnus)

View File

@@ -17,6 +17,7 @@
**Note importante** : Les pourcentages indiqués sont des **points de pourcentage absolus**, **PAS des pourcentages relatifs**.
**Calcul** :
- Si jauge "Automobile" = 45%
- Like renforcé (+2%) → 45 + 2 = **47%**
- **NOT** 45 × 1.02 = 45.9% ❌
@@ -24,6 +25,7 @@
Cette approche garantit une **progression linéaire** et **équitable** pour tous les utilisateurs, indépendamment de leur niveau actuel dans une jauge.
**Paramètres techniques** :
- Les jauges sont bornées strictement entre **0% et 100%**
- Calcul immédiat à chaque action (pas de batch différé)
- Les tags du contenu sont définis par le créateur à la publication
@@ -61,6 +63,7 @@ Scénario 5 : Skip après 5s (ABONNÉ au créateur)
```
**Justification** :
- **Like automatique** : Reflète l'engagement réel (voir [Règle 05 - Section 5.3](interactions-navigation.md#53-interactions-au-volant--like-automatique-et-engagement))
- **Sécurité routière** : Pas d'action complexe en conduite
- **Prévisibilité** : Règles claires et déterministes
@@ -78,11 +81,13 @@ Scénario 5 : Skip après 5s (ABONNÉ au créateur)
**Décision** : Démarrage neutre à 50%, pas de questionnaire
**À l'inscription** :
- Toutes les jauges d'intérêt sont initialisées à **50%**
- Pas de questionnaire onboarding (friction zéro)
- L'algorithme apprend naturellement via les premières écoutes
**Catégories disponibles** :
- Automobile
- Voyage
- Famille
@@ -104,12 +109,14 @@ Scénario 5 : Skip après 5s (ABONNÉ au créateur)
4. Après 10-15 écoutes, profil commence à se dessiner clairement
**Alternative optionnelle (post-MVP)** :
- Questionnaire **optionnel** proposé après 3 écoutes (in-app)
- Message : "Améliorez vos recommandations en sélectionnant vos centres d'intérêt"
- Si rempli : jauges sélectionnées passent à 70%, non sélectionnées à 30%
- Si skip : conserve 50% partout
**Justification** :
- **Inscription ultra-rapide** : pas de questionnaire = moins de churn
- **Découverte naturelle** : l'algorithme apprend en quelques écoutes
- **Équitable** : pas de biais initial vers certains créateurs
@@ -125,6 +132,7 @@ Scénario 5 : Skip après 5s (ABONNÉ au créateur)
Les jauges **ne diminuent jamais** avec le temps de manière automatique.
**Règle** :
- Une jauge ne change **que par les actions utilisateur** (like, écoute, skip)
- Pas de cron job de dégradation périodique
- Pas de "rafraîchissement" artificiel
@@ -138,16 +146,19 @@ Utilisateur aimait "Économie" (jauge 80%) il y a 1 an
```
**Si utilisateur inactif longtemps** :
- Utilisateur part en vacances 6 mois → jauges conservées
- Au retour : ses jauges reflètent toujours ses goûts d'avant
- Comportement cohérent et prévisible
**Alternative utilisateur (contrôle explicite)** :
- Bouton "Réinitialiser mes centres d'intérêt" dans paramètres
- Action manuelle : remet toutes les jauges à 50%
- Permet nouveau départ si souhaité (changement de vie, etc.)
**Justification** :
- **Principe KISS** (Keep It Simple, Stupid)
- **Coût 0** : pas de batch nocturne, pas de calculs temporels
- **Fiabilité maximale** : pas de bugs de fuseaux horaires, dates, etc.

View File

@@ -5,6 +5,7 @@
**Décision** : Pré-calcul 5 contenus avec insertion prioritaire pour points géographiques
**File d'attente** :
- **5 contenus pré-calculés** en cache (Redis)
- Recalcul automatique si :
- Déplacement >10km
@@ -14,12 +15,14 @@
**Insertion prioritaire géo-ancrée (mode voiture uniquement)** :
**Détection** :
- Calcul ETA (Estimated Time of Arrival) via API GPS native iOS/Android
- Notification déclenchée **7 secondes avant** d'arriver au point GPS
- Si vitesse < 5 km/h ET distance < 50m → notification immédiate
- ⚠️ **App doit être ouverte** (pas de détection en arrière-plan en mode voiture)
**Notification** :
- **Sonore uniquement** : bip court ou son personnalisé RoadWave
- **Visuelle minimale** : icône selon type de contenu (🏛️ culture, 👨‍👩‍👧 famille, 🎵 musique, etc.)
- **Compteur visible** : 7...6...5...4...3...2...1 (décompte des secondes)
@@ -34,19 +37,23 @@
5. À la fin du décompte → contenu géolocalisé démarre (fade out/in 0.3s)
**Si user n'appuie pas sur "Suivant"** :
- Notification disparaît après 7 secondes
- Contenu géolocalisé est perdu (pas d'insertion dans file)
- Pas de nouveau contenu géolocalisé pendant **10 minutes** (éviter spam)
**Limitation anti-spam** :
- Maximum **6 contenus géolocalisés par heure**
- Timer reset toutes les heures (rolling window)
- Exception : séquences d'un même audio-guide multi-séquences (comptent comme 1)
- Si quota atteint : notifications suivantes ignorées jusqu'à libération du quota
**Invalidation immédiate** :
- Utilisateur change ses préférences (curseurs géo/découverte/politique)
- ⚠️ **Modification bloquée si vitesse GPS >10 km/h** (sécurité routière)
- Live démarre d'un créateur suivi dans la zone
**Implémentation** :
@@ -76,6 +83,7 @@ Cooldown après ignorance (Redis) :
```
**Justification** :
- **Expérience fluide** : pas de latence au clic "Suivant"
- **Réactivité géo** : contenu local inséré immédiatement
- **Coût optimisé** : recalcul uniquement si nécessaire
@@ -88,12 +96,14 @@ Cooldown après ignorance (Redis) :
**Décision** : Notifications push en arrière-plan avec rayon large
**Contexte** :
- Mode piéton détecté automatiquement si vitesse moyenne < 5 km/h
- Cas d'usage : visites à pied, musées, monuments, quartiers historiques
- User n'a pas besoin d'avoir l'app ouverte
- ⚠️ **Fonctionnalité optionnelle** : requiert permission "localisation en arrière-plan" (activée par user)
**Détection** :
- App peut être en arrière-plan (si permission accordée)
- Rayon de détection : **200 mètres** autour du point GPS
- Geofencing iOS/Android pour minimiser consommation batterie
@@ -119,12 +129,14 @@ Musée du Louvre : La Joconde - @paris_museum
⚠️ **Important** : RoadWave utilise une **stratégie de permissions progressive** pour maximiser l'acceptation utilisateur et la validation stores.
**Étape 1 - Permission de base (tous utilisateurs)** :
- iOS : "Allow While Using App" (`locationWhenInUse`)
- Android : `ACCESS_FINE_LOCATION`
- **Demandée** : Au premier lancement (onboarding)
- **Permet** : Mode voiture complet ✅
**Étape 2 - Permission arrière-plan (optionnelle, mode piéton uniquement)** :
- iOS : "Allow Always" (`locationAlways`)
- Android : `ACCESS_BACKGROUND_LOCATION`
- **Demandée** : Uniquement si user active "Notifications audio-guides piéton" dans settings
@@ -132,6 +144,7 @@ Musée du Louvre : La Joconde - @paris_museum
- **Permet** : Mode piéton avec notifications push en arrière-plan ✅
**Si permission arrière-plan refusée** :
- Mode piéton **désactivé** (toggle grisé dans settings)
- Mode voiture reste **pleinement fonctionnel**
- Audio-guides accessibles en mode **manuel** (user ouvre app, lance contenu)
@@ -188,6 +201,7 @@ Android (`AndroidManifest.xml`) :
```
**Si user refuse** :
- Mode piéton désactivé (uniquement mode voiture disponible)
- App fonctionne normalement avec permission "When In Use"
- Audio-guides accessibles en mode manuel (user ouvre app, sélectionne contenu)
@@ -201,6 +215,7 @@ Android (`AndroidManifest.xml`) :
**Basculement automatique voiture ↔ piéton** :
Détection par vitesse GPS moyenne sur 30 secondes :
- Vitesse < 5 km/h (stable 10s) → mode piéton
- Vitesse ≥ 5 km/h (stable 10s) → mode voiture
@@ -212,15 +227,18 @@ Changements de mode :
| Voiture | < 5 km/h | Piéton | Notifications sonores → push arrière-plan |
**Pas de popup confirmation** :
- Basculement transparent et automatique
- User n'a rien à faire
- Hysteresis (10s) pour éviter basculements intempestifs
**Quota anti-spam mode piéton** :
- Même limitation que mode voiture : **6 contenus/heure**
- Cooldown 10 min si notification ignorée (app pas ouverte après tap)
**Justification** :
- ✅ Expérience adaptée aux visites à pied (rayon large, pas de timing précis)
- ✅ Économie batterie (geofencing natif iOS/Android)
- ✅ User peut garder téléphone en poche
@@ -241,6 +259,7 @@ Changements de mode :
| **Premier de session** | N/A | Replay depuis début (rien avant) |
**Historique de navigation** :
- **10 contenus maximum** en mémoire (Redis List)
- Structure : `[{content_id, position_seconds, listened_at}, ...]`
- FIFO : au-delà de 10, suppression du plus ancien
@@ -257,11 +276,13 @@ Utilisateur écoute :
```
**Interface (responsabilité front)** :
- ❌ Pas de message UI
- ✅ Progress bar revient au début ou à position exacte
- ✅ Animation fluide (transition 0.3s)
**Justification** :
- **UX intuitive** : comportement standard Spotify/YouTube
- **Pas de frustration** : si début, vraiment revenir en arrière
- **Simplicité** : règle unique (seuil 10s)
@@ -273,6 +294,7 @@ Utilisateur écoute :
**Décision** : Like automatique basé sur le temps d'écoute
**Problème technique identifié** :
- iOS et Android ne supportent **pas nativement** les appuis longs ou doubles-appuis sur les commandes média
- Les commandes physiques au volant varient selon les véhicules (pas de bouton "Pause" dédié sur beaucoup de modèles)
- Système de double-appui/appui long = **non-intuitif** et **risques sécurité** (regarder écran pour feedback)
@@ -309,12 +331,14 @@ Utilisateur écoute :
**Exemples concrets** :
```
Contenu de 3 minutes (180s) :
- Écoute 2min30 (83%) → Like renforcé (+2 points)
- Écoute 1min15 (42%) → Like standard (+1 point)
- Écoute 30s (17%) puis skip → Pas de like
- Skip après 5s → Signal négatif (-0.5 point)
Contenu de 15 minutes (900s) :
- Écoute 13min (87%) → Like renforcé (+2 points)
- Écoute 6min (40%) → Like standard (+1 point)
```
@@ -334,11 +358,13 @@ Contenu de 15 minutes (900s) :
| **Signalement** | Menu contextuel "⋮" | Ouverture flux modération |
**Feedback visuel** :
- **Like automatique** : Badge discret "♥ Ajouté à vos favoris" (2s, bas de l'écran)
- **Like explicite** : Animation cœur rouge + vibration courte
- **Abonnement** : Animation étoile dorée + badge "Abonné ✓"
**Disponibilité** :
- ✅ Mode piéton (vitesse < 5 km/h) : toutes les actions disponibles
- ❌ Mode voiture (vitesse ≥ 5 km/h) : aucune de ces actions (sauf like automatique)
@@ -347,17 +373,20 @@ Contenu de 15 minutes (900s) :
#### Gestion impacts jauges (algorithme)
**Like automatique** :
- Like renforcé (≥80%) → **+2% jauges** de tous les tags du contenu
- Like standard (30-79%) → **+1% jauges** des tags du contenu
- Signal négatif (skip <10s) → **-0.5% jauges** des tags du contenu
**Actions explicites** :
- Like manuel → **+2% jauges** (cumulable avec like auto)
- Unlike → **-2% jauges**
- Abonnement → **+5% toutes jauges** tags créateur
- Désabonnement → **-5% toutes jauges**
**Persistance** :
- Événements stockés en base (table `listen_events`)
- Mise à jour jauges : **immédiate** (Redis) + **async batch** (PostgreSQL)
@@ -431,6 +460,7 @@ class AudioPlayerManager {
#### Justification
**Avantages** :
-**Sécurité routière maximale** : aucune action complexe au volant
-**UX intuitive** : comportement standard industrie (Spotify, YouTube Music, Deezer)
-**Compatibilité 100%** : fonctionne sur tous véhicules, tous OS
@@ -439,6 +469,7 @@ class AudioPlayerManager {
-**Simplicité développement** : pas de workarounds complexes iOS/Android
**Inconvénients mitigés** :
- ⚠️ Pas de like explicite en conduite → **Mitigation** : like automatique + vocal (CarPlay/Android Auto)
- ⚠️ Pas d'abonnement en conduite → **Mitigation** : liste "Créateurs à découvrir" dans app
- ⚠️ Like automatique peut surprendre → **Mitigation** : onboarding clair + unlike possible
@@ -502,6 +533,7 @@ Utilisez les boutons au volant :
- Persiste : Redis (immédiat) + PostgreSQL (batch async)
**Séparation des responsabilités** :
-**Calculation** : Logique métier pure (réutilisable pour auto-like, skip, actions manuelles)
-**Update** : Persistance et contraintes techniques
@@ -516,6 +548,7 @@ newValue := currentValue * (1 + adjustment/100) // NE PAS FAIRE
```
**Persistance** :
- **Redis** : Mise à jour immédiate (latence <10ms)
- **PostgreSQL** : Batch async toutes les 5 minutes (cohérence finale)
- Raison : Jauges consultées fréquemment (recommandations temps réel)
@@ -541,12 +574,14 @@ newValue := currentValue * (1 + adjustment/100) // NE PAS FAIRE
| **Live** | 0 seconde | Enchaînement immédiat |
**Insertion publicité** :
- Pub s'insère **pendant le délai de 2s** (transition naturelle)
- Fréquence : **paramétrable admin** (défaut : 1 pub / 5 contenus)
- Message : "Publicité (15s)" puis lecture pub
- ⚠️ **Jamais d'interruption** d'un contenu en cours
**Publicité skippable** :
- Durée minimale visionnage : **paramétrable** (défaut : 5 secondes)
- Bouton "Passer" apparaît après délai
- Métriques engagement : taux skip, durée écoute moyenne
@@ -559,11 +594,13 @@ newValue := currentValue * (1 + adjustment/100) // NE PAS FAIRE
4. Sinon → lecture en pause, attente action utilisateur
**Gestion erreurs** :
- Échec chargement contenu suivant → **retry 3× avec backoff exponentiel**
- Si 3 échecs → message "Connexion instable, basculement mode offline"
- Mode offline → lecture contenus téléchargés uniquement
**Justification** :
- **Fluidité** : enchaînement naturel sans action utilisateur
- **Contrôle** : possibilité annuler pendant délai
- **Paramétrabilité pub** : évite frustration excès publicité

View File

@@ -23,6 +23,7 @@
Les présentes Conditions Générales d'Utilisation (CGU) régissent l'utilisation de la plateforme RoadWave, réseau social audio géolocalisé.
RoadWave permet aux utilisateurs :
- **Auditeurs** : écouter du contenu audio contextuel géolocalisé
- **Créateurs** : publier du contenu audio géolocalisé
@@ -39,11 +40,13 @@ L'utilisation de la Plateforme implique l'acceptation pleine et entière des pr
RoadWave se réserve le droit de modifier les CGU à tout moment.
**Notification** :
- Email à tous les utilisateurs **14 jours avant** l'entrée en vigueur
- Notification in-app au lancement suivant la modification
- Version mise à jour disponible sur roadwave.fr/cgu
**Refus des nouvelles CGU** :
- Utilisateur peut supprimer son compte dans les 14 jours
- Utilisation continue = acceptation tacite
@@ -67,6 +70,7 @@ RoadWave se réserve le droit de modifier les CGU à tout moment.
### 4.3 Responsabilité du compte
L'utilisateur est responsable de :
- La confidentialité de ses identifiants
- Toutes actions effectuées depuis son compte
- Signalement immédiat en cas d'accès non autorisé
@@ -74,6 +78,7 @@ L'utilisateur est responsable de :
### 4.4 Un compte par personne
Création de comptes multiples interdite, sauf :
- Compte test (développeurs autorisés)
- Demande explicite auprès de RoadWave
@@ -84,6 +89,7 @@ Création de comptes multiples interdite, sauf :
### 5.1 Licence d'utilisation
RoadWave accorde une licence **non exclusive, révocable, non transférable** pour :
- Accéder à la Plateforme
- Écouter du contenu
- Publier du contenu (créateurs)
@@ -91,6 +97,7 @@ RoadWave accorde une licence **non exclusive, révocable, non transférable** po
### 5.2 Interdictions générales
Il est interdit de :
- Utiliser la Plateforme à des fins illégales
- Tenter de contourner les mesures de sécurité
- Utiliser des bots, scripts ou outils automatisés
@@ -113,6 +120,7 @@ Il est interdit de :
Voir **[Charte Créateur](charte-createur.md)** pour règles détaillées.
**Résumé** :
- Contenus originaux ou droits acquis
- Pas de contenu haineux, violent, illégal
- Pas de musique protégée >30 secondes sans licence
@@ -132,6 +140,7 @@ Voir **[Charte Créateur](charte-createur.md)** pour règles détaillées.
### 6.4 Responsabilité du créateur
Le créateur garantit :
- Détenir tous les droits nécessaires
- Ne pas violer de droits tiers (musique, marques, image)
- Respecter les classifications d'âge
@@ -146,44 +155,52 @@ Le créateur garantit :
Sont strictement interdits :
#### **Haine et violence** (Article 7.1.1)
- Incitation à la haine raciale, ethnique, religieuse
- Discrimination sexiste, homophobe, transphobe
- Apologie de crimes contre l'humanité
- Menaces de violence physique
#### **Contenu sexuel** (Article 7.1.2)
- Pornographie ou contenu sexuellement explicite
- Contenu impliquant des mineurs (strictement interdit)
- Sollicitation sexuelle
#### **Illégalité** (Article 7.1.3)
- Apologie du terrorisme
- Incitation aux actes criminels
- Vente de produits illégaux (drogues, armes)
- Pédopornographie → **ban immédiat + signalement autorités**
#### **Droits d'auteur** (Article 7.1.4)
- Musique protégée en intégrale ou extraits >30 secondes
- Films, séries, livres audio protégés
- Diffusion de concerts, événements sportifs payants (lives)
- **Exception** : extraits ≤30s pour critique/analyse (fair use)
#### **Désinformation dangereuse** (Article 7.1.5)
- Fausses informations sur la santé (COVID, vaccins, traitements)
- Fausses informations sur la sécurité routière
- Manipulation électorale
#### **Harcèlement** (Article 7.1.6)
- Menaces répétées envers une personne
- Doxxing (publication informations privées)
- Intimidation, chantage
#### **Fraude** (Article 7.1.7)
- Arnaques, escroqueries
- Pyramides de Ponzi, MLM illégaux
- Phishing, vol d'identité
#### **Spam** (Article 7.1.8)
- Publicité non autorisée (hors système pub RoadWave)
- Répétition de contenus identiques
- Liens vers sites externes de spam
@@ -191,6 +208,7 @@ Sont strictement interdits :
### 7.2 Modération
**Délais de traitement** :
- CRITIQUE (violence, suicide) : <2h (24/7)
- HAUTE (haine, harcèlement) : <24h
- MOYENNE (spam) : <48h
@@ -212,10 +230,12 @@ Sont strictement interdits :
### 8.2 Exceptions
**Tolérance 1ère fois (droits d'auteur uniquement)** :
- Avertissement sans strike si première violation musique protégée
- Explication pédagogique + lien vers règles
**Violations graves (pas de tolérance)** :
- Haine, violence → Strike 1 immédiat
- Contenu illégal (terrorisme, pédopornographie) → Strike 4 (ban) + signalement autorités
@@ -243,6 +263,7 @@ Créateur a Strike 2
### 8.5 Notification des sanctions
**Multi-canal** (email + push + in-app) :
- Catégorie violée (référence article CGU)
- Raison détaillée (langage clair)
- Extrait audio concerné (timestamp)
@@ -297,6 +318,7 @@ Tout utilisateur sanctionné peut contester la décision.
Voir **[CGV Publicités](cgv-publicites.md)**
**Résumé** :
- Interface self-service
- Budget minimum : 50€
- Validation manuelle obligatoire (24-48h)
@@ -309,6 +331,7 @@ Voir **[CGV Publicités](cgv-publicites.md)**
Voir **[CGV Premium](cgv-premium.md)**
**Résumé** :
- Prix : 4.99€/mois OU 49.99€/an
- Avantages : 0 pub, contenus exclusifs 👑, qualité 64 kbps, offline illimité
- Résiliation : à tout moment (effet fin période en cours)
@@ -328,6 +351,7 @@ Voir **[CGV Premium](cgv-premium.md)**
### 12.2 KYC (Know Your Customer)
Vérification obligatoire via Mangopay :
- SIRET, numéro TVA, RIB professionnel
- Pièce d'identité
- Kbis <3 mois (entreprises)
@@ -335,10 +359,12 @@ Vérification obligatoire via Mangopay :
### 12.3 Revenus
**Publicités** :
- 3€ / 1000 écoutes complètes
- Représente ~6% du CA publicitaire
**Premium** :
- 70% créateur, 30% plateforme
- Proportionnel au temps d'écoute
@@ -381,6 +407,7 @@ Voir **[Politique de confidentialité](politique-confidentialite.md)** pour dét
### 14.1 Propriété de la Plateforme
RoadWave et tous ses éléments (code, design, logo, marque) sont protégés par :
- Droit d'auteur
- Droit des marques
- Droit sui generis des bases de données
@@ -398,12 +425,14 @@ RoadWave et tous ses éléments (code, design, logo, marque) sont protégés par
### 14.3 Utilisation des contenus par RoadWave
RoadWave peut :
- Diffuser les contenus aux auditeurs
- Transcrire automatiquement (modération IA)
- Générer segments HLS (streaming)
- Promouvoir la Plateforme (captures d'écran, extraits marketing)
RoadWave **ne peut pas** :
- Revendre les contenus à des tiers
- Modifier substantiellement les contenus (hors transcoding technique)
@@ -420,6 +449,7 @@ RoadWave **ne peut pas** :
### 15.2 Résiliation par RoadWave
RoadWave peut suspendre ou supprimer un compte en cas de :
- Violation grave des CGU
- Strike 4 (ban définitif)
- Activité frauduleuse
@@ -428,15 +458,18 @@ RoadWave peut suspendre ou supprimer un compte en cas de :
### 15.3 Conséquences de la résiliation
**Contenus créateurs** :
- Dépubliés immédiatement
- Marqués "Utilisateur supprimé" (anonymisation)
- Fichiers audio supprimés sous 48h
**Abonnement Premium** :
- Pas de remboursement au prorata
- Accès jusqu'à fin période payée
**Revenus créateurs** :
- Solde <50€ → perdu
- Solde ≥50€ → virement final sous 30 jours
@@ -447,6 +480,7 @@ RoadWave peut suspendre ou supprimer un compte en cas de :
### 16.1 Disponibilité de la Plateforme
RoadWave s'efforce d'assurer une disponibilité 24/7 mais :
- **Aucune garantie** de disponibilité continue
- Maintenances programmées notifiées 48h avant
- Interruptions d'urgence possibles sans préavis
@@ -456,6 +490,7 @@ RoadWave s'efforce d'assurer une disponibilité 24/7 mais :
RoadWave n'est **pas responsable** des contenus publiés par les créateurs.
**Modération** :
- Validation 3 premiers contenus (nouveaux créateurs)
- Modération a posteriori (créateurs vérifiés)
- Réactivité <24-48h après signalement
@@ -463,11 +498,13 @@ RoadWave n'est **pas responsable** des contenus publiés par les créateurs.
### 16.3 Limitation de dommages
RoadWave ne peut être tenu responsable de :
- Perte de données (sauvegardes régulières recommandées)
- Perte de revenus créateurs (indisponibilité temporaire)
- Dommages indirects ou consécutifs
**Plafond** :
- Responsabilité limitée aux **12 derniers mois d'abonnement Premium** (auditeurs)
- Responsabilité limitée aux **revenus perçus sur 12 derniers mois** (créateurs)
@@ -482,6 +519,7 @@ Les présentes CGU sont régies par le **droit français**.
### 17.2 Médiation
Avant toute action judiciaire, l'utilisateur doit tenter une **médiation** :
- Médiateur de la consommation : [NOM MÉDIATEUR]
- Plateforme européenne ODR : https://ec.europa.eu/consumers/odr
@@ -508,6 +546,7 @@ L'absence d'exercice d'un droit par RoadWave ne constitue pas une renonciation.
---
**Contact** :
- Email : support@roadwave.fr
- Adresse : [ADRESSE SIÈGE SOCIAL]
- SIRET : [SIRET]

View File

@@ -23,6 +23,7 @@ Complète les **[CGU](cgu.md)** (Article 11).
| **Annuel** | 49.99€/an | ~17% (4.16€/mois effectif) |
**Tarif IAP (In-App Purchase iOS/Android)** :
- Mensuel : 5.99€/mois (+20% commission Apple/Google)
- Annuel : 59.99€/an
@@ -50,11 +51,13 @@ Complète les **[CGU](cgu.md)** (Article 11).
### 3.1 Modalités
**Via web (Mangopay)** :
- Carte bancaire (Visa, Mastercard, Amex)
- Prélèvement SEPA (si mensuel)
- Paiement sécurisé 3D Secure
**Via mobile (IAP)** :
- App Store (iOS) : Apple Pay, carte bancaire
- Google Play (Android) : Google Pay, carte bancaire
@@ -64,6 +67,7 @@ Complète les **[CGU](cgu.md)** (Article 11).
- **Annuel** : renouvellement 1 an après souscription
**Notification avant renouvellement** :
- Email **7 jours avant** renouvellement
- Rappel : résiliation possible à tout moment
@@ -88,17 +92,20 @@ Résiliation : 15 janvier
### 4.2 Par RoadWave
RoadWave peut résilier si :
- Échec paiement (3 tentatives)
- Violation grave CGU (Strike 4 = ban)
- Fraude détectée (carte volée, etc.)
**Notification** :
- Email **48h avant** résiliation
- Possibilité mise à jour moyen paiement
### 4.3 Remboursement
**Aucun remboursement** sauf :
- Bug empêchant utilisation service >7 jours consécutifs
- Résiliation par RoadWave (erreur de notre part)
@@ -133,6 +140,7 @@ RoadWave peut résilier si :
- **Droit de résiliation** sans frais pendant ces 30 jours
**Protection abonnés annuels** :
- Tarif gelé jusqu'à fin période annuelle
- Nouveau tarif appliqué au prochain renouvellement annuel
@@ -156,6 +164,7 @@ RoadWave peut résilier si :
5. Si échec final → **suspension Premium**
**Suspension** :
- Accès Premium désactivé
- Passage compte gratuit (avec pubs)
- Réactivation possible sous 30 jours (mise à jour carte)
@@ -165,11 +174,13 @@ RoadWave peut résilier si :
## 8. Rétractation (14 jours)
**Droit de rétractation UE** :
- **14 jours** après souscription
- Demande via : support@roadwave.fr
- Remboursement intégral sous 14 jours
**Exception** :
- Si utilisation service pendant 14 jours = renonciation au droit de rétractation
- Acceptation explicite à la souscription

View File

@@ -51,6 +51,7 @@ Complète les **[CGU](cgu.md)** (Article 10).
- **Critères** : conformité CGU, pas de contenu trompeur, respect ARPP
**Refus si** :
- Contenu trompeur, illégal
- Alcool, tabac (interdits)
- Produits santé non autorisés
@@ -106,6 +107,7 @@ Complète les **[CGU](cgu.md)** (Article 10).
Accessible 24/7 : roadwave.fr/pub/dashboard
**Métriques** :
- Impressions totales (nombre diffusions)
- Taux d'écoute complète (%)
- Taux de skip (%)
@@ -128,6 +130,7 @@ Accessible 24/7 : roadwave.fr/pub/dashboard
### 7.2 Budget non consommé
**Si campagne terminée avec budget restant** :
- <10€ : crédit conservé pour prochaine campagne
- ≥10€ : remboursement automatique sous 14 jours
@@ -154,6 +157,7 @@ Accessible 24/7 : roadwave.fr/pub/dashboard
### 9.1 Contenus prohibés
Strictement interdits :
- Alcool, tabac, cannabis
- Jeux d'argent (casinos, paris sportifs)
- Produits pharmaceutiques sans autorisation
@@ -174,6 +178,7 @@ Strictement interdits :
### 10.1 Annonceur
L'annonceur garantit :
- Détenir droits sur contenu publicitaire (musique, voix, marques)
- Conformité légale (ARPP, DGCCRF)
- Véracité des informations (pas de publicité mensongère)
@@ -181,6 +186,7 @@ L'annonceur garantit :
### 10.2 RoadWave
RoadWave n'est pas responsable de :
- Performance commerciale de la pub (pas de garantie ventes)
- Avis négatifs utilisateurs sur la pub

View File

@@ -25,11 +25,13 @@ Cette Charte complète les **[CGU](cgu.md)** (Articles 6 et 7) et détaille les
### 1.2 Critères de validation
**Accepté si** :
- Qualité audio compréhensible
- Métadonnées cohérentes (zone géo, tags, classification âge)
- Pas de contenu prohibé évident
**Refusé si** :
- Audio incompréhensible (grésillement excessif)
- Musique protégée évidente en intégrale
- Contenu haineux, violent, illégal
@@ -62,16 +64,19 @@ Cette Charte complète les **[CGU](cgu.md)** (Articles 6 et 7) et détaille les
| **Classification âge** | Tout public / 13+ / 16+ / 18+ | Obligatoire |
**Tags disponibles** :
- Automobile, Voyage, Famille, Amour, Musique, Économie, Cryptomonnaie, Politique, Culture générale, Sport, Technologie, Santé
### 2.3 Cohérence métadonnées
**Exemples incohérents** :
- "Histoire Tour Eiffel" en zone "National" (devrait être "Point GPS Paris")
- Podcast enfants 3-6 ans classé "18+" (incohérent)
- Contenu politique non tagué "Politique"
**Exemples cohérents** :
- "Visite château Versailles" → Type Ancré, Point GPS Versailles, Tags Voyage + Culture
- "Podcast auto route A7" → Type Contextuel, Zone Région Auvergne-Rhône-Alpes, Tag Automobile
@@ -82,6 +87,7 @@ Cette Charte complète les **[CGU](cgu.md)** (Articles 6 et 7) et détaille les
### 3.1 Musique autorisée
**Vous pouvez utiliser** :
- Votre propre musique originale (vous êtes compositeur/interprète)
- Musique libre de droits (Epidemic Sound, Artlist, YouTube Audio Library, Creative Commons CC0)
- Musique domaine public (>70 ans après mort auteur, ex: classique pré-1950)
@@ -90,6 +96,7 @@ Cette Charte complète les **[CGU](cgu.md)** (Articles 6 et 7) et détaille les
### 3.2 Musique interdite
**Strictement interdit** :
- Musique protégée en intégrale (titre complet)
- Musique protégée en fond >30 secondes
- Compilation DJ sans droits
@@ -104,16 +111,19 @@ Cette Charte complète les **[CGU](cgu.md)** (Articles 6 et 7) et détaille les
4. Mention titre + artiste recommandée
**Exemples OK** :
- Review album : extrait 20s + commentaire analyse musicale
- Podcast histoire musique : extrait 25s + contexte historique
**Exemples KO** :
- Fond musical hit radio 2 minutes (>30s)
- Extrait 15s sans commentaire (pas d'usage transformatif)
### 3.4 Preuves licence
Si vous utilisez musique payante (Epidemic Sound, Artlist) :
- Conservez factures/contrats
- En cas de signalement, upload preuve via processus d'appel
- Musique sera ajoutée à whitelist interne (évite futures erreurs)
@@ -125,6 +135,7 @@ Si vous utilisez musique payante (Epidemic Sound, Artlist) :
### 4.1 Règles spécifiques
**Interdictions strictes en live** :
- Diffusion concert/spectacle depuis la salle → Strike 2 immédiat (7 jours)
- Événement sportif payant (match, compétition droits TV) → Strike 2 immédiat
- Film, série, musique fond sans droits → Strike 1 (3 jours)
@@ -177,6 +188,7 @@ Si vous utilisez musique payante (Epidemic Sound, Artlist) :
### 6.2 Si besoin de changer audio/zone/classification
**Supprimer contenu + republier**
- Si <3 contenus validés : retourne en file validation
- Si ≥3 contenus validés : publication immédiate
@@ -201,11 +213,13 @@ Si vous utilisez musique payante (Epidemic Sound, Artlist) :
### 7.2 Suspension monétisation
**Suspension immédiate si** :
- Strike 3+ actif
- Inactivité (aucun contenu publié depuis 6 mois)
- Échec virement (RIB invalide, 3 tentatives)
**Réactivation** :
- Après résolution strikes (réhabilitation 6 mois)
- Après mise à jour RIB
- Après publication nouveau contenu
@@ -213,11 +227,13 @@ Si vous utilisez musique payante (Epidemic Sound, Artlist) :
### 7.3 Fermeture compte monétisé
**Solde perdu si** :
- <50€ au moment de la fermeture
- Ban définitif (Strike 4)
- Inactivité 24 mois + solde <50€
**Virement final si** :
- ≥50€ → virement sous 30 jours après fermeture
---
@@ -227,6 +243,7 @@ Si vous utilisez musique payante (Epidemic Sound, Artlist) :
### 8.1 Spam
**Interdit** :
- Publier 10+ contenus identiques/similaires
- Répéter contenu dans zones différentes (ex: même podcast publié 50 fois dans 50 villes)
- Auto-promotion excessive (ex: "Abonnez-vous !" répété 20 fois)
@@ -234,6 +251,7 @@ Si vous utilisez musique payante (Epidemic Sound, Artlist) :
### 8.2 Manipulation
**Interdit** :
- Acheter des abonnés, likes, écoutes
- Utiliser bots pour gonfler métriques
- S'abonner massivement puis se désabonner (follow/unfollow spam)
@@ -241,6 +259,7 @@ Si vous utilisez musique payante (Epidemic Sound, Artlist) :
### 8.3 Harcèlement
**Interdit** :
- Créer contenu ciblant nommément une personne (harcèlement)
- Publier informations privées d'un tiers (doxxing)
- Menaces répétées
@@ -262,12 +281,14 @@ Si vous utilisez musique payante (Epidemic Sound, Artlist) :
### 9.2 Conséquences strike
**Suspension upload** :
- Strike 1 : **3 jours** sans possibilité de publier
- Strike 2 : **7 jours**
- Strike 3 : **30 jours**
- Strike 4 : **Permanent** (ban définitif)
**Pas d'impact sur** :
- Contenus déjà publiés (restent en ligne sauf si violents/illégaux)
- Revenus en cours (virement mensuel maintenu)
- Radio live (suspension upload = suspension live aussi)
@@ -295,5 +316,6 @@ Si vous utilisez musique payante (Epidemic Sound, Artlist) :
---
**Contact** :
- Email créateurs : createurs@roadwave.fr
- Email général : support@roadwave.fr

View File

@@ -40,10 +40,12 @@ Email : dpo@roadwave.fr
| **Geohash 5 (~5km²)** | Auto | Recommandations après 24h | Intérêt légitime |
**Durée conservation GPS précis** :
- Historique personnel : **24h** puis agrégé en geohash 5
- Geohash : **conservé** pour analytics (anonymisé)
**Révocation consentement** :
- Désactivation GPS dans paramètres → effet immédiat
- Mode dégradé : contenus nationaux + neutres uniquement
@@ -57,6 +59,7 @@ Email : dpo@roadwave.fr
| **Logs techniques** (IP, user-agent) | Sécurité, anti-fraude | Intérêt légitime |
**IP anonymisée** :
- Dernier octet masqué (ex: 192.168.1.XXX)
- Conservation : 7 jours (sécurité) puis suppression
@@ -122,6 +125,7 @@ RoadWave **ne vend jamais** vos données à des tiers.
### 4.4 Autorités
Données transmises uniquement si :
- **Obligation légale** (réquisition judiciaire)
- **Signalement contenu illégal** (terrorisme, pédopornographie) → autorités compétentes
@@ -163,6 +167,7 @@ Données transmises uniquement si :
- Après 30 jours : suppression définitive
**Exceptions** (conservation nécessaire) :
- Logs modération : 3 ans (obligation DSA)
- KYC créateurs : 5 ans (obligation fiscale)
- Analytics agrégés (anonymisés)
@@ -174,6 +179,7 @@ Données transmises uniquement si :
- Lien téléchargement expire après **7 jours**
**Contenu export** :
- Profil (pseudo, bio, stats)
- Historique écoute complet
- Centres d'intérêt (jauges)
@@ -194,6 +200,7 @@ Données transmises uniquement si :
### 6.7 Réclamation CNIL
Si désaccord avec RoadWave :
- **CNIL** (Commission Nationale de l'Informatique et des Libertés)
- Site : https://www.cnil.fr/fr/plaintes
- Adresse : 3 Place de Fontenoy, 75007 Paris
@@ -218,6 +225,7 @@ Si désaccord avec RoadWave :
### 7.3 Violation de données
En cas de fuite de données :
- Notification CNIL sous **72h**
- Notification utilisateurs concernés (email) si risque élevé
- Mesures correctives immédiates
@@ -273,6 +281,7 @@ En cas de fuite de données :
### 10.1 Principe
Données hébergées **exclusivement UE** :
- Serveurs : Hetzner (Allemagne) ou OVH (France)
- Storage : OVH Object Storage (France)
- Paiements : Mangopay (Luxembourg)
@@ -280,6 +289,7 @@ Données hébergées **exclusivement UE** :
### 10.2 Exceptions
**API tierces potentielles** (post-MVP) :
- Si transfert hors UE → clauses contractuelles types (CCT)
- Notification utilisateurs avant activation
@@ -296,6 +306,7 @@ Données hébergées **exclusivement UE** :
## 12. Contact DPO
**Délégué à la Protection des Données** :
- Email : dpo@roadwave.fr
- Délai réponse : **1 mois** (RGPD)

View File

@@ -14,18 +14,21 @@ La géolocalisation est **critique** pour RoadWave, mais les permissions arrièr
### Problématiques Identifiées
#### iOS App Store
- **Taux de rejet ~70%** si permission "Always Location" mal justifiée
- Apple exige que l'app soit **pleinement utilisable** sans "Always Location"
- Textes `Info.plist` scrutés manuellement par reviewers humains
- Rejection si suspicion de tracking publicitaire ou vente de données
#### Android Play Store
- Depuis Android 10 : `ACCESS_BACKGROUND_LOCATION` nécessite **déclaration justifiée**
- Vidéo démo **obligatoire** montrant le flow de demande (< 30s)
- Google vérifie que la permission est **réellement optionnelle**
- Foreground service notification **obligatoire** en arrière-plan (Android 12+)
#### RGPD (Règle 02)
- Permissions doivent être **optionnelles**
- Utilisateur doit pouvoir **refuser sans pénalité**
- App doit fonctionner en **mode dégradé acceptable**
@@ -62,6 +65,7 @@ La géolocalisation est **critique** pour RoadWave, mais les permissions arrièr
## Étape 1 : Permission de Base (Onboarding)
### Quand
- **Premier lancement** de l'app
- Avant de pouvoir utiliser les fonctionnalités principales
@@ -109,6 +113,7 @@ La géolocalisation est **critique** pour RoadWave, mais les permissions arrièr
### Si Permission Refusée
**Mode dégradé (IP2Location)** :
- Détection pays/ville via adresse IP (IP2Location Lite, voir [ADR-019](../adr/019-geolocalisation-ip.md))
- Contenus nationaux et régionaux disponibles
- Pas de contenus hyperlocaux (< 10km)
@@ -246,6 +251,7 @@ class LocationOnboardingScreen extends StatelessWidget {
## Étape 2 : Permission Arrière-Plan (Optionnelle)
### Quand
- User **active explicitement** "Notifications audio-guides piéton" dans Settings
- **Jamais au premier lancement**
@@ -547,6 +553,7 @@ class _NotificationsSettingsScreenState extends State<NotificationsSettingsScree
| **Denied** | ⚠️ IP2Location (ville) | ❌ Désactivé | ❌ Aucun | Aucune |
**Garanties** :
- App **utilisable** à tous niveaux de permission ✅
- Pas de fonctionnalité **bloquante** sans permission ✅
- Mode dégradé **acceptable** (contenus régionaux) ✅
@@ -632,6 +639,7 @@ class _NotificationsSettingsScreenState extends State<NotificationsSettingsScree
- [ ] Fonctionnalité précise ("audio-guides piéton")
- [ ] **Optionnalité** ("Cette fonctionnalité est optionnelle")
- [ ] Pas de mention tracking/publicité
- [ ] App fonctionne **complètement** avec permission "When In Use" uniquement
- [ ] App fonctionne en **mode dégradé** sans aucune permission (IP2Location)
- [ ] Screenshots montrant app fonctionnelle sans permission "Always"
@@ -642,11 +650,13 @@ class _NotificationsSettingsScreenState extends State<NotificationsSettingsScree
- [ ] Déclaration `ACCESS_BACKGROUND_LOCATION` avec justification dans Play Console :
- [ ] "Notifications géolocalisées pour audio-guides touristiques en arrière-plan"
- [ ] "Permet aux utilisateurs de recevoir des alertes lorsqu'ils passent près de monuments"
- [ ] **Vidéo démo obligatoire** (< 30s) montrant :
- [ ] Activation toggle "Mode piéton" dans Settings
- [ ] Écran d'éducation pré-permission
- [ ] Demande permission système Android
- [ ] App fonctionnelle si permission refusée
- [ ] Foreground service notification visible en mode piéton (Android 12+)
- [ ] App fonctionne **complètement** avec `ACCESS_FINE_LOCATION` uniquement
- [ ] App fonctionne en **mode dégradé** sans permissions
@@ -729,6 +739,7 @@ void main() {
### Tests Manuels (Devices Réels)
**iOS** :
- [ ] iPhone avec iOS 14, 15, 16, 17, 18
- [ ] Tester flow onboarding permission "When In Use"
- [ ] Tester activation mode piéton avec permission "Always"
@@ -736,6 +747,7 @@ void main() {
- [ ] Tester changement permission dans Settings iOS → app réagit correctement
**Android** :
- [ ] Android 10, 11, 12, 13, 14, 15
- [ ] Tester flow onboarding permission `FINE_LOCATION`
- [ ] Tester activation mode piéton avec `BACKGROUND_LOCATION`
@@ -755,11 +767,13 @@ void main() {
**Durée** : 2 semaines
**Checklist** :
- [ ] Upload build vers TestFlight
- [ ] Compléter questionnaire App Store Connect :
- [ ] "Why does your app use background location?"
→ "To send push notifications when users walk near tourist audio-guides, even when app is closed. This feature is optional and can be disabled in settings."
- [ ] Screenshots montrant app fonctionnelle sans permission "Always"
- [ ] Attendre review Apple (24-48h)
- [ ] Si rejet : analyser feedback, ajuster textes/flow, re-soumettre
- [ ] Si accepté : lancer beta test avec testeurs
@@ -772,6 +786,7 @@ void main() {
5. Désactiver mode piéton → vérifier app toujours fonctionnelle
**Métriques collectées** :
- Taux acceptation permission "When In Use" : cible >85%
- Taux acceptation permission "Always" : cible >40%
- Taux rejet App Review : cible 0%
@@ -785,10 +800,12 @@ void main() {
**Durée** : 1 semaine
**Checklist** :
- [ ] Upload build vers Play Console (Internal Testing)
- [ ] Compléter déclaration permissions :
- [ ] `ACCESS_BACKGROUND_LOCATION` justification
- [ ] Upload vidéo démo (< 30s)
- [ ] Tester sur Android 10, 11, 12, 13, 14, 15
- [ ] Vérifier foreground notification visible (Android 12+)
@@ -800,6 +817,7 @@ void main() {
5. Vérifier notification foreground service visible dans panneau notifications
**Métriques collectées** :
- Consommation batterie mode piéton : cible <5% par heure
- Taux crash background service : cible <0.1%
@@ -843,6 +861,7 @@ void main() {
### Q4 : Combien de temps pour validation TestFlight/Play Store ?
**R** :
- TestFlight : 24-48h (review Apple)
- Play Console Internal Testing : Immédiat (pas de review)
- Play Console Production : 3-7 jours (review Google)

View File

@@ -39,11 +39,13 @@ Semaine 6 : Validation finale + go/no-go production
- [ ] `NSLocationAlwaysAndWhenInUseUsageDescription` ≤ 200 caractères
- [ ] Pas de mention tracking/publicité
- [ ] Mention explicite "optionnel"
- [ ] Vérifier `UIBackgroundModes` contient `location`
- [ ] Build & Archive (Xcode)
- [ ] Version : `1.0.0 (1)` (beta)
- [ ] Bundle ID : `com.roadwave.app`
- [ ] Signing : Distribution certificate
- [ ] Upload vers App Store Connect
- [ ] Attendre processing (15-30 min)
@@ -55,11 +57,13 @@ Semaine 6 : Validation finale + go/no-go production
- [ ] `ACCESS_BACKGROUND_LOCATION`
- [ ] `FOREGROUND_SERVICE`
- [ ] `FOREGROUND_SERVICE_LOCATION`
- [ ] Vérifier foreground service déclaration
- [ ] Build AAB (Android App Bundle)
- [ ] Version : `1.0.0 (1)`
- [ ] Package : `com.roadwave.app`
- [ ] Signing : Release keystore
- [ ] Upload vers Play Console (Internal Testing)
### Documentation App Store Connect
@@ -79,10 +83,12 @@ Users can use RoadWave fully without enabling background location - they
will simply use the "car mode" which only requires location "while using".
Background location is ONLY used for:
- Detecting proximity to audio-guide points of interest (200m radius)
- Sending a single push notification to alert the user
Background location is NEVER used for:
- Advertising or tracking
- Selling data to third parties
- Analytics beyond core functionality
@@ -116,11 +122,13 @@ notifications push géolocalisées aux utilisateurs en mode piéton (touristes
à pied).
Usage précis :
- Geofencing radius 200m autour des points d'intérêt (monuments, musées)
- Notification push unique lorsque l'utilisateur entre dans la zone
- Permet découverte de contenus audio-guides sans ouvrir l'app
Cette fonctionnalité est OPTIONNELLE :
- Demandée uniquement si utilisateur active "Mode piéton" dans Settings
- Écran explicatif affiché AVANT demande permission système
- L'app fonctionne pleinement sans cette permission (mode voiture disponible)
@@ -128,12 +136,14 @@ Cette fonctionnalité est OPTIONNELLE :
Foreground service notification visible (Android 12+) lorsque geofencing actif.
Données de localisation :
- JAMAIS vendues ou partagées avec tiers
- JAMAIS utilisées pour publicité ciblée
- Anonymisées après 24h (conformité RGPD)
```
**Vidéo démo** (requis) :
- [ ] Enregistrer screen recording (25-30s)
- [ ] Montrer activation mode piéton depuis Settings
- [ ] Montrer écran d'éducation
@@ -157,6 +167,7 @@ Données de localisation :
| **External 2** | 20-30 | Grand public varié | Tests UX/acceptation réelle |
**Configuration** :
- [ ] Créer groupe "Internal Testers" (accès immédiat)
- [ ] Créer groupe "External Beta 1" (review Apple requise, 24-48h)
- [ ] Créer groupe "External Beta 2" (après succès Beta 1)
@@ -168,6 +179,7 @@ Données de localisation :
**Durée** : 2-3 jours
**Devices** :
- iPhone 12 (iOS 15)
- iPhone 13 Pro (iOS 16)
- iPhone 14 (iOS 17)
@@ -325,10 +337,13 @@ analytics.logEvent(
- Taux acceptation "When In Use" : `granted / requested`
- Cible : >85%
- Taux activation mode piéton : `toggle_attempted / total_users`
- Cible : >30%
- Taux acceptation "Always" : `always_granted / education_continued`
- Cible : >40%
- Taux abandon education : `education_dismissed / education_shown`
- Cible : <60%
@@ -355,11 +370,13 @@ Si Apple **rejette** External Beta :
### Configuration Play Console Internal Testing
**Testeurs** :
- [ ] Ajouter emails testeurs (max 100 pour Internal Testing)
- [ ] Créer "testers list" dans Play Console
- [ ] Share lien installation (pas de review Google pour Internal)
**Devices** :
- Google Pixel 5 (Android 12)
- Samsung Galaxy S21 (Android 13)
- OnePlus 9 (Android 14)
@@ -415,6 +432,7 @@ Then:
### Vidéo Démo Play Store
**Enregistrement** :
- [ ] Device : Pixel 8 (Android 15, UI stock)
- [ ] Screen recorder : Android natif (Game Toolbar)
- [ ] Durée : 25-30s
@@ -430,6 +448,7 @@ Then:
6. (22-25s) Retour Settings, toggle ON confirmé
**Post-production** :
- [ ] Ajouter text overlays : "Utilisateur active mode piéton", "Écran explicatif affiché", etc.
- [ ] Exporter MP4 < 50MB
- [ ] Upload Play Console > Permissions > Background Location > Video demo
@@ -462,6 +481,7 @@ Then:
### Décision Go/No-Go Production
**Critères GO** (tous doivent être ✅) :
- [ ] Apple a approuvé External Beta TestFlight
- [ ] Taux acceptation permission base iOS ≥ 80%
- [ ] Taux acceptation permission base Android ≥ 80%
@@ -488,6 +508,7 @@ Then:
### iOS App Store
**Checklist soumission** :
- [ ] Build production uploadé (même code que TestFlight validé)
- [ ] Version : `1.0.0 (1)`
- [ ] Screenshots stores (5 minimum, incluant permissions flow)
@@ -500,6 +521,7 @@ Then:
**App Privacy (obligatoire iOS 14+)** :
Location Data Collection :
- [ ] "Precise Location" : Yes
- [ ] Purpose : "App Functionality" + "Product Personalization"
- [ ] Linked to user : Yes
@@ -507,6 +529,7 @@ Location Data Collection :
- [ ] "Coarse Location" : No
**Timing** :
- Review Apple : 24-48h (généralement)
- Si rejet : corrections + re-soumission (24h)
- **Total prévu** : 3-7 jours
@@ -514,6 +537,7 @@ Location Data Collection :
### Android Play Store
**Checklist soumission** :
- [ ] Build production (Release AAB)
- [ ] Version : `1.0.0 (1)`
- [ ] Screenshots (8 minimum)
@@ -527,6 +551,7 @@ Location Data Collection :
**Data Safety Form** :
Location Data :
- [ ] "Approximate location" : No
- [ ] "Precise location" : Yes
- [ ] Purpose : "App functionality" + "Personalization"
@@ -535,6 +560,7 @@ Location Data :
- [ ] User can request deletion : Yes
**Timing** :
- Review Google : 3-7 jours
- Si rejet : corrections + re-soumission (1-2 jours)
- **Total prévu** : 5-10 jours