# Delta 0.3.5-alpha.2 ## Base Base : `0.3.5-alpha.1` validée par l'utilisateur le 2026-09-21. Cette tranche reste limitée à la fondation WebTransport native prévue par le plan : dépendances minimales, identité TLS, pin SHA-256, bind QUIC/HTTP3 et établissement d'une session client/server. Elle ne contient encore ni stream applicatif principal, ni framing `u32 + payload`, ni adaptation `RealtimeConnection`, ni datagram, ni fallback. ## Historique fermé Ajout de : ```text history/0.3.5/alpha.1.md ``` L'entrée enregistre exactement la gate utilisateur reçue : fmt check, trois audits propres et `cargo check --workspace` propre sur `0.3.5-alpha.1`. Le plan révisé a été explicitement accepté avant le passage à cette tranche. ## Version La version workspace passe de : ```text 0.3.5-alpha.1 ``` à : ```text 0.3.5-alpha.2 ``` Aucune version Android, npm ou Tauri indépendante n'est modifiée. ## Nouvelle crate WebTransport Ajout de : ```text crates/common/game-realtime-webtransport-lib/Cargo.toml crates/common/game-realtime-webtransport-lib/README.md crates/common/game-realtime-webtransport-lib/src/lib.rs crates/common/game-realtime-webtransport-lib/src/webtransport.rs crates/common/game-realtime-webtransport-lib/unit_tests/webtransport.rs crates/common/game-realtime-webtransport-lib/tests/establishment.rs ``` La crate est placée sous `crates/common/` au même niveau que le contrat transport-neutral et le backend WebSocket. Elle ne contient aucune sémantique de jeu. ## Dépendances et features Les contraintes nouvelles sont centralisées dans `[workspace.dependencies]` : ```text rcgen = 0.14.10, default-features = false url = 2.5.8 web-transport-quinn = 0.12.1, default-features = false ``` La crate consommatrice active localement uniquement `ring` sur `rcgen` et `web-transport-quinn`. `web-transport-quinn` est utilisé directement dans cette tranche native. La façade multiplateforme `web-transport` reste différée jusqu'au chemin WASM, afin de ne pas introduire une dépendance sans consommateur réel. Le backend crypto par défaut `aws-lc-rs` de `web-transport-quinn` est donc désactivé. `ring` devient le provider unique du POC natif initial. ## Identité TLS et pinning `WebTransportServerIdentity` accepte deux chemins : ```text generate_loopback() from_pkcs8_der(certificate_der, private_key_pkcs8_der) ``` La génération loopback produit en mémoire : - une clé ECDSA P-256 ; - un certificat self-signed avec SHA-256 ; - les SAN `localhost`, `127.0.0.1` et `::1` ; - une validité de sept jours avec 60 secondes de marge avant l'heure courante ; - aucun PEM ni fichier de clé versionné. `WebTransportCertificateHash` porte exactement les 32 octets SHA-256 du certificat. Le client configure `ClientBuilder::with_server_certificate_hashes(...)` ; aucune option de TLS permissif n'est exposée. L'injection DER ne prétend pas parser ou certifier la cohérence clé/certificat avant le bind : le builder TLS natif reste l'autorité qui rejette une paire incompatible. ## Configuration et établissement natif `WebTransportClientConfig` impose un endpoint `https://` valide et un hash épinglé. `WebTransportServerConfig` possède l'adresse UDP et l'identité TLS. `WebTransportListener::bind(...)` : - construit le serveur Quinn/WebTransport ; - supporte le port `0` pour une allocation éphémère ; - expose l'adresse effectivement bindée ; - mappe les erreurs vers `TransportErrorKind::Bind`. `WebTransportListener::accept(...)` accepte le CONNECT HTTP/3 et retourne une `WebTransportSession`. `connect(...)` construit un client pinned et retourne également une `WebTransportSession`. Les erreurs d'établissement client sont mappées vers `Connect`; les erreurs serveur vers `Accept`. La session expose uniquement des diagnostics d'établissement (`remote_addr`, URL CONNECT). Le stream fiable applicatif appartient explicitement à `alpha.3`. ## Tests ajoutés Les tests unitaires couvrent : - conservation exacte d'un SHA-256 de 32 octets ; - acceptation d'un endpoint HTTPS ; - rejet HTTP/WebSocket ; - rejet d'une identité injectée sans certificat ou sans clé ; - génération d'une identité loopback avec fingerprint SHA-256. Le test d'intégration `establishment.rs` couvre : - bind sur `127.0.0.1:0` ; - génération d'identité éphémère ; - pin SHA-256 transmis au client ; - établissement client/server concurrent borné par timeout ; - URL CONNECT observée des deux côtés ; - rejet d'un mauvais pin côté client. Il ne transmet volontairement aucun payload : ce serait anticiper `alpha.3`. ## Tracing Le nouveau backend utilise : ```text games::realtime::webtransport ``` pour bind, connexion, accept et diagnostics d'échec d'établissement. ## Documentation et plan `README.md` racine annonce `0.3.5-alpha.2` et la nouvelle frontière native. Le README local documente la responsabilité de la crate, le TLS de développement et les frontières encore exclues. Le plan `005` est réconcilié avec les choix réellement fermés : dépendances natives directes, provider `ring`, identité sept jours et absence volontaire de façade `web-transport` avant le chemin WASM. `ROADMAP.md` et `CHANGELOG.md` restent inchangés : le scope macro de `0.3.5` ne change pas et cette alpha n'est pas un jalon de changelog. ## Validation exécutée dans l'environnement de génération L'environnement de génération ne possède pas de toolchain Rust. Il ne doit donc attribuer aucun `cargo fmt`, `cargo check`, Clippy, test ou `cargo tree` à cette livraison. Les audits Python et contrôles statiques sont exécutés après constitution du delta. Sur la reconstruction locale issue du ZIP taggé `v0.3.4` puis du delta `alpha.1`, ils donnent : ```text General Rust rule audit: clean Rust export completeness audit: 0 candidate(s) games.sasedev workspace audit: clean Markdown table audit: clean (5 table(s), 269 file(s)) Distribution layout audit: clean (50 required path(s), 8 forbidden path(s) absent) TOML/workspace consistency: clean ``` Le compteur de fichiers Markdown de cette reconstruction n'est pas utilisé comme référence pour le checkout utilisateur : la gate `alpha.1` de l'utilisateur comptait déjà davantage de fichiers (`282`) que la reconstruction autoritaire ZIP + delta. Seul le statut clean est comparé. Ces contrôles restent distincts de la gate Cargo utilisateur. ## Validation utilisateur demandée Cette tranche modifie Rust et le graphe de dépendances ; la gate ciblée est donc : ```bash 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-webtransport-lib --all-targets --all-features cargo tree -p game-realtime-webtransport-lib --edges normal cargo tree -p game-realtime-webtransport-lib --edges features cargo tree -i web-transport-quinn --workspace --edges normal ``` Le full `cargo test --workspace --all-targets --all-features` reste réservé au jalon large `beta.1` conformément au plan. Aucun smoke executable n'est requis dans `alpha.2` : le test d'intégration prouve l'établissement natif sous harness, tandis que le smoke WebTransport public reste la responsabilité explicite de `alpha.5` après le framing fiable et la robustesse. ## Suite après validation Si la gate est propre, `0.3.5-alpha.3` peut : - ouvrir/ accepter le stream bidirectionnel principal ; - ajouter le framing privé borné `u32 big-endian + payload` ; - implémenter `RealtimeConnection`, sender et receiver ; - prouver le round-trip binaire ordonné et plusieurs messages ; - conserver datagrams, robustesse avancée et smoke public hors de cette tranche. Un défaut fermé de cette tranche produit d'abord `0.3.5-alpha.2.fix.N` au lieu d'ouvrir `alpha.3`.