Files
roadwave/TECHNICAL.md
2026-01-31 11:45:11 +01:00

8.1 KiB

RoadWave - Architecture Technique

Les décisions techniques sont documentées dans docs/adr/

Stack Technologique

Composant Technologie ADR
Backend Go + Fiber ADR-001
Architecture Backend Monolithe Modulaire ADR-012
Authentification Zitadel (self-hosted OVH) ADR-008
Streaming HLS ADR-002
Codec Opus ADR-003
CDN NGINX Cache (OVH VPS) ADR-004
Storage OVH Object Storage ADR-004
Hébergement MVP OVH VPS Essential ADR-017
Organisation Monorepo ADR-016
Base de données PostgreSQL + PostGIS ADR-005
ORM/Accès données sqlc ADR-013
Cache Redis Cluster ADR-005
Chiffrement TLS 1.3 ADR-006
Live WebRTC ADR-002
Frontend Mobile Flutter ADR-014
Tests Testify + Godog (Gherkin) ADR-015, ADR-007
Paiements Mangopay ADR-009
Emailing Brevo ADR-018
Commandes volant Like automatique ADR-010
Conformité stores CarPlay, Android Auto, App/Play Store ADR-011

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

-- 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

┌─────────────────────────────────────────────┐
│         OVH VPS (Gravelines, France)        │
│                                             │
│  ┌─────────────────┐                       │
│  │  NGINX Cache    │  Cache HLS            │
│  │  + Let's Encrypt│  SSL, rate limiting   │
│  └────────┬────────┘                       │
│           │                                 │
│  ┌────────┴────────┐                       │
│  │   API Gateway   │  Go + Fiber           │
│  └────────┬────────┘                       │
│           │                                 │
│      ┌────┴────┬─────────────┬──────────┐ │
│      │         │             │          │  │
│  ┌───▼───┐ ┌──▼───┐ ┌───────▼────┐ ┌──▼─────┐
│  │ Auth  │ │ User │ │Content/Geo │ │Zitadel │
│  │Service│ │Svc   │ │  Service   │ │  IdP   │
│  └───┬───┘ └──┬───┘ └──────┬─────┘ └───┬────┘
│      │        │            │           │     │
│      └────────┴────────────┴───────────┘     │
│                     │                         │
│         ┌───────────┴──────────┐             │
│         │                      │              │
│    ┌────▼────┐          ┌──────▼──────┐     │
│    │  Redis  │          │ PostgreSQL  │     │
│    │ Cluster │          │  + PostGIS  │     │
│    └─────────┘          │             │     │
│                         │ Schémas:    │     │
│                         │ - roadwave  │     │
│                         │ - zitadel   │     │
│                         └─────────────┘     │
└─────────────────────────────────────────────┘
                    │
         ┌──────────┴──────────┐
         │                     │
┌────────▼────────┐   ┌────────▼────────┐
│ OVH Object      │   │  Mobile Apps    │
│ Storage (S3)    │   │  iOS/Android    │
│ Fichiers audio  │   │                 │
└─────────────────┘   └─────────────────┘

Souveraineté : 100% données en France

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.