0.3.5-alpha.5
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# file: Cargo.toml
|
||||
# version: 100
|
||||
# version: 101
|
||||
|
||||
[workspace]
|
||||
resolver = "3"
|
||||
@@ -10,6 +10,7 @@ members = [
|
||||
"crates/games/game-reflex-poc",
|
||||
"crates/games/game-snake-poc",
|
||||
"crates/apps/game-realtime-websocket-smoke",
|
||||
"crates/apps/game-realtime-webtransport-smoke",
|
||||
"crates/apps/game-reflex-poc-desktop",
|
||||
"crates/apps/game-snake-poc-desktop",
|
||||
"crates/common/game-assets-lib",
|
||||
@@ -25,7 +26,7 @@ members = [
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.3.5-alpha.4.fix.1"
|
||||
version = "0.3.5-alpha.5"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
repository = "https://git.sasedev.com/Sasedev/games"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: README.md -->
|
||||
<!-- version: 68 -->
|
||||
<!-- version: 69 -->
|
||||
|
||||
# games.sasedev
|
||||
|
||||
@@ -27,9 +27,9 @@ Workspace expérimental puis productif pour des jeux multiplateformes principale
|
||||
|
||||
Version stable de référence : `0.3.4`.
|
||||
|
||||
Version active : `0.3.5-alpha.4.fix.1`. `0.3.2` reste différée.
|
||||
Version active : `0.3.5-alpha.5`. `0.3.2` reste différée.
|
||||
|
||||
La stable `0.3.4` livre la première baseline realtime : contrat binaire transport-neutral, backend WebSocket Tokio/tokio-tungstenite, limites et deadlines, tests loopback/robustesse, smoke runtime localhost public et frontières de dépendances empêchant moteurs et gameplay de dépendre d'un backend concret. `0.3.5-alpha.4.fix.1` consolide le backend WebTransport natif avec limite de message configurable, deadlines connexion/stream/send, mapping d'erreurs, reset/abort/drop explicites et parseur de framing incrémental résistant à l'annulation ; le fix ferme uniquement le lint strict `implicit-return` révélé par la gate de `alpha.4` sans changer le comportement runtime. Navigateur/WASM, smoke public, fallback et datagrams restent réservés aux tranches suivantes.
|
||||
La stable `0.3.4` livre la première baseline realtime : contrat binaire transport-neutral, backend WebSocket Tokio/tokio-tungstenite, limites et deadlines, tests loopback/robustesse, smoke runtime localhost public et frontières de dépendances empêchant moteurs et gameplay de dépendre d'un backend concret. `0.3.5-alpha.5` ajoute au backend WebTransport natif déjà robuste un smoke runtime localhost hors harness : identité TLS locale en mémoire, pin SHA-256 exact, session WebTransport réelle, stream fiable principal, round-trip binaire bidirectionnel et fermeture propre avec verdict `PASS` déterministe. Navigateur/WASM, fallback et datagrams restent réservés aux tranches suivantes.
|
||||
|
||||
Les deux premiers jeux sont des POC structurels : `game-reflex-poc` et `game-snake-poc`. Ils existent d'abord pour valider les frontières du workspace, le moteur, les assets et le packaging multiplateforme.
|
||||
|
||||
@@ -45,4 +45,4 @@ Les deux premiers jeux sont des POC structurels : `game-reflex-poc` et `game-sna
|
||||
|
||||
## Diagnostics et tests
|
||||
|
||||
Les socles transverses `crates/common/game-assets-lib` et `crates/common/game-logging-lib` fournissent respectivement la résolution logique des assets et le tracing commun. Le realtime est séparé entre `game-realtime-transport-lib`, contrat binaire transport-neutral, `game-realtime-websocket-lib`, backend Tokio/tokio-tungstenite, et `game-realtime-webtransport-lib`, backend WebTransport/QUIC candidat dont le chemin natif couvre désormais TLS/pinning, établissement de session et stream fiable principal adapté au contrat commun. Leurs responsabilités sont documentées dans leurs README/USAGE locaux lorsqu'un guide d'usage est justifié. `game-realtime-websocket-smoke` fournit la preuve runtime localhost hors harness de test ; le smoke WebTransport public est planifié après la tranche de robustesse. Les tests unitaires résident hors `src/` sous `unit_tests/`; les tests d’intégration/environnement résident sous `tests/`.
|
||||
Les socles transverses `crates/common/game-assets-lib` et `crates/common/game-logging-lib` fournissent respectivement la résolution logique des assets et le tracing commun. Le realtime est séparé entre `game-realtime-transport-lib`, contrat binaire transport-neutral, `game-realtime-websocket-lib`, backend Tokio/tokio-tungstenite, et `game-realtime-webtransport-lib`, backend WebTransport/QUIC candidat dont le chemin natif couvre désormais TLS/pinning, établissement de session et stream fiable principal adapté au contrat commun. Leurs responsabilités sont documentées dans leurs README/USAGE locaux lorsqu'un guide d'usage est justifié. `game-realtime-websocket-smoke` et `game-realtime-webtransport-smoke` fournissent les preuves runtime localhost hors harness des deux backends fiables natifs. Les tests unitaires résident hors `src/` sous `unit_tests/`; les tests d’intégration/environnement résident sous `tests/`.
|
||||
|
||||
21
crates/apps/game-realtime-webtransport-smoke/Cargo.toml
Normal file
21
crates/apps/game-realtime-webtransport-smoke/Cargo.toml
Normal file
@@ -0,0 +1,21 @@
|
||||
# file: crates/apps/game-realtime-webtransport-smoke/Cargo.toml
|
||||
# version: 1
|
||||
|
||||
[package]
|
||||
name = "game-realtime-webtransport-smoke"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
authors.workspace = true
|
||||
publish.workspace = true
|
||||
|
||||
[dependencies]
|
||||
game-logging-lib = { path = "../../common/game-logging-lib" }
|
||||
game-realtime-transport-lib = { path = "../../common/game-realtime-transport-lib" }
|
||||
game-realtime-webtransport-lib = { path = "../../common/game-realtime-webtransport-lib" }
|
||||
tokio = { workspace = true, features = ["macros", "rt", "time"] }
|
||||
tracing.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
134
crates/apps/game-realtime-webtransport-smoke/src/main.rs
Normal file
134
crates/apps/game-realtime-webtransport-smoke/src/main.rs
Normal file
@@ -0,0 +1,134 @@
|
||||
// file: crates/apps/game-realtime-webtransport-smoke/src/main.rs
|
||||
// version: 1
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unreachable_pub)]
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
//! Executable localhost smoke for the public games.sasedev native WebTransport realtime path.
|
||||
|
||||
use game_realtime_transport_lib::RealtimeConnection; // rust-rules: trait-import
|
||||
use game_realtime_transport_lib::RealtimeReceiver; // rust-rules: trait-import
|
||||
use game_realtime_transport_lib::RealtimeSender; // rust-rules: trait-import
|
||||
|
||||
const CLIENT_PAYLOAD: &[u8] = b"games.sasedev-webtransport-client-smoke";
|
||||
const SERVER_PAYLOAD: &[u8] = b"games.sasedev-webtransport-server-smoke";
|
||||
const SMOKE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);
|
||||
const TRACING_TARGET: &str = "games::realtime::webtransport::smoke";
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() -> std::process::ExitCode {
|
||||
let _logging_guard = match game_logging_lib::init_console_tracing() {
|
||||
std::result::Result::Ok(guard) => guard,
|
||||
std::result::Result::Err(error) => {
|
||||
eprintln!("failed to initialize realtime WebTransport smoke tracing: {error}");
|
||||
return std::process::ExitCode::FAILURE;
|
||||
},
|
||||
};
|
||||
tracing::info!(target: TRACING_TARGET, "realtime WebTransport smoke started");
|
||||
let result = tokio::time::timeout(SMOKE_TIMEOUT, run_smoke()).await;
|
||||
return match result {
|
||||
std::result::Result::Ok(std::result::Result::Ok(())) => {
|
||||
tracing::info!(target: TRACING_TARGET, "realtime WebTransport smoke passed");
|
||||
println!("game-realtime-webtransport-smoke: PASS");
|
||||
std::process::ExitCode::SUCCESS
|
||||
},
|
||||
std::result::Result::Ok(std::result::Result::Err(error)) => {
|
||||
tracing::error!(target: TRACING_TARGET, detail = error.as_str(), "realtime WebTransport smoke failed");
|
||||
eprintln!("game-realtime-webtransport-smoke: FAIL: {error}");
|
||||
std::process::ExitCode::FAILURE
|
||||
},
|
||||
std::result::Result::Err(_) => {
|
||||
tracing::error!(target: TRACING_TARGET, timeout_ms = SMOKE_TIMEOUT.as_millis(), "realtime WebTransport smoke timed out");
|
||||
eprintln!("game-realtime-webtransport-smoke: FAIL: smoke timed out");
|
||||
std::process::ExitCode::FAILURE
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async fn run_smoke() -> std::result::Result<(), String> {
|
||||
let identity = match game_realtime_webtransport_lib::WebTransportServerIdentity::generate_loopback() {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(format!("loopback identity generation failed: {error}")),
|
||||
};
|
||||
let certificate_hash = identity.certificate_hash().clone();
|
||||
let bind_address = std::net::SocketAddr::from(([127, 0, 0, 1], 0));
|
||||
let server_config = game_realtime_webtransport_lib::WebTransportServerConfig::new(bind_address, identity);
|
||||
let mut listener = match game_realtime_webtransport_lib::WebTransportListener::bind(server_config) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(format!("listener bind failed: {error}")),
|
||||
};
|
||||
let endpoint = format!("https://{}/smoke", listener.local_addr());
|
||||
let client_config = match game_realtime_webtransport_lib::WebTransportClientConfig::new(endpoint.as_str(), certificate_hash) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(format!("client configuration failed: {error}")),
|
||||
};
|
||||
tracing::info!(target: TRACING_TARGET, endpoint = endpoint.as_str(), "loopback endpoint bound with exact certificate pin");
|
||||
let (server_result, client_result) = tokio::join!(listener.accept(), game_realtime_webtransport_lib::connect(&client_config));
|
||||
let server_session = match server_result {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(format!("server accept failed: {error}")),
|
||||
};
|
||||
let client_session = match client_result {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(format!("client connect failed: {error}")),
|
||||
};
|
||||
let client_connection = match client_session.open_primary_connection().await {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(format!("client primary stream open failed: {error}")),
|
||||
};
|
||||
let server_connection = match server_session.accept_primary_connection().await {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(format!("server primary stream accept failed: {error}")),
|
||||
};
|
||||
let (mut server_sender, mut server_receiver) = server_connection.split();
|
||||
let (mut client_sender, mut client_receiver) = client_connection.split();
|
||||
if let std::result::Result::Err(error) = client_sender.send(game_realtime_transport_lib::TransportMessage::new(CLIENT_PAYLOAD.to_vec())).await {
|
||||
return std::result::Result::Err(format!("client send failed: {error}"));
|
||||
}
|
||||
let server_received = match server_receiver.receive().await {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(format!("server receive failed: {error}")),
|
||||
};
|
||||
if !receive_matches(server_received, CLIENT_PAYLOAD) {
|
||||
return std::result::Result::Err(String::from("server did not receive the expected client payload"));
|
||||
}
|
||||
if let std::result::Result::Err(error) = server_sender.send(game_realtime_transport_lib::TransportMessage::new(SERVER_PAYLOAD.to_vec())).await {
|
||||
return std::result::Result::Err(format!("server send failed: {error}"));
|
||||
}
|
||||
let client_received = match client_receiver.receive().await {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(format!("client receive failed: {error}")),
|
||||
};
|
||||
if !receive_matches(client_received, SERVER_PAYLOAD) {
|
||||
return std::result::Result::Err(String::from("client did not receive the expected server payload"));
|
||||
}
|
||||
if let std::result::Result::Err(error) = client_sender.close().await {
|
||||
return std::result::Result::Err(format!("client close failed: {error}"));
|
||||
}
|
||||
let server_close = match server_receiver.receive().await {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(format!("server close observation failed: {error}")),
|
||||
};
|
||||
if server_close != game_realtime_transport_lib::TransportReceive::Closed {
|
||||
return std::result::Result::Err(String::from("server did not observe the client FIN"));
|
||||
}
|
||||
if let std::result::Result::Err(error) = server_sender.close().await {
|
||||
return std::result::Result::Err(format!("server close failed: {error}"));
|
||||
}
|
||||
let client_close = match client_receiver.receive().await {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(format!("client close observation failed: {error}")),
|
||||
};
|
||||
if client_close != game_realtime_transport_lib::TransportReceive::Closed {
|
||||
return std::result::Result::Err(String::from("client did not observe the server FIN"));
|
||||
}
|
||||
return std::result::Result::Ok(());
|
||||
}
|
||||
|
||||
fn receive_matches(receive: game_realtime_transport_lib::TransportReceive, expected: &[u8]) -> bool {
|
||||
return match receive {
|
||||
game_realtime_transport_lib::TransportReceive::Message(message) => message.as_bytes() == expected,
|
||||
game_realtime_transport_lib::TransportReceive::Closed => false,
|
||||
};
|
||||
}
|
||||
126
deltas/0.3.5/alpha.5.md
Normal file
126
deltas/0.3.5/alpha.5.md
Normal file
@@ -0,0 +1,126 @@
|
||||
<!-- file: deltas/0.3.5/alpha.5.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta 0.3.5-alpha.5
|
||||
|
||||
## Base requise
|
||||
|
||||
`0.3.5-alpha.4.fix.1`, validée par l'utilisateur le 2026-09-21 avec fmt, audits, `cargo check`, Clippy strict, les sept tests du contrat realtime commun et les vingt tests WebTransport.
|
||||
|
||||
La preuve est enregistrée dans `history/0.3.5/alpha.4.fix.1.md`.
|
||||
|
||||
## Objectif
|
||||
|
||||
Fermer la preuve runtime native WebTransport hors harness de test sans ajouter de fonctionnalité à la bibliothèque.
|
||||
|
||||
Cette tranche doit démontrer avec les APIs publiques réellement distribuées que le chemin localhost complet fonctionne depuis un exécutable normal : TLS local, pinning, session WebTransport, stream fiable principal, contrat realtime commun, round-trip bidirectionnel et fermeture propre.
|
||||
|
||||
## Version
|
||||
|
||||
La version workspace passe à :
|
||||
|
||||
```text
|
||||
0.3.5-alpha.5
|
||||
```
|
||||
|
||||
## Launcher technique
|
||||
|
||||
Nouvelle crate :
|
||||
|
||||
```text
|
||||
crates/apps/game-realtime-webtransport-smoke
|
||||
```
|
||||
|
||||
Elle dépend uniquement de :
|
||||
|
||||
```text
|
||||
game-logging-lib
|
||||
game-realtime-transport-lib
|
||||
game-realtime-webtransport-lib
|
||||
tokio
|
||||
tracing
|
||||
```
|
||||
|
||||
Aucune nouvelle dépendance externe n'est introduite.
|
||||
|
||||
Le launcher :
|
||||
|
||||
1. initialise le tracing commun ;
|
||||
2. génère une identité TLS loopback ECDSA P-256 courte durée en mémoire ;
|
||||
3. dérive le hash SHA-256 exact exposé par cette identité ;
|
||||
4. bind le listener WebTransport sur `127.0.0.1:0` ;
|
||||
5. construit le client `https://<adresse>/smoke` avec ce hash pin ;
|
||||
6. établit simultanément les sessions client et serveur ;
|
||||
7. ouvre/accepte le stream bidirectionnel primaire ;
|
||||
8. échange un payload client puis un payload serveur via le contrat `RealtimeConnection` ;
|
||||
9. ferme proprement le sender client et vérifie `Closed` côté serveur ;
|
||||
10. ferme proprement le sender serveur et vérifie `Closed` côté client ;
|
||||
11. imprime exactement :
|
||||
|
||||
```text
|
||||
game-realtime-webtransport-smoke: PASS
|
||||
```
|
||||
|
||||
Une deadline globale de 10 secondes empêche le smoke de rester bloqué indéfiniment.
|
||||
|
||||
## Frontière de dépendances
|
||||
|
||||
Le backend WebTransport est désormais consommé par un launcher technique public, ce qui est intentionnel. Il doit toujours rester absent des crates engine et gameplay.
|
||||
|
||||
Le graphe inverse attendu peut donc contenir :
|
||||
|
||||
```text
|
||||
game-realtime-webtransport-lib
|
||||
game-realtime-webtransport-smoke
|
||||
```
|
||||
|
||||
mais aucune crate `engine-v1-*`, `game-snake-poc` ou `game-reflex-poc`.
|
||||
|
||||
## Fichiers modifiés
|
||||
|
||||
```text
|
||||
Cargo.toml
|
||||
README.md
|
||||
docs/plans/005-V0_3_5_WEBTRANSPORT_QUIC_POC_PLAN.md
|
||||
```
|
||||
|
||||
Nouveaux fichiers :
|
||||
|
||||
```text
|
||||
crates/apps/game-realtime-webtransport-smoke/Cargo.toml
|
||||
crates/apps/game-realtime-webtransport-smoke/src/main.rs
|
||||
deltas/0.3.5/alpha.5.md
|
||||
history/0.3.5/alpha.4.fix.1.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-webtransport-lib --all-targets --all-features
|
||||
|
||||
cargo run -p game-realtime-webtransport-smoke
|
||||
|
||||
cargo tree -p game-realtime-webtransport-smoke --edges normal
|
||||
cargo tree -i game-realtime-webtransport-lib --workspace --edges normal
|
||||
```
|
||||
|
||||
Le smoke doit se terminer avec :
|
||||
|
||||
```text
|
||||
game-realtime-webtransport-smoke: PASS
|
||||
```
|
||||
|
||||
## Après validation
|
||||
|
||||
Créer `history/0.3.5/alpha.5.md` à partir des sorties réellement fournies, puis ouvrir `0.3.5-alpha.6` pour le chemin WASM compilable. Le smoke navigateur/TLS réel reste réservé à `alpha.7`.
|
||||
@@ -1,11 +1,11 @@
|
||||
<!-- file: docs/plans/005-V0_3_5_WEBTRANSPORT_QUIC_POC_PLAN.md -->
|
||||
<!-- version: 6 -->
|
||||
<!-- version: 7 -->
|
||||
|
||||
# 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`, puis réconcilié pour l'implémentation native de `0.3.5-alpha.2`, son correctif de validation `0.3.5-alpha.2.fix.1`, le chemin fiable validé de `0.3.5-alpha.3`, la robustesse candidate de `0.3.5-alpha.4` et son correctif de gate `0.3.5-alpha.4.fix.1`.
|
||||
Plan actif créé pendant `0.3.5-alpha.1` à partir de l'archive taggée `v0.3.4`, puis réconcilié pour l'implémentation native de `0.3.5-alpha.2`, son correctif de validation `0.3.5-alpha.2.fix.1`, le chemin fiable validé de `0.3.5-alpha.3`, la robustesse validée par `0.3.5-alpha.4.fix.1` et le smoke natif candidat de `0.3.5-alpha.5`.
|
||||
|
||||
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.
|
||||
|
||||
@@ -457,17 +457,23 @@ Tranche candidate matérialisée avec :
|
||||
|
||||
Un timeout d'idle de `receive()` n'est volontairement pas imposé au contrat : l'appelant peut borner/annuler l'attente sans corrompre l'état du frame parser. Un test artificiel de saturation/backpressure n'est pas ajouté tant qu'il n'est pas déterministe.
|
||||
|
||||
La gate utilisateur de `alpha.4` a confirmé fmt, audits, `cargo check`, tous les tests du contrat commun et les vingt tests WebTransport, mais Clippy strict a détecté un unique `clippy::implicit-return` dans la future retournée par `RealtimeReceiver::receive()`. `alpha.4.fix.1` explicite ce `return` sans changement sémantique, d'API, de framing, de lifecycle ou de dépendance. La gate complète du fix reste requise avant d'ouvrir `alpha.5`.
|
||||
La gate utilisateur de `alpha.4` a confirmé fmt, audits, `cargo check`, tous les tests du contrat commun et les vingt tests WebTransport, mais Clippy strict a détecté un unique `clippy::implicit-return` dans la future retournée par `RealtimeReceiver::receive()`. `alpha.4.fix.1` a explicité ce `return` sans changement sémantique, d'API, de framing, de lifecycle ou de dépendance. Sa gate complète est ensuite passée : audits, check workspace, Clippy strict, sept tests du contrat commun et vingt tests WebTransport. La preuve est conservée dans `history/0.3.5/alpha.4.fix.1.md`.
|
||||
|
||||
### `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.
|
||||
Tranche candidate matérialisée avec :
|
||||
|
||||
Cette tranche reste distincte pour ne pas mélanger robustesse de bibliothèque et preuve runtime publique.
|
||||
- nouvelle app technique `game-realtime-webtransport-smoke` ;
|
||||
- bind UDP loopback sur port éphémère ;
|
||||
- identité TLS ECDSA P-256 locale générée en mémoire et pin SHA-256 dérivé de cette identité ;
|
||||
- établissement WebTransport client/server réel sur `https://127.0.0.1:<port>/smoke` ;
|
||||
- ouverture/accept du stream fiable principal via l'API publique du backend ;
|
||||
- round-trip binaire bidirectionnel via `RealtimeConnection` ;
|
||||
- FIN propre client puis serveur, chacun observé comme `TransportReceive::Closed` par le pair ;
|
||||
- timeout global du launcher et verdict terminal déterministe `game-realtime-webtransport-smoke: PASS` ;
|
||||
- aucune nouvelle dépendance externe et aucun couplage engine/gameplay.
|
||||
|
||||
Cette tranche reste distincte pour ne pas mélanger robustesse de bibliothèque et preuve runtime publique. La gate doit exécuter le smoke hors harness puis contrôler les graphes direct et inverse : l'inverse de `game-realtime-webtransport-lib` peut désormais contenir le launcher technique, mais aucune crate engine ou gameplay.
|
||||
|
||||
### `0.3.5-alpha.6` — chemin WASM compilable
|
||||
|
||||
|
||||
75
history/0.3.5/alpha.4.fix.1.md
Normal file
75
history/0.3.5/alpha.4.fix.1.md
Normal file
@@ -0,0 +1,75 @@
|
||||
<!-- file: history/0.3.5/alpha.4.fix.1.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Historique 0.3.5-alpha.4.fix.1
|
||||
|
||||
## Statut
|
||||
|
||||
`0.3.5-alpha.4.fix.1` a été validée par l'utilisateur le 2026-09-21. La tranche robustesse/lifecycle WebTransport est donc fermée : configuration, deadlines, framing négatif, cancellation, reset/abort/drop et mapping d'erreurs passent avec Clippy strict.
|
||||
|
||||
La suite peut ouvrir `0.3.5-alpha.5` pour le smoke natif hors harness sans réouvrir le scope de la bibliothèque.
|
||||
|
||||
## Gates statiques et compilation
|
||||
|
||||
Les commandes utilisateur ont terminé proprement :
|
||||
|
||||
```text
|
||||
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
|
||||
```
|
||||
|
||||
La sortie confirme :
|
||||
|
||||
```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), 292 file(s))
|
||||
Distribution layout audit: clean (50 required path(s), 8 forbidden path(s) absent)
|
||||
cargo check --workspace: clean
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings: clean
|
||||
```
|
||||
|
||||
Le workspace compilé porte `0.3.5-alpha.4.fix.1`, y compris `game-realtime-webtransport-lib` et l'ensemble des targets workspace affichées par la gate.
|
||||
|
||||
## Tests du contrat realtime commun
|
||||
|
||||
La commande :
|
||||
|
||||
```bash
|
||||
cargo test -p game-realtime-transport-lib --all-targets --all-features
|
||||
```
|
||||
|
||||
est entièrement propre :
|
||||
|
||||
```text
|
||||
7 passed; 0 failed
|
||||
```
|
||||
|
||||
## Tests WebTransport
|
||||
|
||||
La commande :
|
||||
|
||||
```bash
|
||||
cargo test -p game-realtime-webtransport-lib --all-targets --all-features
|
||||
```
|
||||
|
||||
est entièrement propre :
|
||||
|
||||
```text
|
||||
unit tests: 11 passed; 0 failed
|
||||
establishment integration tests: 2 passed; 0 failed
|
||||
realtime_connection integration tests: 1 passed; 0 failed
|
||||
robustness integration tests: 6 passed; 0 failed
|
||||
```
|
||||
|
||||
Les vingt tests WebTransport couvrent donc l'établissement et le pinning, le framing fiable, le round-trip primaire, les limites configurables, les frames tronquées, la cancellation de receive, les reset/abort/drop et la deadline d'accept du stream primaire.
|
||||
|
||||
## Conséquence
|
||||
|
||||
`alpha.5` peut se limiter à une preuve runtime publique hors harness : launcher technique dédié, bind éphémère, identité TLS locale en mémoire, pin SHA-256 exact, round-trip binaire bidirectionnel, FIN propre dans les deux directions et verdict `PASS` déterministe.
|
||||
Reference in New Issue
Block a user