0.3.5-alpha.1

This commit is contained in:
2026-09-21 21:21:28 +02:00
parent bf9ead329a
commit 3e24b7840c
8 changed files with 1166 additions and 8 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: docs/000-README.md -->
<!-- version: 34 -->
<!-- version: 35 -->
# Documentation games.sasedev
@@ -11,6 +11,7 @@
- [`ideas/000-README.md`](ideas/000-README.md) — rôle des idées non engagées et règles de maturation.
- [`studies/000-README.md`](studies/000-README.md) — rôle des études comparatives non normatives.
- [`studies/026-V0_3_5_WEBTRANSPORT_QUIC_STACK_AUDIT.md`](studies/026-V0_3_5_WEBTRANSPORT_QUIC_STACK_AUDIT.md) — audit `0.3.5` des stacks WebTransport/QUIC, du contrat transport, de TLS et des plateformes.
## Plans
@@ -19,6 +20,7 @@
- [`plans/002-V0_3_1_TAURI_ANDROID_SNAKE_PLAN.md`](plans/002-V0_3_1_TAURI_ANDROID_SNAKE_PLAN.md) — plan clôturé de `0.3.1`, second host Snake Tauri Android.
- [`plans/003-V0_3_3_ANDROID_NATIVE_MULTI_ABI_PLAN.md`](plans/003-V0_3_3_ANDROID_NATIVE_MULTI_ABI_PLAN.md) — plan clôturé de `0.3.3`, pipeline Android SDL3 natif Gradle/Cargo multi-ABI.
- [`plans/004-V0_3_4_REALTIME_TRANSPORT_WEBSOCKET_PLAN.md`](plans/004-V0_3_4_REALTIME_TRANSPORT_WEBSOCKET_PLAN.md) — plan clôturé de `0.3.4`, API de transport realtime et baseline WebSocket Tokio/tokio-tungstenite.
- [`plans/005-V0_3_5_WEBTRANSPORT_QUIC_POC_PLAN.md`](plans/005-V0_3_5_WEBTRANSPORT_QUIC_POC_PLAN.md) — plan actif de `0.3.5`, POC WebTransport/QUIC, navigateur, fallback WebSocket et mesures comparatives.
## Architecture

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/000-README.md -->
<!-- version: 6 -->
<!-- version: 7 -->
# Plans de versions games.sasedev
@@ -15,3 +15,4 @@ Le `ROADMAP.md` reste la trajectoire macroscopique du projet ; les deltas décri
- [`002-V0_3_1_TAURI_ANDROID_SNAKE_PLAN.md`](002-V0_3_1_TAURI_ANDROID_SNAKE_PLAN.md) — plan clôturé de `0.3.1`, second host Snake Tauri Android.
- [`003-V0_3_3_ANDROID_NATIVE_MULTI_ABI_PLAN.md`](003-V0_3_3_ANDROID_NATIVE_MULTI_ABI_PLAN.md) — plan clôturé de `0.3.3`, pipeline Android SDL3 natif Gradle/Cargo multi-ABI.
- [`004-V0_3_4_REALTIME_TRANSPORT_WEBSOCKET_PLAN.md`](004-V0_3_4_REALTIME_TRANSPORT_WEBSOCKET_PLAN.md) — plan clôturé de `0.3.4`, API de transport realtime et baseline WebSocket Tokio/tokio-tungstenite.
- [`005-V0_3_5_WEBTRANSPORT_QUIC_POC_PLAN.md`](005-V0_3_5_WEBTRANSPORT_QUIC_POC_PLAN.md) — plan actif de `0.3.5`, POC WebTransport/QUIC, navigateur, fallback WebSocket et comparaison mesurée.

View File

