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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) |
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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`)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -103,10 +103,12 @@ Quelles autres options ont été évaluées ?
|
||||
## Conséquences
|
||||
|
||||
### Positives
|
||||
|
||||
- Avantage 1
|
||||
- Avantage 2
|
||||
|
||||
### Négatives
|
||||
|
||||
- Limitation 1
|
||||
- Compromis accepté
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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** :
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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é"`)
|
||||
|
||||
@@ -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"]`
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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€
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]`
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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é)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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é
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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é
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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é
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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é
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -96,7 +96,8 @@ nav:
|
||||
- Domaines DDD:
|
||||
- 'Context Map': domains/README.md
|
||||
- 'Core Domain':
|
||||
- '🔐 Shared': domains/_shared/README.md
|
||||
- '🔐 Shared':
|
||||
- Vue d'ensemble: domains/_shared/README.md
|
||||
- Règles:
|
||||
- Authentification: domains/_shared/rules/authentification.md
|
||||
- RGPD: domains/_shared/rules/rgpd.md
|
||||
|
||||
58
scripts/fix-markdown-lists.sh
Executable file
58
scripts/fix-markdown-lists.sh
Executable file
@@ -0,0 +1,58 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script pour ajouter des lignes vides avant les listes markdown
|
||||
# qui n'en ont pas, pour un rendu correct dans mkdocs
|
||||
|
||||
set -e
|
||||
|
||||
echo "🔍 Recherche des fichiers markdown dans docs/..."
|
||||
|
||||
# Compteur de fichiers modifiés
|
||||
modified=0
|
||||
|
||||
# Trouver tous les fichiers .md dans docs/
|
||||
find docs -name "*.md" -type f | while read -r file; do
|
||||
echo " Traitement de $file..."
|
||||
|
||||
# Utiliser awk pour ajouter une ligne vide avant les listes si nécessaire
|
||||
awk '
|
||||
BEGIN {
|
||||
prev = ""
|
||||
prev_empty = 1
|
||||
}
|
||||
{
|
||||
current = $0
|
||||
# Si la ligne courante commence par "- " et que la ligne précédente n'\''est pas vide
|
||||
# et ne commence pas déjà par "- " (déjà dans une liste)
|
||||
if (current ~ /^- / && prev !~ /^$/ && prev !~ /^- /) {
|
||||
print prev
|
||||
print "" # Ajouter une ligne vide
|
||||
prev = current
|
||||
}
|
||||
# Sinon, imprimer la ligne précédente normalement
|
||||
else if (NR > 1) {
|
||||
print prev
|
||||
prev = current
|
||||
}
|
||||
else {
|
||||
prev = current
|
||||
}
|
||||
}
|
||||
END {
|
||||
# Imprimer la dernière ligne
|
||||
if (prev != "") print prev
|
||||
}
|
||||
' "$file" > "$file.tmp"
|
||||
|
||||
# Vérifier si le fichier a changé
|
||||
if ! cmp -s "$file" "$file.tmp"; then
|
||||
mv "$file.tmp" "$file"
|
||||
echo " ✅ $file modifié"
|
||||
modified=$((modified + 1))
|
||||
else
|
||||
rm "$file.tmp"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "✨ Terminé ! $modified fichier(s) modifié(s)"
|
||||
@@ -195,6 +195,7 @@ def get_keyword_color(keyword: str) -> str:
|
||||
def format_step(step: Step, indent: str = "") -> str:
|
||||
"""Formate une étape Gherkin avec couleur"""
|
||||
color = get_keyword_color(step.keyword)
|
||||
# Ajouter deux espaces à la fin pour forcer un line break en markdown
|
||||
result = f'{indent}<span style="color: {color}">**{step.keyword}**</span> {step.text} '
|
||||
|
||||
if step.table:
|
||||
|
||||
Reference in New Issue
Block a user