refactor(docs): réorganiser ADR et règles métier pour clarté
**Changements majeurs** : 1. **Suppression ADR-010 (Commandes volant et likes)** : - Contenu consolidé dans Règle 05 (section 5.3) - Raison : ADR-010 était du métier déguisé en architecture - Section "Implémentation Technique" ajoutée à Règle 05 - Pattern correct (addition) vs incorrect (multiplication) 2. **Déplacement ADR-011 → Compliance** : - `docs/adr/011-conformite-stores.md` → `docs/compliance/stores-submission.md` - Raison : Nature opérationnelle/légale, pas architecture technique - Nouveau dossier `/docs/compliance/` créé 3. **Renumérotation ADR (010-022)** : - Combler les trous de numérotation (010 et 011) - ADR-012→010, ADR-013→011, ..., ADR-024→022 - 22 ADR numérotés en continu (001-022) - Historique Git préservé (git mv) 4. **Mise à jour références** : - Règle 03 : ADR-010 → Règle 05 (section 5.3) - Règle 09 : ADR-010 → Règle 05 (section 5.3) - INCONSISTENCIES-ANALYSIS.md : toutes références mises à jour - Incohérence #15 annulée (faux problème : modes séparés) **Résultat** : - ✅ Séparation claire ADR (technique) vs Règles métier (fonctionnel) - ✅ Documentation compliance séparée - ✅ Numérotation ADR continue sans trous - ✅ Single Source of Truth (pas de redondance) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
234
docs/adr/012-frontend-mobile.md
Normal file
234
docs/adr/012-frontend-mobile.md
Normal file
@@ -0,0 +1,234 @@
|
||||
# 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](../regles-metier/05-interactions-navigation.md#512-mode-piéton-audio-guides)
|
||||
- **RGPD** : [Règle 02 - Conformité RGPD](../regles-metier/02-conformite-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
|
||||
Reference in New Issue
Block a user