@@ -0,0 +1,555 @@
<!-- file: docs/plans/005-V0_3_5_WEBTRANSPORT_QUIC_POC_PLAN.md -->
<!-- version: 1 -->
# Plan 0.3.5 — POC WebTransport/QUIC et fallback WebSocket
## Statut
Plan actif créé pendant `0.3.5-alpha.1` à partir de l'archive taggée `v0.3.4`.
Le cadrage détaillé et la comparaison des stacks actuelles sont conservés dans `docs/studies/026-V0_3_5_WEBTRANSPORT_QUIC_STACK_AUDIT.md`. Le présent document porte les décisions opérationnelles, le scope, les gates et le forecast vivant de la version.
## Mission
`0.3.5` doit déterminer par des preuves reproductibles si WebTransport/QUIC mérite de devenir un second backend realtime aux côtés de WebSocket.
La version doit :
- conserver `game-realtime-transport-lib` comme frontière transport-neutral tant qu'aucun besoin commun ne justifie son évolution ;
- implémenter un chemin WebTransport fiable compatible avec `TransportMessage` ;
- prouver client/server natifs en loopback ;
- prouver un chemin navigateur/WASM réel si la stack retenue reste viable ;
- prouver le traitement des certificats de développement sans désactivation permanente de TLS ;
- exercer le fallback WebSocket au niveau composition ;
- comparer WebSocket et WebTransport avec des mesures locales bornées ;
- challenger séparément les datagrams sans les forcer dans le contrat fiable ;
- conclure `retained`, `deferred` ou `rejected` pour la trajectoire produit.
La frontière reste :
```text
transport
wire codec
session protocol
synchronization
authoritative simulation
```
Aucune couche supérieure n'est introduite dans `0.3.5`.
## Décisions acquises en alpha.1
### Stack POC primaire
Famille retenue :
```text
web-transport 0.12.x
native -> web-transport-quinn 0.12.x
wasm32 -> web-transport-wasm 0.6.x
```
La version exacte résolue par Cargo sera enregistrée dans le delta qui introduit les dépendances. Les contraintes restent centralisées sous `[workspace.dependencies]` conformément à `RUST-DEP-001` et les features sont choisies localement par la crate consommatrice.
`wtransport 0.7.x` reste le candidat de repli prioritaire si une exigence concrète bloque la famille primaire. Quinn/H3 brut n'est pas le premier choix.
### Ownership physique
Nouveau backend durable candidat :
```text
crates/common/game-realtime-webtransport-lib
```
Responsabilités :
- établissement WebTransport natif et, si viable, client WASM ;
- adaptation du chemin fiable vers `game-realtime-transport-lib` ;
- framing binaire privé du stream principal ;
- TLS/certificat/hash nécessaires au transport ;
- limites, timeouts, close/reset/cancellation et mapping d'erreurs ;
- tracing `games::realtime::webtransport` ;
- tests natifs déterministes ;
- aucune notion joueur/room/tick/snapshot.
Launchers techniques candidats :
```text
crates/apps/game-realtime-webtransport-smoke
crates/apps/game-realtime-transport-benchmark
```
Un launcher séparé de fallback n'est créé que si le smoke WebTransport ou le benchmark ne peut pas porter proprement cette preuve. Ne pas créer plusieurs exécutables uniquement pour refléter chaque alpha.
Pour le navigateur, le frontend technique exact est décidé au moment de `alpha.7` après validation du chemin WASM. S'il faut un host Vite direct, il doit rester explicitement technique et ne pas contaminer `Web/game-snake-poc` ou le gameplay Snake.
### Contrat commun
`game-realtime-transport-lib` reste inchangé dans le plan initial.
Le chemin fiable utilise :
```text
one WebTransport session
-> one primary bidirectional reliable stream
-> u32 big-endian length
-> payload bytes
```
Le framing est privé au backend, borné avant allocation et distinct du futur wire codec.
Le client ouvre le stream principal ; le serveur l'accepte avant de retourner une connexion utilisable. Le split commun mappe ensuite write/read du stream principal vers `RealtimeSender`/`RealtimeReceiver`.
Toute modification du contrat commun requiert un besoin impossible à satisfaire proprement par WebSocket et WebTransport autrement ; elle n'est pas autorisée pour harmoniser les noms d'API.
### Datagrams
Les datagrams restent hors `RealtimeConnection` parce qu'ils sont non fiables et non ordonnés.
Le POC les exerce uniquement comme capacité backend-spécifique/mesure. Aucune API commune durable n'est créée sans second consommateur réel.
### TLS de développement
Le POC privilégie :
- certificat self-signed X.509v3 court ;
- ECDSA P-256 ;
- validité totale inférieure à deux semaines ;
- pin SHA-256 côté client natif et navigateur ;
- aucune clé privée durable versionnée ;
- aucune désactivation globale de validation TLS.
Le mode PKI publique, ACME et reverse proxy HTTP/3 restent hors scope de `0.3.5`.
### Fallback
Le fallback vit au niveau composition/application :
```text
WebTransport attempt
-> success: WebTransport
-> classified unavailable/establishment failure: WebSocket
```
Le test doit pouvoir forcer les deux branches.
Pas de `TransportManager`, registry de plugins ou sélection dynamique générique dans `game-realtime-transport-lib`.
## Plateformes et preuves
### Linux natif — obligatoire
- compilation backend ;
- client/server loopback sur adresse/port éphémère ;
- round-trip binaire ;
- limites/timeouts/close/reset ;
- smoke runtime hors `#[test]` ;
- mesures locales WebSocket vs WebTransport.
### WASM/navigateur — obligatoire si la stack primaire reste viable
Deux gates distinctes :
1. build/check réel `wasm32-unknown-unknown` du chemin WebTransport Rust ;
2. smoke runtime dans un navigateur récent vers le serveur Rust local.
Le cfg `web_sys_unstable_apis` doit être ciblé sur WASM uniquement.
### Android — trajectoire, pas intégration produit
- vérifier la compatibilité des dépendances et, si raisonnable, compiler le backend pour au moins `aarch64-linux-android` ;
- ne modifier ni Java, ni Gradle, ni JNI sans besoin concret découvert ;
- ne pas rejouer APK/AAB quatre ABI si aucun chemin Android produit n'est touché.
### Apple — documentation uniquement
macOS/iOS restent non validés sans environnement Apple. La version documente la dépendance supposée mais n'attribue aucun smoke.
## Métriques
Mesures obligatoires si les deux transports fonctionnent :
```text
establishment latency
RTT: small payload
throughput: bounded medium payload
several messages in flight
```
Jeu d'essai candidat :
```text
32 B
256 B
1 KiB
16 KiB
```
La taille exacte peut évoluer selon les limites observées, mais reste identique entre transports.
Les résultats doivent inclure au minimum nombre d'itérations et une statistique robuste simple, par exemple médiane et p95. Aucun benchmark loopback ne conclut à lui seul sur Internet/mobile.
CPU/mémoire sont optionnels si la mesure n'est pas stable/reproductible dans la session.
## Smoke tests prévus
### Smoke WebSocket hérité
```bash
cargo run -p game-realtime-websocket-smoke
```
Reste le témoin de fallback et doit être rejoué aux jalons larges où le fallback est concerné.
### Smoke WebTransport natif
Cible prévue :
```bash
cargo run -p game-realtime-webtransport-smoke
```
Il doit :
- générer/charger uniquement l'identité de développement nécessaire ;
- binder localement sans port fixe ;
- établir un client WebTransport ;
- échanger au moins un payload dans chaque sens ;
- fermer proprement ;
- afficher un résultat `PASS` déterministe ;
- ne dépendre ni d'Internet ni d'un secret versionné.
### Smoke navigateur
Le smoke navigateur doit prouver réellement :
- chargement du client WASM retenu ;
- création WebTransport vers le serveur Rust ;
- hash certificat transmis explicitement ;
- round-trip binaire ;
- close propre ;
- absence de fallback silencieux vers WebSocket pendant la preuve WebTransport.
Le workflow exact est fixé dans `alpha.7` après la preuve de compilation WASM.
### Smoke fallback
La preuve de fallback doit couvrir :
- WebTransport disponible -> chemin WebTransport ;
- WebTransport volontairement indisponible/endpoint invalide -> WebSocket ;
- erreur non classée comme fallback -> erreur visible, pas masquée.
Cette preuve peut être intégrée à un launcher technique existant si cela garde le code plus petit et plus clair.
## Tests automatisés prévus
### Backend natif
Au minimum :
- configuration valide/invalide ;
- établissement loopback ;
- payload vide si le contrat l'autorise ;
- payload binaire normal ;
- plusieurs messages ordonnés ;
- taille maximale et dépassement ;
- longueur de frame malformée/overflow impossible ;
- timeout d'établissement ;
- timeout send/receive lorsque reproductible ;
- fermeture locale ;
- fermeture distante ;
- reset/abort du stream principal ;
- drop/cancellation sans task détachée ;
- mapping des erreurs sans fuite des types amont dans le contrat commun.
### WASM
Les tests unitaires qui n'exigent pas de navigateur restent ciblés. L'interop navigateur est un smoke runtime distinct et ne doit pas être simulée par un test natif.
### Fallback
Tester la classification et la décision de composition sans créer une abstraction runtime générique.
## Graphe de dépendances attendu
```text
game-realtime-transport-lib
├── game-realtime-websocket-lib
└── game-realtime-webtransport-lib
```
Aucune crate sous :
```text
crates/engines/
crates/games/
```
doit dépendre de `web-transport`, Quinn, Rustls ou d'un backend concret.
Les launchers techniques peuvent dépendre des backends nécessaires à leur preuve.
## Hors scope
- wire codec définitif ;
- session joueur/room ;
- matchmaking/auth ;
- snapshots/deltas gameplay ;
- prediction/reconciliation/rollback ;
- simulation authoritative ;
- Uroburas Mode 3 ;
- persistence gameplay ;
- cluster/sharding/regions ;
- Redis/NATS/Kafka ;
- PKI/ACME produit ;
- reverse proxy HTTP/3 définitif ;
- CDN/edge ;
- framework générique multi-transport ;
- réécriture Actix Web ;
- modification du gameplay pour sélectionner un transport.
## Risques et critères de replanification
La version est replanifiée avant exécution lorsqu'une tranche dépasse clairement 30 minutes de scope attendu.
Déclencheurs explicites :
- compilation de la stack primaire impossible avec les règles Rust du dépôt ;
- besoin d'un fork amont ;
- browser smoke exigeant une infrastructure externe ou PKI disproportionnée ;
- dépendance crypto rendant Android ou Linux non praticable ;
- évolution du contrat commun requise ;
- framing fiable beaucoup plus complexe que prévu ;
- fallback nécessitant une abstraction partagée nouvelle ;
- benchmark devenant un sous-projet de performance.
Dans ces cas, le delta courant reste fermé sur sa preuve et le plan est révisé avant la tranche suivante.
## Forecast révisé
Chaque tranche vise environ 15 à 30 minutes de travail effectif et une preuve indépendante. Les numéros restent prévisionnels conformément à `SESSION-007`.
### `0.3.5-alpha.1` — cadrage, audit et plan
- audit archive/règles/historique `0.3.4` ;
- recherche stacks WebTransport/QUIC ;
- choix primaire + fallback technique ;
- décision contrat/framing/datagram ;
- matrice TLS/plateforme ;
- smoke/tests/metrics ;
- plan vivant.
Aucun backend ni dépendance WebTransport ajouté.
### `0.3.5-alpha.2` — crate backend, dépendances et établissement natif
- créer `game-realtime-webtransport-lib` ;
- ajouter uniquement les dépendances/features nécessaires ;
- config native client/server ;
- génération ou injection d'identité de test ;
- hash pinning ;
- établir une session native client/server ;
- tests d'établissement/configuration ;
- README initial de responsabilité/frontières.
Pas encore d'implémentation complète `RealtimeConnection` si cela rend la tranche trop lourde.
### `0.3.5-alpha.3` — stream fiable et contrat commun
- stream bidirectionnel principal ;
- framing `u32 + payload` borné ;
- `RealtimeConnection`, sender et receiver ;
- round-trip ordonné multi-message ;
- fermeture distante de base ;
- tests loopback ciblés ;
- USAGE si l'API/configuration devient non triviale.
### `0.3.5-alpha.4` — robustesse et lifecycle
- limites ;
- deadlines ;
- backpressure/erreurs observables ;
- close/reset/abort ;
- cancellation/drop ;
- cas négatifs de framing ;
- mapping d'erreurs ;
- tests de robustesse ciblés.
### `0.3.5-alpha.5` — smoke natif hors harness
- créer ou finaliser `game-realtime-webtransport-smoke` ;
- round-trip réel localhost ;
- certificat/hash de développement reproductible ;
- `PASS` déterministe ;
- contrôle du graphe de dépendances.
Cette tranche reste distincte pour ne pas mélanger robustesse de bibliothèque et preuve runtime publique.
### `0.3.5-alpha.6` — chemin WASM compilable
- activer `web_sys_unstable_apis` uniquement pour `wasm32-unknown-unknown` ;
- implémenter/adapter le client WASM ;
- prouver le build/check WASM ciblé ;
- ne pas modifier Snake ou Reflex ;
- documenter les différences native/WASM réellement rencontrées.
Si la famille `web-transport` échoue ici, évaluer `wtransport` serveur + API navigateur directe avant de conclure.
### `0.3.5-alpha.7` — interop navigateur et TLS local
- host technique minimal si nécessaire ;
- navigateur récent -> serveur Rust WebTransport ;
- hash certificat W3C ;
- round-trip binaire ;
- close propre ;
- smoke documenté et reproductible ;
- aucune désactivation permanente de TLS.
Cette tranche est volontairement séparée de `alpha.6` car certificat, serveur local et browser tooling constituent un risque opérationnel distinct.
### `0.3.5-alpha.8` — fallback WebSocket au niveau composition
- tentative WebTransport ;
- fallback WebSocket uniquement sur erreurs classifiées ;
- branche WebTransport forcée ;
- branche fallback forcée ;
- erreur non-fallback visible ;
- aucun couplage gameplay ;
- pas de registry/framework générique.
### `0.3.5-alpha.9` — datagram POC isolé
Uniquement si le backend fiable et le navigateur sont suffisamment stables :
- émission/réception datagram ;
- pertes/ordre non garantis documentés ;
- preuve locale bornée ;
- aucune modification du contrat commun ;
- décision explicite : utile pour future capability ou simple constat.
Si la valeur est déjà claire sans API supplémentaire, cette tranche peut être fusionnée avec la mesure ou supprimée.
### `0.3.5-alpha.10` — mesures comparatives bornées
- launcher/outil minimal de mesure ;
- WebSocket vs WebTransport fiable ;
- établissement, RTT, throughput, messages en vol ;
- datagram seulement s'il existe réellement ;
- résultats et limites de méthode documentés ;
- conclusion technique provisoire `retain/defer/reject`.
### `0.3.5-beta.1` — validation large
Jalon rare de full workspace :
```bash
cargo test --workspace --all-targets --all-features
```
Plus :
- fmt/check/Clippy/audits ;
- tests ciblés realtime ;
- smoke WebSocket ;
- smoke WebTransport natif ;
- smoke navigateur si retenu ;
- preuve fallback ;
- `cargo tree` direct/inverse des deux backends ;
- vérification qu'aucun gameplay/engine ne dépend d'un backend concret.
Toute capacité fonctionnelle majeure manquante réouvre une alpha ; un défaut fermé produit `beta.1.fix.N`.
### `0.3.5-beta.2` — consolidation pré-RC
Tranche explicitement réservée par `SESSION-009` / `VER-PHASE-010` :
- réconcilier README/USAGE et docs durables ;
- figer la conclusion WebTransport ;
- documenter plateformes réellement validées/non validées ;
- mettre à jour `CHANGELOG.md` si la transition vers RC est préparée ;
- réconcilier `ROADMAP.md` seulement si le statut macro change ;
- écrire le prompt `0.3.6` ;
- enregistrer l'historique `beta.1` après validation ;
- aucune nouvelle fonctionnalité majeure.
### `0.3.5-rc.1` — candidate gelée
- aucun comportement volontaire nouveau ;
- full workspace conformément à `CMD-RC-002` ;
- gates realtime de publication ;
- smokes retenus ;
- graphe de dépendances ;
- vérification du prompt `0.3.6` ;
- corrections uniquement selon `VER-RC-*`.
### `0.3.5` — stable
Promotion mécanique autant que possible :
- version stable ;
- historique RC ;
- changelog stable ;
- clôture du plan ;
- roadmap si nécessaire ;
- delta final ;
- ajustement mécanique du prompt `0.3.6`.
## Gates Cargo planifiées
### Tranches Rust ordinaires
Dès qu'un fichier Rust/Cargo change :
```bash
cargo fmt --all
cargo fmt --all -- --check
python3 scripts/audit_rust_workspace_rules.py
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
```
Puis tests ciblés des crates touchées/consommateurs affectés.
### Full workspace
`cargo test --workspace --all-targets --all-features` est réservé explicitement à :
- `beta.1` ;
- `rc.1` ;
- éventuellement une tranche plus tôt uniquement si un changement transverse rend les tests ciblés insuffisants.
Il n'est pas répété à chaque alpha.
### Cargo tree
À exécuter :
- après introduction/changement de dépendances WebTransport ;
- à `alpha.5` pour prouver la frontière ;
- à `beta.1` et `rc.1` pour les graphes de publication.
## Nettoyage Cargo
Aucun `cargo clean` n'est requis dans `alpha.1`.
Le plan réserve un nettoyage complet au plus tard avant la validation RC si l'accumulation du target-dir ou un doute de reproductibilité le justifie. Un nettoyage ciblé reste préférable pendant les alphas.
## Critère de réussite de 0.3.5
La version est réussie si elle fournit une conclusion reproductible parmi :
```text
retained -> second backend utile, conserver pour 0.4.x
deferred -> viable mais bénéfice/portabilité/infrastructure insuffisants aujourd'hui
rejected -> coût ou incompatibilité disproportionnés pour la trajectoire actuelle
```
Aucune conclusion n'est imposée à l'avance.
Même en cas de report/rejet, la baseline WebSocket `0.3.4` reste fonctionnelle et le POC ne doit pas laisser une abstraction commune artificiellement déformée.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/studies/000-README.md -->
<!-- version: 11 -->
<!-- version: 12 -->
# Études
@@ -65,3 +65,7 @@ Ces documents étudient les POC à réaliser ; ils ne lancent encore aucune impl
## Étude de cadrage 0.3.3
- [`025-V0_3_3_ANDROID_NATIVE_MULTI_ABI_AUDIT.md`](025-V0_3_3_ANDROID_NATIVE_MULTI_ABI_AUDIT.md) — audit de la baseline `0.3.1`, toolchain Android native actuelle, choix ABI/API, packaging APK/AAB et contraintes 16 KB.
## Étude de cadrage 0.3.5
- [`026-V0_3_5_WEBTRANSPORT_QUIC_STACK_AUDIT.md`](026-V0_3_5_WEBTRANSPORT_QUIC_STACK_AUDIT.md) — audit de la stable `0.3.4`, comparaison des stacks WebTransport/QUIC actuelles, compatibilité du contrat realtime, TLS, navigateurs et sizing de `0.3.5`.

View 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`.