# Petite veille tech
## Vision
Application de messagerie et réseau social **absolument décentralisé**. Aucun serveur central, aucun point de contrôle unique. L'application utilise **tous les moyens à sa disposition** pour faire parvenir un message d'un point A à un point B, en privilégiant toujours la méthode la plus efficace disponible à un instant donné.
Le réseau doit pouvoir fonctionner **avec ou sans Internet**. L'application est autosuffisante : elle peut former son propre réseau de proche en proche sans dépendre d'aucune infrastructure extérieure (antennes, routeurs, box).
## Stack technique
| Couche | Technologie | Rôle |
| ------------ | -------------------------------------------- | ----------------------------------------------------- |
| UI / Logique | **Leptos** (Rust → WASM) | Framework frontend, rendu client-side uniquement |
| Concurrency | WebAssembly (SharedArrayBuffer, Web Workers) | Multiprocessing, channels Rust, gestion du protocole |
| Natif | **Tauri Mobile** | Wrapper natif iOS/Android autour de la webview Leptos |
| Build PWA | **Trunk** | Compilation WASM → fichiers statiques |
| Build natif | **Tauri CLI** + Xcode / Android Studio | Plugins natifs Swift (iOS) + Kotlin (Android) |
**Partage de code** : ~98% de la codebase est commune entre la PWA et les versions natives. Les plugins natifs (BLE, MultipeerConnectivity, etc.) sont des **capabilities optionnelles** activées quand disponibles.
## Distribution
L'application se décline en **trois modes de diffusion** pour minimiser la dépendance aux stores et garantir l'accès en toutes circonstances.
```mermaid
graph TD
APP[Application Leptos / WASM]
APP -->|PWA| PWA[URL]
APP -->|Tauri Android| AND[.apk / .aab]
APP -->|Tauri iOS| IOS[.ipa]
AND --> FDROID[F-Droid]
AND --> APK[APK direct]
IOS --> ALTSTORE_PAL[AltStore PAL — UE/Japon/Brésil]
IOS --> ALTSTORE[AltStore — monde entier]
style PWA fill:#4caf50,color:#fff
style FDROID fill:#4caf50,color:#fff
style APK fill:#4caf50,color:#fff
style ALTSTORE fill:#ff9800,color:#fff
style ALTSTORE_PAL fill:#ff9800,color:#fff
```
| Mode | Plateforme | Friction | Résistance à la censure |
| ---------------- | -------------------------- | ---------------------------- | ------------------------------ |
| **PWA** | iOS + Android (navigateur) | Nulle (une URL) | Maximale tant que l'URL existe |
| **F-Droid** | Android | Faible | Maximale aucune review |
| **APK direct** | Android | Faible | Maximale |
| **AltStore PAL** | iOS (UE/Japan/Brésil) | Modérée (notarization Apple) | Apple peut révoquer |
| **Altstore** | iOS (mondial) | Modérée (notarization Apple) | Apple peut révoquer |
**Principe** : la PWA garantit que l'application reste accessible quel que soit le contexte. Les versions natives sur stores alternatifs sont un **bonus** qui débloque des capabilities matérielles supplémentaires.
## Capacités par plateforme
### Stockage
| | PWA | Natif iOS | Natif Android |
| ---------------------- | ----------------------------------------------------- | ---------------------- | ---------------------- |
| **IndexedDB** | Données structurées, messages, queue | ok | ok |
| **OPFS** | Fichiers binaires, médias (accès synchrone en Worker) | ok | ok |
| **Storage persistant** | `navigator.storage.persist()`(pas dispo sur iOS) | File system natif | File system natif |
| **Quota** | iOS ~1 GB (variable) · Chrome 60% disque | Illimité (sandbox app) | Illimité (sandbox app) |
| **Éviction** | iOS : 7 jours sans usage → cache effacé | Pas d'éviction | Pas d'éviction |
### 4.2 Accès matériel et réseau
| Capability | PWA iOS | PWA Android | Natif iOS | Natif Android |
| ------------------------- | ------------------------------ | ------------------------------ | --------------- | ------------- |
| **WebSocket** | foreground | foreground | background | background |
| **WebRTC (LAN)** | après pairing | après pairing | après pairing | après pairing |
| **WebRTC (Internet)** | via STUN | via STUN | via STUN | via STUN |
| **BLE advertise** | x | x | background | background |
| **BLE scan** | x | foreground (scan uniquement) | background | background |
| **MultipeerConnectivity** | x | x | (BLE+WiFi+AWDL) | x |
| **WiFi Direct** | x | x | x | ok |
| **Nearby Connections** | x | x | x | ok (BLE+WiFi) |
| **Ultrasonore** | background (hack MediaSession) | background (hack MediaSession) | background | background |
| **Micro** | foreground | foreground | background | background |
## Modes de communication
Le protocole sélectionne **dynamiquement** le meilleur transport disponible, par ordre de priorité décroissante :
1. Internet (WebSocket / WebRTC via STUN)
2. Réseau local (WebRTC host candidates sur LAN partagé)
3. Ondes radio (BLE, MultipeerConnectivity, WiFi Direct)
4. Ultrasons (fallback universel)
### Internet — WebSocket / WebRTC via STUN
| | Valeur |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| **Portée** | Illimitée (mondiale) |
| **Débit** | WebSocket : illimité · WebRTC Data Channel : illimité |
| **Mode** | Full-duplex |
| **Latence** | ~50-200 ms |
| **Background** | Natif : ok / PWA : nope) |
| **Disponible** | Toutes versions (quand Internet est accessible) |
| **Infrastructure requise** | Serveurs : STUN (lightweight) + éventuellement TURN pour NAT difficiles. Bootstrap server optionnel pour discovery initiale. |
### Réseau local (LAN) — WebRTC host candidates
| | Valeur |
| -------------------------- | --------------------------------------------------------- |
| **Portée** | Portée du WiFi local (~30-50m) |
| **Débit** | Illimité (WiFi) |
| **Mode** | Full-duplex |
| **Latence** | ~1-5 ms |
| **Background** | Natif : ok · PWA : nope |
| **Disponible** | Toutes versions (quand 2+ pairs sur le même WiFi) |
| **Infrastructure requise** | nécessite un WiFi partagé (box, hotspot) |
| **Pairing** | Nécessite signaling initial (QR, ultrasons, ou bootstrap) |
### Ondes radio — BLE (iOS ↔ Android)
| | Valeur |
| -------------------------- | ---------------------------------------------------------------------------------------------- |
| **Portée** | ~10 m |
| **Débit utile** | ~100-500 kbit/s (GATT) · ~1-2 Mbit/s théorique |
| **Mode** | Full-duplex (connexion GATT établie) |
| **Latence** | ~10-50 ms |
| **Background** | Natif iOS (`bluetooth-central` + `bluetooth-peripheral`) · Natif Android (foreground service) |
| **Disponible** | Natif iOS + Natif Android uniquement |
| **Discovery** | Automatique (advertise + scan) — pas de pairing manuel |
| **Infrastructure requise** | Aucune |
### Ondes radio — MultipeerConnectivity (iOS ↔ iOS)
| | Valeur |
| -------------------------- | ------------------------------------- |
| **Portée** | ~10-30 m (BLE + WiFi + AWDL combinés) |
| **Débit** | WiFi : plusieurs Mbit/s |
| **Mode** | Full-duplex |
| **Latence** | ~5-20 ms |
| **Background** | (session persistante) |
| **Disponible** | Natif iOS uniquement |
| **Discovery** | Automatique |
| **Infrastructure requise** | Aucune |
### Ondes radio — WiFi Direct / Nearby Connections (Android ↔ Android)
| | Valeur |
| -------------------------- | --------------------------------------------------- |
| **Portée** | ~50-100 m (WiFi Direct) |
| **Débit** | WiFi : plusieurs Mbit/s |
| **Mode** | Full-duplex |
| **Latence** | ~5-20 ms |
| **Background** | (foreground uniquement) |
| **Disponible** | Natif Android uniquement |
| **Discovery** | Automatique (Nearby Connections combine BLE + WiFi) |
| **Infrastructure requise** | Aucune |
### Ultrasons — fallback universel
| | Valeur |
| -------------------------- | ----------------------------------------------------- |
| **Portée** | ~2 m (volume max, 18-19 kHz) |
| **Débit** | ~300 bits/s (FSK à 19 kHz) |
| **Mode** | **Half-duplex** (mono — voir ci-dessous) |
| **Latence** | ~1-2 s par transmission |
| **Background** | PWA : nope (micro tué) · Natif : ok |
| **Disponible** | Toutes versions (PWA + natif iOS + natif Android) |
| **Discovery** | Broadcast chirp périodique |
| **Infrastructure requise** | Aucune |
| **Discrétion** | Inaudible (18-19 kHz, au-dessus de l'audition adulte) |
### Qui peut parler à qui, et comment
| Source → Destination | Meilleur transport | Fallback |
| ---------------------------------------- | ------------------------ | ------------------------------- |
| PWA → PWA | Ultrasons (seule option) | QR code manuel (et encore mdrr) |
| PWA → Natif iOS | Ultrasons | — |
| PWA → Natif Android | Ultrasons | — |
| Natif iOS → Natif iOS | MultipeerConnectivity | BLE → Ultrasons |
| Natif Android → Natif Android | WiFi Direct / Nearby | BLE → Ultrasons |
| Natif iOS → Natif Android | BLE | Ultrasons |
| N'importe qui → N'importe qui (Internet) | WebSocket / WebRTC | Tout le reste |
| N'importe qui → N'importe qui (LAN) | WebRTC host candidates | BLE → Ultrasons |
## Formation du mesh autonome
### Principe du store-and-forward
Chaque pair stocke les messages en local (IndexedDB / storage natif) et les re-broadcast dès qu'un voisin entre à portée. Les messages voyagent hop par hop, potentiellement avec délai.
```mermaid
sequenceDiagram
participant A as Alice
participant B as Bob
participant C as Charlie
participant D as Dave
A->>A: Écrit message pour Dave<br/>Stocké en IndexedDB
Note over A: Aucun pair à portée<br/>Message en attente
A->>B: Pair entre à portée (BLE ~10m)<br/>Transfert du message
B->>B: Stocke en local
B->>C: Relay vers Charlie (BLE ~10m)
C->>C: Stocke en local
C->>D: Relay vers Dave (BLE ~10m)
D->>D: Message reçu ! ACK généré
D->>C: ACK remonte (BLE)
C->>B: ACK relay
B->>A: ACK relay → message purgé de la queue
```
### Mesh avec transports hétérogènes
Dans la vraie vie, le mesh mêle téléphones PWA et natifs, avec des transports différents à chaque hop.
```mermaid
graph TD
subgraph "5 tel, pas d'Internet"
A["PWA Alice"]
B["Natif iOS Bob"]
C["Natif Android Charlie"]
D["Natif iOS Dave"]
E["PWA Eve"]
A -->|"Ultrasons ~2m ~300b/s"| B
B -->|"BLE ~10m ~500kb/s"| C
C -->|"BLE ~10m ~500kb/s"| D
B -->|"MultipeerConnectivity ~30m Mbit/s"| D
A -->|"Ultrasons ~2m"| E
end
style A fill:#4caf50,color:#fff
style E fill:#4caf50,color:#fff
style B fill:#2196f3,color:#fff
style D fill:#2196f3,color:#fff
style C fill:#ff9800,color:#fff
```
**Exemple de routage** : Alice (PWA) veut envoyer un message à Dave (natif iOS) :
1. Alice émet en ultrasons vers Bob (~2m, half-duplex, ~5s)
2. Bob (natif iOS) relaye à Dave via MultipeerConnectivity (~30m, full-duplex, instantané)
3. Dave accuse réception → ACK remonte par le même chemin
### Mode half-duplex ultrasonore — séquence temporelle
L'ultrasonore étant half-duplex, chaque pair alterne entre émission et écoute selon un cycle :
```mermaid
sequenceDiagram
participant A as Phone A (émetteur)
participant B as Phone B (récepteur)
Note over A,B: Phase 1 — A émet, B écoute
A->>B: Chirp discovery (~0.5s)<br/>"Je suis PeerId X"
B->>B: Décodage + stockage
Note over A,B: Phase 2 — B répond, A écoute
B->>A: Réponse (~2s)<br/>PeerId Y + ICE candidates
A->>A: Décodage + stockage
Note over A,B: Phase 3 — A confirme, B écoute
A->>B: ACK (~0.3s)<br/>Confirmation réception
Note over A,B: Phase 4 — Silencieux, switch transport
Note over A,B: Si BLE/Multipeer disponible → upgrade
Note over A,B: Sinon → continue en ultrasons
```
Récapitulatif des transports
| Transport | Portée | Débit | Mode | Background | iOS | Android | PWA |
| ------------------------- | ------ | -------------- | --------------- | ------------------- | --- | ------- | --- |
| **WebSocket** | ∞ | Illimité | Full-duplex | Natif ok / PWA nope | ok | ok | ok |
| **WebRTC (Internet)** | ∞ | Illimité | Full-duplex | Natif ok/ PWA nope | ok | ok | ok |
| **WebRTC (LAN)** | ~50m | Illimité | Full-duplex | Natif ok / PWA nope | ok | ok | ok |
| **BLE** | ~10m | ~500 kbit/s | Full-duplex | ok natif | ok | ok | x |
| **MultipeerConnectivity** | ~30m | Mbit/s | Full-duplex | ok ios | ok | x | x |
| **WiFi Direct** | ~100m | Mbit/s | Full-duplex | ok android | x | ok | |
| **Ultrasons** | ~2m | ~300 bits/s | **Half-duplex** | Natif ok / PWA nope | ok | ok | x |
| **QR code** | Visuel | ~60 bytes/scan | One-shot | N/A | ok | ok | ok |