Files
roadwave/docs/adr/012-frontend-mobile.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

235 lines
10 KiB
Markdown

# ADR-012 : Frontend Mobile
**Statut** : Accepté
**Date** : 2025-01-20
## Contexte
RoadWave nécessite applications iOS et Android avec support CarPlay/Android Auto, lecture audio HLS avancée, géolocalisation temps réel. Le choix du framework impacte vélocité développement et performances.
## Décision
**Flutter** pour iOS et Android avec codebase unique.
## Alternatives considérées
| Framework | Codebase | Performance | Audio/CarPlay | Communauté |
|-----------|----------|-------------|---------------|------------|
| **Flutter** | Unique | Native | Excellente | Large |
| React Native | Unique | Bonne | Modules natifs requis | Très large |
| Native (Swift+Kotlin) | Double | Excellente | Native | Large |
| Ionic/Capacitor | Unique | Moyenne | Limitée | Moyenne |
## Justification
- **Codebase unique** : iOS + Android maintenus ensemble, vélocité développement x2
- **Performance** : Dart compilé en code natif (pas de bridge JS)
- **Audio HLS** : Package `just_audio` mature avec support HLS, buffering adaptatif
- **CarPlay/Android Auto** : Support via packages communautaires (`flutter_carplay`, `android_auto_flutter`)
- **Géolocalisation** : `geolocator` robuste avec gestion permissions
- **Écosystème** : Widgets riches (Material/Cupertino), state management mature (Bloc, Riverpod)
## Packages Flutter
> **Voir [ADR-020 - Librairies Flutter](020-librairies-flutter.md)** pour la liste complète des packages, licences, alternatives considérées et justifications détaillées.
**Packages clés pour RoadWave** :
- **State management** : `flutter_bloc` (pattern BLoC, testable, reactive)
- **Audio HLS** : `just_audio` (HLS natif, buffering adaptatif, background playback)
- **GPS temps réel** : `geolocator` (mode voiture haute précision)
- **Geofencing** : `geofence_service` (mode piéton, détection rayon 200m, économie batterie)
- **Notifications** : `flutter_local_notifications` (compteur dynamique, conformité CarPlay/Android Auto)
- **HTTP** : `dio` (client HTTP avec retry logic)
- **Stockage sécurisé** : `flutter_secure_storage` (JWT tokens, Keychain iOS, KeyStore Android)
- **Cache images** : `cached_network_image` (LRU cache)
**Points d'attention** :
- ⚠️ **Permissions progressives requises** pour `geofence_service` et `geolocator` (voir section "Stratégie de Permissions")
- ⚠️ **Licences** : 100% permissives (MIT, BSD-3) - voir ADR-020
## Stratégie de Permissions (iOS/Android)
### Contexte et Enjeux
**Problème** : La géolocalisation en arrière-plan (requise pour le mode piéton) est **très scrutée** par Apple et Google :
- **iOS App Store** : Taux de rejet ~70% si permission "Always Location" mal justifiée
- **Android Play Store** : `ACCESS_BACKGROUND_LOCATION` nécessite déclaration spéciale depuis Android 10
- **RGPD** : Permissions doivent être **optionnelles** et l'app **utilisable sans**
### Architecture de Permissions Progressive
**Principe** : Demander le **minimum** au départ, puis proposer upgrade **contextuel** uniquement si besoin.
#### Niveaux de Permissions
Trois niveaux de permissions doivent être gérés :
- **Denied** : Aucune permission → app limitée (contenu national)
- **When In Use** : "Quand l'app est ouverte" → mode voiture complet ✅
- **Always** : "Toujours" / Background → mode piéton ✅
#### Étape 1 : Permission de Base (Onboarding)
**Quand** : Premier lancement de l'app
**Demande** : `locationWhenInUse` uniquement
- iOS : "Allow While Using App"
- Android : `ACCESS_FINE_LOCATION`
**Justification affichée** :
```
📍 RoadWave a besoin de votre position
Pour vous proposer du contenu audio adapté
à votre localisation en temps réel.
[Autoriser] [Non merci]
```
**Si acceptée** : Mode voiture entièrement fonctionnel ✅
**Si refusée** : Mode dégradé (contenus nationaux/régionaux via GeoIP)
#### Étape 2 : Upgrade Optionnel (Contextuel)
**Quand** : Utilisateur **active explicitement** "Notifications audio-guides piéton" dans Settings
**Flow** :
1. **Écran d'éducation** (requis pour validation stores) :
```
┌────────────────────────────────────────┐
│ 📍 Notifications audio-guides piéton │
├────────────────────────────────────────┤
│ Pour vous alerter d'audio-guides à │
│ proximité même quand vous marchez avec │
│ l'app fermée, RoadWave a besoin de │
│ votre position en arrière-plan. │
│ │
│ Votre position sera utilisée pour : │
│ ✅ Détecter monuments à 200m │
│ ✅ Vous envoyer une notification │
│ │
│ Votre position ne sera jamais : │
│ ❌ Vendue à des tiers │
│ ❌ Utilisée pour de la publicité │
│ │
│ Cette fonctionnalité est optionnelle. │
│ Vous pouvez utiliser RoadWave sans │
│ cette permission. │
│ │
│ [Continuer] [Non merci] │
│ │
│ Plus d'infos : Politique confidentialité│
└────────────────────────────────────────┘
```
2. **Demande permission OS** : `locationAlways` / `ACCESS_BACKGROUND_LOCATION`
3. **Si refusée** :
- Toggle "Mode piéton" reste désactivé
- Message : "Mode piéton non disponible sans permission arrière-plan"
- **App reste pleinement fonctionnelle en mode voiture**
### Implémentation
Le service de gestion des permissions (`lib/core/services/location_permission_service.dart`) doit implémenter :
**Détection du niveau actuel** :
- Vérifier le statut de la permission `location` (when in use)
- Vérifier le statut de la permission `locationAlways` (background)
- Retourner le niveau le plus élevé accordé
**Demande de permission de base** (Étape 1) :
- Demander uniquement la permission `location` (when in use)
- Utilisée lors de l'onboarding
- Aucun écran d'éducation requis
**Demande de permission arrière-plan** (Étape 2) :
- **Toujours** afficher un écran d'éducation AVANT la demande OS
- Demander la permission `locationAlways` (iOS) ou `ACCESS_BACKGROUND_LOCATION` (Android)
- Si refusée de manière permanente, proposer l'ouverture des réglages système
**Gestion des refus** :
- Détecter si la permission est refusée de manière permanente
- Proposer l'ouverture des réglages de l'appareil avec un message clair
- Permettre à l'utilisateur d'annuler
### Configuration Platform-Specific
#### iOS (`ios/Runner/Info.plist`)
**Clés requises** :
- `NSLocationWhenInUseUsageDescription` : Décrire l'usage pour le mode voiture (contenu géolocalisé en temps réel)
- `NSLocationAlwaysAndWhenInUseUsageDescription` : Décrire l'usage optionnel pour le mode piéton (notifications audio-guides en arrière-plan), mentionner explicitement que c'est optionnel et désactivable
- `UIBackgroundModes` : Activer les modes `location` et `remote-notification`
**Exemple de texte pour `NSLocationAlwaysAndWhenInUseUsageDescription`** :
> "Si vous activez les notifications audio-guides piéton, RoadWave peut vous alerter lorsque vous passez près d'un monument ou musée, même quand l'app est en arrière-plan. Cette fonctionnalité est optionnelle et peut être désactivée à tout moment dans les réglages."
#### Android (`android/app/src/main/AndroidManifest.xml`)
**Permissions requises** :
- `ACCESS_FINE_LOCATION` et `ACCESS_COARSE_LOCATION` : Permission de base (when in use)
- `ACCESS_BACKGROUND_LOCATION` : Permission arrière-plan (Android 10+), nécessite justification Play Store
- `FOREGROUND_SERVICE` et `FOREGROUND_SERVICE_LOCATION` : Service persistant pour mode piéton (Android 12+)
**Android Play Store** : Déclaration requise dans Play Console lors de la soumission :
- Justification : "Notifications géolocalisées pour audio-guides touristiques en arrière-plan"
- Vidéo démo obligatoire montrant le flow de demande de permission
### Fallbacks et Dégradations Gracieuses
| Niveau Permission | Mode Voiture | Mode Piéton | Contenus Accessibles |
|-------------------|--------------|-------------|---------------------|
| **Always** | ✅ Complet | ✅ Complet | Tous (national + hyperlocal) |
| **When In Use** | ✅ Complet | ❌ Désactivé | Tous (si app ouverte) |
| **Denied** | ⚠️ Limité | ❌ Désactivé | Nationaux/régionaux (GeoIP) |
**Garantie RGPD** : App est **pleinement utilisable** même avec permission refusée (mode dégradé acceptable).
### Tests de Validation Stores
**Checklist App Store (iOS)** :
- [ ] Permission "Always" demandée **uniquement** si user active mode piéton
- [ ] Écran d'éducation **avant** demande OS (requis iOS 13+)
- [ ] App fonctionne sans permission "Always" (validation critique)
- [ ] Texte `Info.plist` clair et honnête (pas de tracking publicitaire)
**Checklist Play Store (Android)** :
- [ ] Déclaration `ACCESS_BACKGROUND_LOCATION` avec justification détaillée
- [ ] Vidéo démo flow de permissions (< 30s, requis Play Console)
- [ ] App fonctionne sans permission background (validation critique)
- [ ] Foreground service notification visible en mode piéton (requis Android 12+)
### Documentation Associée
- **Guide détaillé** : [/docs/mobile/permissions-strategy.md](../mobile/permissions-strategy.md)
- **Règles métier** : [Règle 05 - Mode Piéton](../domains/recommendation/rules/interactions-navigation.md#512-mode-piéton-audio-guides)
- **RGPD** : [Règle 02 - Conformité RGPD](../domains/_shared/rules/rgpd.md)
---
## Structure application
```
lib/
├── core/ # Config, DI, routes
│ └── services/ # LocationPermissionService, GeofencingService
├── data/ # Repositories, API clients
├── domain/ # Models, business logic
├── presentation/ # UI (screens, widgets, blocs)
│ └── dialogs/ # PedestrianModeEducationDialog
└── main.dart
```
## Conséquences
- Équipe doit apprendre Dart (syntaxe proche Java/TypeScript)
- Taille binaire : 8-15 MB (acceptable)
- Tests : `flutter_test` pour widgets, `integration_test` pour E2E
- CI/CD : Fastlane pour déploiement stores
- **Permissions** : Stratégie progressive critique pour validation stores (iOS/Android)
- **Validation stores** : Tests requis avec TestFlight beta (iOS) et Internal Testing (Android)
- **Documentation** : Justifications permissions détaillées requises pour soumission stores