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