# Delta 0.3.4-alpha.4 ## Base Base directe : `0.3.4-alpha.3.fix.1`, validée par l'utilisateur le 2026-09-21. Cette tranche n'élargit pas le contrat transport-neutral et n'introduit ni session gameplay, ni wire codec, ni TLS. Elle ferme les limites, deadlines et principaux cas négatifs du backend WebSocket avant la validation large. ## Historique du jalon précédent Ajout de : ```text history/0.3.4/alpha.3.fix.1.md ``` L'historique enregistre la gate utilisateur réellement fournie : audits propres, workspace/Clippy propres, sept tests transport, loopback WebSocket propre et graphe normal sans pile TLS. ## Configuration WebSocket produit Ajout de `WebSocketConfig`, réexportée au crate-root de `game-realtime-websocket-lib`. Valeurs par défaut : ```text max message size 1 MiB max frame size 1 MiB write buffer target 64 KiB max write buffer 2 MiB connect/handshake 10 s send 5 s close 2 s receive idle timeout aucun ``` La configuration peut être ajustée par builders `with_*` puis validée. Les invariants refusent notamment : - message/frame de taille nulle ; - frame maximale supérieure au message maximal ; - write buffer maximal incapable de contenir le target plus un message maximal ; - overflow de ce calcul ; - deadline connect/send/close nulle. Les wrappers `connect()` et `WebSocketListener::bind()` restent disponibles avec la configuration par défaut. Les nouveaux chemins configurables sont : ```text connect_with_config(endpoint, config) WebSocketListener::bind_with_config(address, config) ``` ## Limites et backpressure Les limites message/frame/write-buffer sont transmises à `tungstenite::protocol::WebSocketConfig` aussi bien côté client que côté serveur. Le send vérifie également `max_message_size` et `max_frame_size` avant l'écriture afin que le dépassement sortant soit déterministe et remonte `TransportErrorKind::MessageTooLarge` sans dépendre d'un comportement réseau. `max_write_buffer_size` est borné à `2 MiB` par défaut. `tungstenite::Error::WriteBufferFull` continue d'être mappé vers `TransportErrorKind::Backpressure` et ce mapping dispose désormais d'un test unitaire dédié. Aucun test loopback ne fabrique une saturation artificielle : le write buffer Tungstenite ne grossit au-delà de son target que lors d'échecs d'écriture sous-jacents, ce qui rendrait ce scénario réseau local non déterministe. ## Timeouts et lifecycle La feature Tokio `time` devient une dépendance de production uniquement pour `game-realtime-websocket-lib`. Les deadlines sont appliquées ainsi : - connexion client complète : `connect_timeout` ; - handshake serveur après accept TCP : `connect_timeout` ; - émission d'un message : `send_timeout` ; - fermeture locale du sink : `close_timeout`. L'attente d'un nouveau peer sur `TcpListener::accept()` n'est volontairement pas bornée par la configuration d'une connexion. `receive()` ne reçoit aucun idle timeout : heartbeat et inactivité appartiennent aux futures couches session/synchronisation. Si un send expire, la moitié émission mémorise cet état et refuse un nouvel envoi avec `TransportErrorKind::Aborted`. Le send interrompu peut avoir progressé partiellement ; il ne doit donc jamais être rejoué implicitement comme s'il n'avait rien produit. Une fermeture explicite reste néanmoins tentable avec sa propre deadline. Le backend continue de ne créer aucun runtime, thread ou task détachée. ## Tests ajoutés Tests unitaires de configuration : - defaults produit exacts ; - limites message/frame/write-buffer invalides ; - deadlines nulles invalides. Tests unitaires de mapping backend : - `WriteBufferFull -> Backpressure` ; - `Capacity -> MessageTooLarge`. Nouveau `tests/robustness.rs` : 1. payload sortant hors limite rejeté avant écriture ; 2. payload entrant hors limite rejeté par Tungstenite ; 3. frame Text rejetée par le contrat binaire ; 4. peer drop sans close handshake remonté comme erreur de protocole ; 5. peer TCP silencieux borné par le timeout de handshake serveur. Tous les scénarios réseau utilisent uniquement `127.0.0.1:0` et une borne externe de test de trois secondes. ## Documentation Le plan actif `docs/plans/004-V0_3_4_REALTIME_TRANSPORT_WEBSOCKET_PLAN.md` est mis à jour avec : - validation effective de `alpha.3.fix.1` ; - configuration et deadlines retenues ; - raison de l'absence d'idle timeout transport ; - stratégie backpressure testable sans test réseau flaky ; - orientation vers beta ou courte consolidation selon le résultat réel de cette gate. `CHANGELOG.md` et `ROADMAP.md` restent inchangés : la version est encore en alpha et le scope macroscopique `0.3.4` ne change pas. ## Fichiers Modifiés : ```text Cargo.toml README.md crates/common/game-realtime-websocket-lib/Cargo.toml crates/common/game-realtime-websocket-lib/src/lib.rs crates/common/game-realtime-websocket-lib/src/websocket.rs docs/plans/004-V0_3_4_REALTIME_TRANSPORT_WEBSOCKET_PLAN.md ``` Ajoutés : ```text crates/common/game-realtime-websocket-lib/src/config.rs crates/common/game-realtime-websocket-lib/unit_tests/config.rs crates/common/game-realtime-websocket-lib/unit_tests/websocket.rs crates/common/game-realtime-websocket-lib/tests/robustness.rs history/0.3.4/alpha.3.fix.1.md deltas/0.3.4/alpha.4.md ``` ## Validation attendue ```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-transport-lib --all-targets --all-features cargo test -p game-realtime-websocket-lib --all-targets --all-features cargo tree -p game-realtime-websocket-lib --edges normal ``` La validation utilisateur reste autoritaire pour la compilation, Clippy et les tests runtime. Les audits statiques exécutables dans l'environnement de génération doivent être propres avant livraison du delta.