6.8 KiB
Delta 0.3.5-alpha.8
Base requise
0.3.5-alpha.7.fix.2, validée par l'utilisateur le 2026-09-22.
La gate finale confirme fmt, audits, cargo check --workspace, Clippy strict, build WASM de l'adapter browser, génération wasm-bindgen, build TypeScript/Vite et smoke WebTransport navigateur réel terminé par :
game-realtime-webtransport-browser-smoke: PASS
La preuve complète est enregistrée dans history/0.3.5/alpha.7.fix.2.md.
Objectif
Prouver le fallback WebSocket au niveau composition sans modifier le contrat transport-neutral ni masquer les erreurs sensibles :
- essayer WebTransport en premier ;
- conserver WebTransport lorsqu'il est disponible ;
- basculer vers WebSocket uniquement pour des erreurs explicitement classifiées ;
- forcer une branche fallback déterministe ;
- garder une erreur non-fallback visible ;
- ne créer ni manager générique, ni registry, ni couplage gameplay.
Version
La version workspace passe à :
0.3.5-alpha.8
Launcher de composition
Nouveau package technique :
crates/apps/game-realtime-transport-fallback-smoke
Il dépend directement des deux backends candidats et du contrat commun, mais d'aucun engine ni gameplay.
Le sélecteur reste privé au launcher :
WebTransport attempt
-> success -> WebTransport
-> classified Timeout/Io -> WebSocket attempt
-> any other error -> visible error
Aucune API n'est ajoutée à game-realtime-transport-lib, game-realtime-websocket-lib ou game-realtime-webtransport-lib.
Classification conservative
Le backend WebTransport natif mappe actuellement les erreurs amont d'établissement sous une catégorie Connect trop large pour distinguer de manière sûre une indisponibilité réseau d'un problème TLS/pinning.
Pour éviter un downgrade silencieux, alpha.8 autorise le fallback uniquement pour :
Timeout
Io
et refuse explicitement le fallback pour :
InvalidConfiguration
Connect
Bind
Accept
MessageTooLarge
Backpressure
Closed
Protocol
Aborted
Cette politique est volontairement plus restrictive qu'un fallback générique sur toute erreur de connexion. Une évolution future pourra élargir la matrice uniquement si le backend expose une classification suffisamment précise pour préserver les erreurs de sécurité/protocole.
Smoke runtime
Le launcher exécute trois scénarios séquentiels sous une deadline globale de 10 s.
1. WebTransport disponible
- serveur WebTransport loopback réel sur port éphémère ;
- identité P-256 en mémoire et pin SHA-256 exact ;
- sélection WebTransport-first ;
- fallback WebSocket volontairement inutilisable si appelé ;
- round-trip binaire dans les deux sens ;
- fermeture propre dans les deux sens.
2. Fallback WebSocket forcé
- erreur WebTransport
Timeoutinjectée explicitement au point de composition ; - listener WebSocket loopback réel sur port éphémère ;
- sélection de la branche fallback ;
- round-trip binaire dans les deux sens ;
- fermeture propre dans les deux sens.
L'injection ne simule pas le backend WebSocket : elle force uniquement la cause WebTransport classifiée afin que la branche de sélection soit déterministe et rapide. La connexion fallback et son échange restent réels.
3. Erreur non-fallback visible
- vraie
WebTransportClientConfigavecconnect_timeout = 0; game-realtime-webtransport-lib::connect()retourneInvalidConfigurationavant I/O ;- la branche WebSocket ne doit pas être utilisée ;
- l'erreur exacte
connect_timeout must be greater than zerodoit rester visible.
Le verdict global attendu est :
game-realtime-transport-fallback-smoke: PASS
Tests unitaires
Le binary contient également des tests ciblés qui vérifient :
- la matrice
TransportErrorKindcomplète ; Connectexplicitement non éligible ;- succès WebTransport prioritaire ;
Timeoutdéclenchant la valeur WebSocket ;InvalidConfigurationrestant inchangée et visible.
Audit de distribution
scripts/audit_distribution_layout.py ajoute les chemins du launcher et vérifie :
- dépendance directe aux deux backends ;
- aucune dépendance engine/gameplay ;
- classification limitée à
Timeout/Io; - exclusion explicite de
Connect; - verdict
PASSdéterministe.
Fichiers modifiés
Cargo.toml
README.md
docs/plans/005-V0_3_5_WEBTRANSPORT_QUIC_POC_PLAN.md
scripts/audit_distribution_layout.py
Nouveaux fichiers :
crates/apps/game-realtime-transport-fallback-smoke/Cargo.toml
crates/apps/game-realtime-transport-fallback-smoke/src/main.rs
crates/apps/game-realtime-transport-fallback-smoke/unit_tests/fallback.rs
deltas/0.3.5/alpha.8.md
history/0.3.5/alpha.7.fix.2.md
Validation attendue
cargo fmt --all
cargo fmt --all -- --check
python3 scripts/audit_rust_workspace_rules.py
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates Android Web deltas history
python3 scripts/audit_distribution_layout.py
cargo check --workspace
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test -p game-realtime-transport-lib --all-targets --all-features
cargo test -p game-realtime-websocket-lib --all-targets --all-features
cargo test -p game-realtime-webtransport-lib --all-targets --all-features
cargo test -p game-realtime-transport-fallback-smoke --all-targets --all-features
cargo run -p game-realtime-websocket-smoke
cargo run -p game-realtime-webtransport-smoke
cargo run -p game-realtime-transport-fallback-smoke
cargo tree -p game-realtime-transport-fallback-smoke --edges normal
cargo tree -i game-realtime-websocket-lib --workspace --edges normal
cargo tree -i game-realtime-webtransport-lib --workspace --edges normal
Le nouveau smoke doit terminer par :
game-realtime-transport-fallback-smoke: PASS
Les graphes inverses peuvent contenir les launchers techniques, mais aucun engine ni crate gameplay ne doit dépendre des backends concrets.
Contrôles statiques avant livraison
Le candidat a été vérifié côté générateur sans attribuer de résultat Cargo non exécuté :
General Rust rule audit: clean
Rust export completeness audit: 0 candidate(s)
games.sasedev workspace audit: clean
Markdown table audit: clean (5 table(s), 286 file(s))
Distribution layout audit: clean (61 required path(s), 8 forbidden path(s) absent)
Cargo.toml parse: clean
La compilation, Clippy, les tests et les smokes restent à exécuter dans la gate utilisateur ci-dessus.
Après validation
Créer history/0.3.5/alpha.8.md à partir des sorties réellement fournies, puis ouvrir 0.3.5-alpha.9 pour le POC datagram isolé si cette tranche reste justifiée par l'API/backend réellement disponibles.