0.3.5-alpha.1
This commit is contained in:
300
docs/studies/026-V0_3_5_WEBTRANSPORT_QUIC_STACK_AUDIT.md
Normal file
300
docs/studies/026-V0_3_5_WEBTRANSPORT_QUIC_STACK_AUDIT.md
Normal file
@@ -0,0 +1,300 @@
|
||||
<!-- file: docs/studies/026-V0_3_5_WEBTRANSPORT_QUIC_STACK_AUDIT.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Audit WebTransport/QUIC pour 0.3.5
|
||||
|
||||
## Statut et objet
|
||||
|
||||
Cette étude cadre `0.3.5-alpha.1` à partir de l'archive taggée `v0.3.4`. Elle reste non normative : les décisions opérationnelles retenues pour la version sont portées par `docs/plans/005-V0_3_5_WEBTRANSPORT_QUIC_POC_PLAN.md`.
|
||||
|
||||
L'objectif est de déterminer, sur l'état réel de l'écosystème au 2026-09-21, quelle pile WebTransport/QUIC mérite un POC, comment elle se confronte au contrat `game-realtime-transport-lib` livré en `0.3.4`, quelles preuves navigateur/TLS sont réalistes et où doit vivre le fallback WebSocket.
|
||||
|
||||
## Base auditée
|
||||
|
||||
L'archive fournie est annoncée comme le téléchargement ZIP du tag Gitea `v0.3.4` et déclare :
|
||||
|
||||
```text
|
||||
workspace.package.version = 0.3.4
|
||||
17 membres workspace
|
||||
```
|
||||
|
||||
Avant modification, les contrôles statiques exécutables dans l'environnement de génération donnent :
|
||||
|
||||
```text
|
||||
unzip -t : no errors
|
||||
General Rust rule audit: clean
|
||||
Rust export completeness audit: 0 candidate(s)
|
||||
games.sasedev workspace audit: clean
|
||||
Markdown table audit: clean (5 table(s), 263 file(s))
|
||||
Distribution layout audit: clean (50 required path(s), 8 forbidden path(s) absent)
|
||||
```
|
||||
|
||||
L'inventaire indépendant confirme :
|
||||
|
||||
```text
|
||||
437 fichiers dans le ZIP
|
||||
267 fichiers Markdown extraits
|
||||
68 fichiers Rust
|
||||
18 Cargo.toml, dont le manifest racine
|
||||
17 membres workspace
|
||||
0 symlink
|
||||
0 chemin absolu ou traversal détecté
|
||||
0 target/, node_modules/, build/ ou gen/android/ généré
|
||||
```
|
||||
|
||||
La sortie utilisateur fournie à l'ouverture de session confirme également `cargo fmt --all -- --check`, les trois audits et `cargo check --workspace` propres sur son checkout `0.3.4`. Son audit Markdown annonce `279` fichiers contre `263` dans le périmètre scanné du ZIP fourni. La baseline taggée reçue reste l'autorité de génération conformément à `CMD-GIT-003` et `CMD-GIT-004`; l'écart est enregistré sans inventer les fichiers locaux absents de l'archive.
|
||||
|
||||
## État hérité de 0.3.4
|
||||
|
||||
Les preuves de `history/0.3.4/` et `deltas/0.3.4/rel.001.md` confirment :
|
||||
|
||||
- `game-realtime-transport-lib` sans Tokio, WebSocket, QUIC, HTTP ni TLS ;
|
||||
- `TransportMessage` binaire opaque et contrat message-oriented ;
|
||||
- split `RealtimeConnection -> Sender + Receiver` ;
|
||||
- fermeture distante propre distincte d'une erreur ;
|
||||
- erreurs transport-neutral ;
|
||||
- backend `game-realtime-websocket-lib` Tokio/tokio-tungstenite ;
|
||||
- tests loopback et robustesse ;
|
||||
- smoke runtime `game-realtime-websocket-smoke` hors harness `#[test]` ;
|
||||
- `beta.1` validée avec 53 tests workspace ;
|
||||
- `rc.1` validée avec 18 tests realtime ciblés, smoke `PASS` et arbre inverse où seul le launcher de smoke consomme le backend WebSocket.
|
||||
|
||||
Cette frontière constitue la baseline de comparaison. `0.3.5` n'a pas besoin de la redessiner avant d'avoir une preuve WebTransport concrète.
|
||||
|
||||
## État du protocole au 2026-09-21
|
||||
|
||||
WebTransport côté navigateur est désormais classé « Baseline 2026 » par MDN : l'API fonctionne sur les versions récentes des principaux navigateurs depuis mars 2026, avec la réserve habituelle sur les versions anciennes et certaines sous-capacités. L'API exige un contexte sécurisé et expose streams bidirectionnels/unidirectionnels fiables ainsi que datagrams non fiables.
|
||||
|
||||
Sources :
|
||||
|
||||
- <https://developer.mozilla.org/en-US/docs/Web/API/WebTransport_API>
|
||||
- <https://developer.mozilla.org/en-US/docs/Web/API/WebTransport>
|
||||
|
||||
Le binding WebTransport over HTTP/3 n'est cependant pas encore un RFC final. `draft-ietf-webtrans-http3-16`, daté du 2026-07-06, est toujours un Internet-Draft en WG Last Call avec statut visé Proposed Standard.
|
||||
|
||||
Source : <https://datatracker.ietf.org/doc/draft-ietf-webtrans-http3/>
|
||||
|
||||
Conséquence pour le POC : l'interopérabilité navigateur est suffisamment réelle pour être testée, mais la version ne doit pas présenter le protocole ni une crate comme une dépendance produit définitivement stabilisée.
|
||||
|
||||
## Candidats Rust actuels
|
||||
|
||||
### Famille `web-transport`
|
||||
|
||||
État observé :
|
||||
|
||||
```text
|
||||
web-transport 0.12.0 (2026-08-20)
|
||||
web-transport-quinn 0.12.1 (2026-08-20)
|
||||
web-transport-wasm 0.6.0 (2026-08)
|
||||
```
|
||||
|
||||
`web-transport` fournit une API générique qui sélectionne :
|
||||
|
||||
```text
|
||||
native -> web-transport-quinn
|
||||
wasm32 -> web-transport-wasm
|
||||
```
|
||||
|
||||
La crate native s'appuie sur Quinn, Rustls, Tokio et expose streams + datagrams. La crate WASM enveloppe l'API WebTransport du navigateur. Le projet amont est sous licence `MIT OR Apache-2.0`.
|
||||
|
||||
Sources :
|
||||
|
||||
- <https://docs.rs/crate/web-transport/latest>
|
||||
- <https://docs.rs/crate/web-transport-quinn/latest>
|
||||
- <https://docs.rs/crate/web-transport-wasm/latest>
|
||||
- <https://github.com/moq-dev/web-transport>
|
||||
|
||||
Point particulièrement pertinent pour `games.sasedev` : la documentation `web-transport` explique explicitement le problème `Send` entre natif et WASM et contourne ce problème par sélection de l'implémentation selon la cible. Cela rejoint la décision prise en `0.3.4` de ne pas imposer `Send` aux futures du contrat transport-neutral.
|
||||
|
||||
La voie WASM impose actuellement :
|
||||
|
||||
```text
|
||||
--cfg=web_sys_unstable_apis
|
||||
```
|
||||
|
||||
car les bindings WebTransport de `web-sys` restent derrière ce cfg. Ce flag doit être fourni par le build final et ne peut pas être activé par une dépendance. Une éventuelle modification `.cargo/config.toml` devra donc être ciblée sur `wasm32-unknown-unknown`, pas appliquée globalement au workspace.
|
||||
|
||||
### `wtransport`
|
||||
|
||||
État observé :
|
||||
|
||||
```text
|
||||
wtransport 0.7.2 (2026-08-11)
|
||||
```
|
||||
|
||||
La crate fournit une implémentation WebTransport/HTTP3 pure Rust, client et serveur natifs, fondée notamment sur Quinn, Rustls et Tokio. Sa documentation est plus riche et elle fournit des helpers explicites pour certificat self-signed, hash SHA-256 et contraintes W3C. La branche `0.7.x` annonce un MSRV au moins Rust 1.88 dans la metadata consultée de `0.7.1`; la compilation exacte de `0.7.2` reste à prouver sur le toolchain du projet.
|
||||
|
||||
Sources :
|
||||
|
||||
- <https://docs.rs/crate/wtransport/latest>
|
||||
- <https://docs.rs/wtransport/latest/wtransport/>
|
||||
|
||||
Sa limite pour ce projet est l'absence d'une façade Rust WASM équivalente : l'intégration navigateur documentée utilise directement l'API JavaScript `WebTransport`. Cela reste viable pour un serveur Rust, mais apporte moins de valeur au POC si l'objectif est aussi de challenger le contrat Rust commun sur `wasm32`.
|
||||
|
||||
### Quinn / H3 de plus bas niveau
|
||||
|
||||
Quinn est la base QUIC commune à plusieurs stacks, mais l'utiliser directement imposerait de réimplémenter le binding WebTransport/HTTP3, la négociation et les détails de session déjà possédés par les crates spécialisées.
|
||||
|
||||
Cette voie reste un recours si les wrappers retenus bloquent une exigence essentielle ; elle n'est pas retenue comme premier POC, conformément au principe d'éviter une infrastructure disproportionnée.
|
||||
|
||||
## Choix de POC retenu
|
||||
|
||||
La famille `web-transport` est retenue en premier pour `0.3.5`, avec :
|
||||
|
||||
```text
|
||||
game-realtime-webtransport-lib
|
||||
-> web-transport
|
||||
-> native: web-transport-quinn
|
||||
-> wasm32: web-transport-wasm
|
||||
```
|
||||
|
||||
Raisons :
|
||||
|
||||
- façade native + WASM déjà pensée par l'amont ;
|
||||
- alignement direct avec la contrainte `!Send` possible du contrat `0.3.4` ;
|
||||
- serveur natif et client natif/WASM disponibles dans la même famille ;
|
||||
- streams et datagrams disponibles pour le POC ;
|
||||
- Quinn/Rustls/Tokio restent contenus dans le backend concret ;
|
||||
- licence compatible avec le dépôt ;
|
||||
- activité amont récente en août 2026.
|
||||
|
||||
`wtransport` reste le candidat de repli technique prioritaire si `web-transport` échoue sur une exigence concrète de `alpha.2` à `alpha.4`, notamment configuration TLS, lifecycle ou interop navigateur. Un échec d'implémentation ne justifie pas de basculer silencieusement : le plan et le delta doivent enregistrer la raison.
|
||||
|
||||
## Compatibilité avec le contrat 0.3.4
|
||||
|
||||
### Chemin fiable
|
||||
|
||||
Le contrat commun est message-oriented alors qu'un stream QUIC/WebTransport est un flux d'octets fiable, ordonné et flow-controlled. La différence de sémantique est réelle mais ne nécessite pas de modifier `RealtimeConnection`.
|
||||
|
||||
Le POC retiendra un stream bidirectionnel principal par connexion logique :
|
||||
|
||||
```text
|
||||
WebTransport session
|
||||
-> one primary bidirectional reliable stream
|
||||
-> bounded backend framing
|
||||
-> TransportMessage
|
||||
```
|
||||
|
||||
Le framing interne candidat est :
|
||||
|
||||
```text
|
||||
u32 big-endian payload length
|
||||
payload bytes
|
||||
```
|
||||
|
||||
avec une limite produit vérifiée avant allocation/écriture. Ce framing sert uniquement à reconstruire les frontières `TransportMessage` sur un byte stream ; il n'est pas le futur wire codec métier, ne porte aucune version de protocole joueur/room et reste privé au backend.
|
||||
|
||||
Le client ouvre le stream principal ; le serveur l'accepte avant de considérer la `RealtimeConnection` établie. Ce choix conserve l'ordre des messages et permet au split commun de mapper naturellement le côté write/read du même stream.
|
||||
|
||||
### Datagrams
|
||||
|
||||
Les datagrams WebTransport sont non fiables, non ordonnés et non flow-controlled. Ils ne satisfont donc pas le contrat fiable/ordonné livré en `0.3.4`.
|
||||
|
||||
Ils seront exercés séparément dans le POC, sans élargir `RealtimeConnection` et sans créer une capability commune tant qu'un second consommateur réel et un besoin sémantique durable ne sont pas démontrés.
|
||||
|
||||
Une mesure backend-spécifique peut utiliser la session amont directement ou une surface expérimentale locale au launcher de mesure. Elle ne doit pas devenir une API durable uniquement pour permettre le benchmark.
|
||||
|
||||
## TLS et certificats de développement
|
||||
|
||||
Le navigateur impose une URL `https://` vers le serveur WebTransport. L'option `serverCertificateHashes` permet de faire confiance à un certificat connu sans PKI publique lorsque la connexion est dédiée.
|
||||
|
||||
La documentation MDN impose notamment pour ce mode :
|
||||
|
||||
- hash SHA-256 ;
|
||||
- certificat X.509v3 ;
|
||||
- validité totale inférieure à deux semaines ;
|
||||
- date courante dans la période de validité ;
|
||||
- ECDSA P-256 comme choix interopérable minimal.
|
||||
|
||||
Source : <https://developer.mozilla.org/en-US/docs/Web/API/WebTransport/WebTransport>
|
||||
|
||||
`web-transport-quinn` fournit `ClientBuilder::with_server_certificate_hashes`, ce qui permet de reprendre la même stratégie de pinning côté client natif sans désactiver la validation TLS.
|
||||
|
||||
Source : <https://docs.rs/web-transport-quinn/latest/web_transport_quinn/struct.ClientBuilder.html>
|
||||
|
||||
Le POC doit donc privilégier une identité self-signed courte générée pour localhost et un pin de hash explicite. Une API « dangerous/no certificate verification » ne devient pas le chemin normal du smoke.
|
||||
|
||||
Aucun certificat privé, clé privée durable ou secret ne doit être commité.
|
||||
|
||||
## Plateformes
|
||||
|
||||
### Linux natif
|
||||
|
||||
Cible de référence pour :
|
||||
|
||||
- serveur local UDP/QUIC ;
|
||||
- client natif ;
|
||||
- tests loopback déterministes ;
|
||||
- smoke runtime hors harness ;
|
||||
- benchmark local borné.
|
||||
|
||||
### Navigateur / WASM
|
||||
|
||||
Cible obligatoire du POC parce que WebTransport apporte une valeur spécifique au navigateur. Deux preuves distinctes sont nécessaires :
|
||||
|
||||
1. compilation `wasm32-unknown-unknown` du chemin Rust choisi ;
|
||||
2. interop runtime d'un navigateur récent avec le serveur Rust local.
|
||||
|
||||
Le smoke navigateur ne doit pas être confondu avec un simple `cargo check` WASM.
|
||||
|
||||
### Android
|
||||
|
||||
La pile native Quinn/Rustls rend Android plausible, mais `0.3.5-alpha.1` ne le déclare pas validé. Le plan réserve au minimum un contrôle de compilation ciblé si la dépendance choisie ne force pas une réouverture disproportionnée du pipeline Android.
|
||||
|
||||
Aucun changement Java/Gradle/JNI n'est prévu pour le POC ; la matrice quatre ABI `0.3.3` n'est donc pas rejouée par cérémonie.
|
||||
|
||||
### macOS / iOS
|
||||
|
||||
La trajectoire est documentée mais non validée en l'absence d'environnement Apple. Une compatibilité supposée depuis Quinn/Rustls ne doit pas être présentée comme un smoke réel.
|
||||
|
||||
## Fallback WebSocket
|
||||
|
||||
Le fallback est retenu au niveau composition/application du POC, pas dans le gameplay et pas dans `game-realtime-transport-lib`.
|
||||
|
||||
La preuve visée est :
|
||||
|
||||
```text
|
||||
attempt WebTransport
|
||||
success -> use WebTransport path
|
||||
classified establishment failure / unsupported path -> WebSocket baseline
|
||||
```
|
||||
|
||||
Le POC doit également permettre de forcer chaque branche afin de vérifier le fallback de façon déterministe. Il ne doit pas créer de registry dynamique, `TransportManager` générique ni système de plugins.
|
||||
|
||||
Aucune règle n'impose encore que cette logique devienne une crate réutilisable : un launcher technique suffit tant qu'un second consommateur réel ne justifie pas l'extraction.
|
||||
|
||||
## Mesures retenues
|
||||
|
||||
Les mesures minimales sont :
|
||||
|
||||
- temps d'établissement ;
|
||||
- RTT de petits payloads ;
|
||||
- débit sur payloads bornés ;
|
||||
- plusieurs messages en vol ;
|
||||
- comparaison WebSocket vs stream WebTransport fiable ;
|
||||
- comparaison datagram uniquement si la preuve datagram est effectivement réalisée ;
|
||||
- coût opérationnel observé : certificat, UDP, port, debug et build WASM.
|
||||
|
||||
Les résultats loopback sont décrits comme des mesures locales contrôlées. Ils ne seront jamais extrapolés en gains Internet/mobile sans test réseau correspondant.
|
||||
|
||||
CPU/mémoire peuvent être relevés si la méthode est stable, mais ne sont pas une gate de release.
|
||||
|
||||
## Risques principaux
|
||||
|
||||
- protocole HTTP/3 WebTransport encore en Internet-Draft ;
|
||||
- APIs amont actives mais encore susceptibles de casser ;
|
||||
- `web_sys_unstable_apis` imposé au build WASM ;
|
||||
- contraintes de certificats plus lourdes que la baseline `ws://` ;
|
||||
- UDP parfois bloqué par réseau, firewall ou infrastructure ;
|
||||
- browser smoke nécessitant plusieurs processus/outils locaux ;
|
||||
- framing message interne nécessaire sur le stream fiable ;
|
||||
- différences de close/reset entre session WebTransport et stream principal ;
|
||||
- dépendances crypto natives pouvant compliquer certains targets ;
|
||||
- Android plausible mais non prouvé ;
|
||||
- benchmark loopback trop bruité pour porter seul une décision produit.
|
||||
|
||||
## Conclusion de cadrage
|
||||
|
||||
Le POC est viable et justifie `0.3.5`, mais le forecast initial du prompt est trop grossier pour la règle de 15 à 30 minutes par delta. En particulier, backend natif, robustesse, smoke runtime, WASM, interop navigateur/TLS, fallback et mesures ne doivent pas être agrégés en deux grosses alpha.
|
||||
|
||||
Le plan actif découpe ces preuves en tranches verticales indépendantes et ajoute une consolidation explicite avant RC, conformément à `SESSION-009` et `VER-PHASE-010`.
|
||||
Reference in New Issue
Block a user