Files
games/docs/plans/005-V0_3_5_WEBTRANSPORT_QUIC_POC_PLAN.md
2026-09-21 21:21:28 +02:00

18 KiB

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 :

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 :

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 :

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 :

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 :

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 :

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 :

establishment latency
RTT: small payload
throughput: bounded medium payload
several messages in flight

Jeu d'essai candidat :

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é

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 :

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

game-realtime-transport-lib
    ↑
    ├── game-realtime-websocket-lib
    └── game-realtime-webtransport-lib

Aucune crate sous :

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 :

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 :

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 :

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.