Files
roadwave/docs/domains/premium/rules/mode-offline.md
jpgiannetti 5e5fcf4714 refactor(docs): réorganiser la documentation selon principes DDD
Réorganise la documentation du projet selon les principes du Domain-Driven Design (DDD) pour améliorer la cohésion, la maintenabilité et l'alignement avec l'architecture modulaire du backend.

**Structure cible:**
```
docs/domains/
├── README.md (Context Map)
├── _shared/ (Core Domain)
├── recommendation/ (Supporting Subdomain)
├── content/ (Supporting Subdomain)
├── moderation/ (Supporting Subdomain)
├── advertising/ (Generic Subdomain)
├── premium/ (Generic Subdomain)
└── monetization/ (Generic Subdomain)
```

**Changements effectués:**

Phase 1: Création de l'arborescence des 7 bounded contexts
Phase 2: Déplacement des règles métier (01-19) vers domains/*/rules/
Phase 3: Déplacement des diagrammes d'entités vers domains/*/entities/
Phase 4: Déplacement des diagrammes flux/états/séquences vers domains/*/
Phase 5: Création des README.md pour chaque domaine
Phase 6: Déplacement des features Gherkin vers domains/*/features/
Phase 7: Création du Context Map (domains/README.md)
Phase 8: Mise à jour de mkdocs.yml pour la nouvelle navigation
Phase 9: Correction automatique des liens internes (script fix-markdown-links.sh)
Phase 10: Nettoyage de l'ancienne structure (regles-metier/, diagrammes/, features/)

**Configuration des tests:**
- Makefile: godog run docs/domains/*/features/
- scripts/generate-bdd-docs.py: features_dir → docs/domains

**Avantages:**
 Cohésion forte: toute la doc d'un domaine au même endroit
 Couplage faible: domaines indépendants, dépendances explicites
 Navigabilité améliorée: README par domaine = entrée claire
 Alignement code/docs: miroir de backend/internal/
 Onboarding facilité: exploration domaine par domaine
 Tests BDD intégrés: features au plus près des règles métier

Voir docs/REFACTOR-DDD.md pour le plan complet.
2026-02-07 17:15:02 +01:00

8.2 KiB
Raw Blame History

11. Mode offline

11.1 Téléchargement

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)
  • "Ma région" (sélection liste)
  • Recherche manuelle : "Paris", "Lyon", "Marseille", etc.

Nombre de contenus téléchargeables :

Statut Limite Affichage
Gratuit 50 contenus max "12/50 contenus téléchargés"
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

Connexion WiFi/Mobile :

Par défaut : WiFi uniquement

Sur données mobiles :

  1. User clique "Télécharger"
  2. Détection : pas de WiFi
  3. Popup : "Vous n'êtes pas connecté en WiFi. Télécharger via données mobiles consommera environ X MB. Continuer ?"
  4. Boutons : "Attendre WiFi" / "Continuer"

Calcul estimation :

Nombre contenus × durée moyenne × bitrate qualité
Exemple : 20 contenus × 5 min × 48 kbps = ~72 MB

Qualité audio téléchargement :

Qualité Bitrate Taille Disponibilité
Basse 24 kbps ~10 MB/h Gratuit + Premium
Standard 48 kbps ~20 MB/h Gratuit + Premium (défaut)
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é

11.2 Validité et renouvellement

Durée de validité : 30 jours après téléchargement

Standard industrie :

  • Spotify : 30 jours
  • YouTube Music : 30 jours
  • Deezer : 30 jours

Renouvellement automatique :

App détecte WiFi + contenus >25 jours
→ Requête API : GET /offline/contents/refresh
→ Backend vérifie pour chaque contenu :
    - Abonnement Premium toujours actif ?
    - Contenu pas modéré/supprimé ?
    - Métadonnées à jour ?
→ Renouvelle validité à 30 jours supplémentaires
→ Mise à jour métadonnées (titre, créateur, statut)
→ Pas de re-téléchargement audio (sauf si fichier corrompu)

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

11.3 Synchronisation actions offline

Actions stockées localement (SQLite) :

  • Likes/unlikes
  • Abonnements/désabonnements
  • Signalements
  • Progression audio-guides

Sync automatique à la reconnexion :

1. App détecte reconnexion Internet
2. Récupération queue locale : SELECT * FROM pending_actions ORDER BY created_at
3. Envoi batch API : POST /sync/actions
4. Backend traite chaque action
5. Confirmation réception : DELETE FROM pending_actions WHERE id IN (...)
6. Toast : "3 likes et 1 abonnement synchronisés"

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

11.4 Contenus supprimés pendant offline

Problème : Que se passe-t-il si un utilisateur télécharge des contenus, part offline plusieurs jours, et pendant ce temps certains contenus sont supprimés par les créateurs ou la modération ?

Décision : Suppression immédiate à la reconnexion (Option A - KISS)

Processus de synchronisation

User se reconnecte (WiFi détecté)
↓
1. API sync : GET /offline/validate
   Backend retourne :
   {
     "valid_ids": [id1, id2, id3, ...],
     "deleted_ids": [id10, id12, id15],
     "metadata_updates": [{id: id5, new_title: "..."}]
   }

2. App mobile compare avec contenus locaux :
   - valid_ids : renouvelle validité 30j
   - deleted_ids : suppression immédiate fichiers locaux
   - metadata_updates : mise à jour titre/créateur/tags

3. Notification user :
   Toast : "3 contenus supprimés ont été retirés"

Gestion contenu en cours d'écoute

Si contenu supprimé en cours de lecture :

┌────────────────────────────────────────┐
│ Contenu supprimé                       │
├────────────────────────────────────────┤
│ Ce contenu n'est plus disponible       │
│ et a été retiré par le créateur.       │
│                                        │
│ Passage au contenu suivant...          │
│                                        │
│ [OK]                                   │
└────────────────────────────────────────┘

→ Lecture s'arrête
→ Fichier supprimé localement
→ Passage automatique au contenu suivant (après 2s)

Message récapitulatif

Si plusieurs contenus supprimés :

┌────────────────────────────────────────┐
│ Contenus supprimés                     │
├────────────────────────────────────────┤
│ 3 contenus téléchargés ne sont plus   │
│ disponibles et ont été retirés.        │
│                                        │
│ Les créateurs peuvent supprimer ou    │
│ modifier leurs contenus à tout moment. │
│                                        │
│ [Voir la liste] [OK]                   │
└────────────────────────────────────────┘

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

Mais attendre feedback réel avant d'ajouter cette complexité.


Récapitulatif Section 11

Aspect Décision Valeur
Zone téléchargement Choix Manuel (autour/ville/département/région/recherche)
Limite gratuit Contenus 50 max
Limite Premium Contenus Illimité (espace disque)
Connexion Par défaut WiFi (mobile avec confirmation)
Qualité Standard Bitrate 48 kbps Opus
Qualité Haute Bitrate 64 kbps (Premium uniquement)
Validité Durée 30 jours
Renouvellement Mode Automatique si WiFi
Notification expiration Délai J-3
Sync actions Mode Batch automatique reconnexion
Rétention queue Durée 7 jours max