refactor(docs): réorganiser structure documentation
- Déplacer TECHNICAL.md vers docs/ pour cohérence - Renommer docs/index.md en docs/README.md (convention GitHub) - Créer docs/adr/README.md comme index des ADR - Supprimer docs/REFACTOR-DDD.md (plan appliqué) - Supprimer docs/technical.md (doublon) - Mettre à jour tous les liens internes - Mettre à jour mkdocs.yml pour nouvelle structure Structure finale : - README.md : vue d'ensemble projet (GitHub) - docs/README.md : page d'accueil documentation (MkDocs) - docs/TECHNICAL.md : architecture technique - docs/adr/README.md : index des 25 ADR
This commit is contained in:
228
docs/TECHNICAL.md
Normal file
228
docs/TECHNICAL.md
Normal file
@@ -0,0 +1,228 @@
|
||||
# RoadWave - Architecture Technique
|
||||
|
||||
> Les décisions techniques sont documentées dans [adr/](adr/)
|
||||
|
||||
## Stack Technologique
|
||||
|
||||
| Composant | Technologie | ADR |
|
||||
|-----------|-------------|-----|
|
||||
| **Backend** | Go + Fiber | [ADR-001](adr/001-langage-backend.md) |
|
||||
| **Architecture Backend** | Monolithe Modulaire | [ADR-010](adr/010-architecture-backend.md) |
|
||||
| **Authentification** | Zitadel (self-hosted OVH) | [ADR-008](adr/008-authentification.md) |
|
||||
| **Streaming** | HLS | [ADR-002](adr/002-protocole-streaming.md) |
|
||||
| **Codec** | Opus | [ADR-003](adr/003-codec-audio.md) |
|
||||
| **CDN** | NGINX Cache (OVH VPS) | [ADR-004](adr/004-cdn.md) |
|
||||
| **Storage** | OVH Object Storage | [ADR-004](adr/004-cdn.md) |
|
||||
| **Hébergement MVP** | OVH VPS Essential | [ADR-015](adr/015-hebergement.md) |
|
||||
| **Organisation** | Monorepo | [ADR-014](adr/014-organisation-monorepo.md) |
|
||||
| **Base de données** | PostgreSQL + PostGIS | [ADR-005](adr/005-base-de-donnees.md) |
|
||||
| **ORM/Accès données** | sqlc | [ADR-011](adr/011-orm-acces-donnees.md) |
|
||||
| **Cache** | Redis Cluster | [ADR-021](adr/021-solution-cache.md) |
|
||||
| **Chiffrement** | TLS 1.3 | [ADR-006](adr/006-chiffrement.md) |
|
||||
| **Live** | WebRTC | [ADR-002](adr/002-protocole-streaming.md) |
|
||||
| **Frontend Mobile** | Flutter | [ADR-012](adr/012-frontend-mobile.md) |
|
||||
| **Tests** | Testify + Godog (Gherkin) | [ADR-013](adr/013-strategie-tests.md), [ADR-007](adr/007-tests-bdd.md) |
|
||||
| **Paiements** | Mangopay | [ADR-009](adr/009-solution-paiement.md) |
|
||||
| **Emailing** | Brevo | [ADR-016](adr/016-service-emailing.md) |
|
||||
| **Géolocalisation IP** | IP2Location (fallback) | [ADR-019](adr/019-geolocalisation-ip.md) |
|
||||
| **Librairies Mobile** | Flutter packages | [ADR-020](adr/020-librairies-flutter.md) |
|
||||
| **CI/CD** | GitHub Actions (monorepo) | [ADR-022](adr/022-strategie-cicd-monorepo.md) |
|
||||
| **Modération** | Architecture modération | [ADR-023](adr/023-architecture-moderation.md) |
|
||||
| **Monitoring** | Prometheus + Grafana | [ADR-024](adr/024-monitoring-observabilite.md) |
|
||||
| **Secrets** | Vault + sealed secrets | [ADR-025](adr/025-securite-secrets.md) |
|
||||
| **Notifications géo** | Push + geofencing | [ADR-017](adr/017-notifications-geolocalisees.md) |
|
||||
| **Notifications push** | FCM + APNS | [ADR-018](adr/018-notifications-push.md) |
|
||||
|
||||
---
|
||||
|
||||
## Streaming Audio
|
||||
|
||||
### Protocole : HLS (HTTP Live Streaming)
|
||||
|
||||
- Fonctionne à travers firewalls et réseaux mobiles instables
|
||||
- Cache CDN natif (réduction des coûts)
|
||||
- Bitrate adaptatif automatique (tunnels, zones rurales)
|
||||
- Support natif iOS/Android
|
||||
|
||||
### Codec : Opus
|
||||
|
||||
Optimisé pour la voix en environnement bruyant (voiture).
|
||||
|
||||
| Qualité | Bitrate | Usage |
|
||||
|---------|---------|-------|
|
||||
| Basse | 24 kbps | 2G/Edge |
|
||||
| Standard | 48 kbps | 3G |
|
||||
| Haute | 64 kbps | 4G/5G |
|
||||
|
||||
Fallback AAC-LC pour appareils legacy.
|
||||
|
||||
### Buffering Adaptatif
|
||||
|
||||
| Réseau | Buffer min | Buffer cible | Buffer max |
|
||||
|--------|------------|--------------|------------|
|
||||
| WiFi | 5s | 30s | 120s |
|
||||
| 4G/5G | 10s | 45s | 120s |
|
||||
| 3G | 30s | 90s | 300s |
|
||||
|
||||
---
|
||||
|
||||
## Sécurité
|
||||
|
||||
### Chiffrement
|
||||
|
||||
- **TLS 1.3** sur tous les endpoints (overhead ~1-2%)
|
||||
- **DTLS-SRTP** pour WebRTC (radio live)
|
||||
- Pas de DRM initialement (ajout si licences l'exigent)
|
||||
|
||||
### Authentification
|
||||
|
||||
- **Zitadel self-hosted sur OVH France** (Gravelines) pour IAM
|
||||
- Souveraineté totale : 100% données en France (cohérent avec ADR-004)
|
||||
- JWT validation locale (zitadel-go SDK)
|
||||
- OAuth2 PKCE pour mobile (iOS/Android)
|
||||
- MFA et passkeys disponibles
|
||||
- Rate limiting par IP et par utilisateur (Nginx + Zitadel)
|
||||
- PostgreSQL schema partagé avec RoadWave (séparation logique)
|
||||
|
||||
---
|
||||
|
||||
## Base de Données
|
||||
|
||||
### PostgreSQL + PostGIS
|
||||
|
||||
```sql
|
||||
-- Requête géolocalisée typique
|
||||
SELECT id, ST_Distance(location::geography, ST_MakePoint($lon, $lat)::geography) as distance
|
||||
FROM contents
|
||||
WHERE ST_DWithin(location::geography, ST_MakePoint($lon, $lat)::geography, 50000)
|
||||
ORDER BY distance
|
||||
LIMIT 20;
|
||||
```
|
||||
|
||||
### Redis Geospatial (Cache)
|
||||
|
||||
```
|
||||
GEOADD contents:geo longitude latitude content_id
|
||||
GEORADIUS contents:geo user_lon user_lat 50 km WITHDIST COUNT 20 ASC
|
||||
```
|
||||
|
||||
TTL cache : 5 minutes (le contenu ne bouge pas).
|
||||
|
||||
---
|
||||
|
||||
## Architecture Services
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph clients["Clients"]
|
||||
mobile["Mobile Apps<br/>iOS/Android<br/>Flutter"]
|
||||
carplay["CarPlay /<br/>Android Auto"]
|
||||
end
|
||||
|
||||
subgraph ovh["OVH VPS Essential (Gravelines, France)"]
|
||||
nginx["NGINX Cache<br/>+ Let's Encrypt<br/>TLS 1.3, Rate Limiting"]
|
||||
api["API Gateway<br/>Go + Fiber :8080"]
|
||||
|
||||
subgraph services["Backend Services (Monolithe Modulaire)"]
|
||||
auth["Auth Service<br/>JWT validation"]
|
||||
user["User Service<br/>Profils, Jauges"]
|
||||
content["Content/Geo Service<br/>Recommandations<br/>PostGIS queries"]
|
||||
streaming["Streaming Service<br/>HLS generation"]
|
||||
payment["Payment Service<br/>Mangopay integration"]
|
||||
notif["Notification Service<br/>FCM/APNS"]
|
||||
end
|
||||
|
||||
zitadel["Zitadel IdP<br/>OAuth2 PKCE<br/>:8081"]
|
||||
ip2loc["IP2Location DB<br/>SQLite ~50MB<br/>Mode dégradé"]
|
||||
|
||||
subgraph data["Données"]
|
||||
pgbouncer["PgBouncer<br/>Connection pooling<br/>:6432"]
|
||||
postgres["PostgreSQL 16<br/>+ PostGIS 3.4<br/>Schémas:<br/>- roadwave<br/>- zitadel"]
|
||||
redis["Redis 7 Cluster<br/>Cache + Geospatial<br/>GEORADIUS"]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph external["Services Externes"]
|
||||
storage["OVH Object Storage<br/>Fichiers audio HLS"]
|
||||
mangopay["Mangopay<br/>Paiements, KYC"]
|
||||
brevo["Brevo<br/>Emails transactionnels"]
|
||||
fcm["FCM / APNS<br/>Push notifications"]
|
||||
end
|
||||
|
||||
mobile --> nginx
|
||||
carplay --> nginx
|
||||
nginx --> api
|
||||
api --> auth
|
||||
api --> user
|
||||
api --> content
|
||||
api --> streaming
|
||||
api --> payment
|
||||
api --> notif
|
||||
api --> ip2loc
|
||||
|
||||
auth --> zitadel
|
||||
user --> pgbouncer
|
||||
user --> redis
|
||||
content --> pgbouncer
|
||||
content --> redis
|
||||
streaming --> storage
|
||||
payment --> mangopay
|
||||
notif --> fcm
|
||||
|
||||
zitadel --> pgbouncer
|
||||
pgbouncer --> postgres
|
||||
|
||||
brevo -.email.-> mobile
|
||||
fcm -.push.-> mobile
|
||||
|
||||
style ovh fill:#e3f2fd
|
||||
style external fill:#fff3e0
|
||||
style clients fill:#f3e5f5
|
||||
style data fill:#e8f5e9
|
||||
```
|
||||
|
||||
**Souveraineté** : 100% données en France (RGPD compliant)
|
||||
|
||||
---
|
||||
|
||||
## Scaling 10M Utilisateurs
|
||||
|
||||
### Stratégie par phase
|
||||
|
||||
| Phase | Utilisateurs | Infra | Coût estimé |
|
||||
|-------|--------------|-------|-------------|
|
||||
| MVP | 0-20K | OVH VPS Essential + PostgreSQL + Zitadel + NGINX Cache | ~14€/mois |
|
||||
| Growth | 20K-500K | Scaleway Instances (multi-replicas), OVH Object Storage | 150-500€/mois |
|
||||
| Scale | 500K+ | Multi-région, Kubernetes managé, NGINX origin shield | 2-10K€/mois |
|
||||
|
||||
### Métriques cibles
|
||||
|
||||
| Métrique | Objectif |
|
||||
|----------|----------|
|
||||
| Latence API p99 | < 100ms |
|
||||
| Temps de démarrage audio | < 3s |
|
||||
| Disponibilité | 99.9% |
|
||||
| Connexions/serveur | 100K+ |
|
||||
|
||||
---
|
||||
|
||||
## Points de vigilance
|
||||
|
||||
1. **Buffering mobile** : Pré-chargement agressif avant tunnels (détection GPS)
|
||||
2. **Handoff réseau** : Buffer suffisant pour survivre aux changements de cellule
|
||||
3. **Mode offline** : Téléchargement complet sur WiFi
|
||||
4. **Bande passante** : 48 kbps Opus = ~20 MB/heure (faible consommation data)
|
||||
|
||||
---
|
||||
|
||||
## Pourquoi pas UDP brut ?
|
||||
|
||||
| UDP | HLS/TCP |
|
||||
|-----|---------|
|
||||
| Latence minimale | Latence acceptable (5-30s) |
|
||||
| Problèmes NAT/firewall | Passe partout |
|
||||
| Perte de paquets = artefacts | Retransmission automatique |
|
||||
| Pas de cache CDN | Cache CDN = économies |
|
||||
| Complexité++ | Standard de l'industrie |
|
||||
|
||||
Pour du contenu non-interactif (podcasts, audio-guides), la latence HLS est acceptable. WebRTC réservé à la radio live uniquement.
|
||||
Reference in New Issue
Block a user