Remplace la règle complexe de détection multi-devices par une règle simple : le dernier device à démarrer prend toujours la priorité. Clarifications ajoutées : - Comportement online : Device 2 démarre → Device 1 coupé immédiatement - Comportement offline connecté WiFi : même mécanisme (heartbeat envoyé) - Comportement offline mode avion : pas de détection possible (exception technique) - Message coupure explicite avec 2 boutons : "Reprendre ici" / "Sécuriser compte" - Limite offline 30j force reconnexion (cohérence avec mode offline) Détection abus post-MVP : - Monitoring patterns suspects (>10 changements/jour, villes éloignées) - Action manuelle modération (pas automatique pour éviter faux positifs) - Suspension 7j si partage confirmé, ban si récidive Avantages KISS : - Pas de tracking GPS précis ni calcul distances - Pas de faux positifs (TGV légitime) - Assume bonne foi, gestion réactive suffit - Message dissuasif clair Référence: CLARIFICATIONS-REGLES-METIER.md section 5
9.3 KiB
10. Premium
10.1 Offre et tarification
Décision : Deux formules sans essai gratuit
| Formule | Prix | Économie | Prix effectif |
|---|---|---|---|
| Mensuel | 4.99€/mois | - | 4.99€/mois |
| Annuel | 49.99€/an | 2 mois offerts | 4.16€/mois |
❌ 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
- Engagement : utilisateur qui paie dès début = plus engagé
❌ 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
- La plupart des users RoadWave sont individuels (conducteurs)
- 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
10.2 Multi-devices et détection simultanée
Décision : 1 seul stream actif par compte à tout moment - Priorité au dernier device (KISS)
Règle simple : Le dernier device à démarrer prend toujours la priorité, sans exception temporelle ni géolocalisation.
Comportement multi-devices
| Scénario | Device 1 | Device 2 | Résultat | Message Device 1 |
|---|---|---|---|---|
| Transition normale | Écoute online | Démarre 5s après | Device 1 coupé, Device 2 actif | "Lecture interrompue : compte utilisé sur autre appareil" |
| Offline connecté internet | Écoute offline (avec WiFi) | Démarre online | Device 1 coupé, Device 2 actif | Même message |
| Offline déconnecté internet | Écoute offline (mode avion) | Démarre online | Device 1 continue, Device 2 actif | Pas de détection possible (exception technique) |
Implémentation technique détaillée
1. Stream online :
Device 1 écoute online
→ Heartbeat 30s vers serveur
→ Redis : active_streams:{user_id} = {device_id: "iPhone_123", started_at: timestamp}
→ TTL : 5 minutes
Device 2 démarre
→ Détection : active_stream existe
→ Action : Envoi WebSocket close à Device 1
→ Redis : mise à jour active_streams:{user_id} = {device_id: "iPad_456", started_at: timestamp}
→ Device 2 lecture démarre
2. Offline connecté internet :
Device 1 écoute offline MAIS connecté WiFi/4G
→ Heartbeat 30s envoyé quand même
→ Redis : active_streams:{user_id} = {device_id: "iPhone_123", started_at: timestamp, mode: "offline"}
→ Même mécanique que online : Device 2 coupe Device 1
3. Offline déconnecté internet :
Device 1 vraiment offline (mode avion, tunnel)
→ Pas de heartbeat possible
→ Redis : aucune entrée OU expiration TTL après 5 min
→ Device 2 démarre : pas de détection Device 1
→ "Tant pis" (exception technique acceptable)
Message utilisateur (device coupé)
┌────────────────────────────────────────┐
│ ⚠️ Lecture interrompue │
├────────────────────────────────────────┤
│ Votre compte est utilisé sur un │
│ autre appareil. │
│ │
│ Un seul appareil peut écouter à la │
│ fois avec votre compte Premium. │
│ │
│ Le partage de compte viole nos CGU │
│ et peut entraîner une suspension. │
│ │
│ [Reprendre ici] [Sécuriser mon compte] │
└────────────────────────────────────────┘
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
Limite offline 30 jours
Référence : 08-mode-offline.md section 11.2
Contenus téléchargés valides 30 jours
→ Après 30j sans connexion : contenus bloqués
→ Reconnexion WiFi : renouvellement auto si <30j
→ Notification J-3 : "X contenus expirent dans 3 jours"
Cohérence : User offline déconnecté >30j ne peut plus écouter → force reconnexion → détection multi-devices redevient possible.
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"
Action : → Email investigation : "Activité suspecte, sécurisez votre compte" → Si confirmé partage : suspension 7j + warning → Récidive : ban définitif
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
- ✅ Protection revenus créateurs : 1 abonnement = 1 personne = 1 écoute active
- ✅ UX claire : message explicite, user comprend immédiatement
10.3 Contenus exclusifs Premium
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
10.4 Avantages Premium
Inclus dans l'abonnement :
| Avantage | Gratuit | Premium |
|---|---|---|
| Publicités | 1/5 contenus | 0 (aucune) |
| Contenus exclusifs | ❌ Bloqués | ✅ Accès complet |
| Qualité audio | 48 kbps Opus | 64 kbps Opus |
| Mode offline | 50 contenus max | Illimité |
| 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
- Pas d'over-engineering : pas de badges cosmétiques, fonctionnalités sociales, etc. (focus essentiel)
10.5 Gestion abonnement
Souscription :
| Canal | Prestataire | Prix | Commission |
|---|---|---|---|
| Web (desktop/mobile) | Mangopay | 4.99€ | 1.8% + 0.18€ = 0.27€ |
| iOS App | Apple In-App Purchase | 5.99€ | 30% (Apple) |
| 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)
Architecture données :
CREATE TABLE subscriptions (
id UUID PRIMARY KEY,
user_id UUID NOT NULL REFERENCES users(id) UNIQUE,
mangopay_recurring_payin_id VARCHAR(255), -- Null si IAP
mangopay_user_id VARCHAR(255), -- Null si IAP
apple_transaction_id VARCHAR(255), -- Null si Mangopay
google_purchase_token VARCHAR(255), -- Null si Mangopay
status VARCHAR(50) NOT NULL, -- 'active', 'cancelled', 'expired', 'past_due'
plan VARCHAR(50) NOT NULL, -- 'monthly', 'yearly'
current_period_start TIMESTAMP NOT NULL,
current_period_end TIMESTAMP NOT NULL,
cancelled_at TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
Vérification Premium en temps réel :
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