Files
games/deltas/0.3.5/alpha.3.md
2026-09-21 22:55:21 +02:00

185 lines
7.3 KiB
Markdown

<!-- file: deltas/0.3.5/alpha.3.md -->
<!-- version: 1 -->
# Delta 0.3.5-alpha.3
## Base requise
`0.3.5-alpha.2.fix.1`, validée par l'utilisateur le 2026-09-21 avec fmt, audits, check workspace, Clippy strict et les six tests de `game-realtime-webtransport-lib` entièrement verts.
La validation réellement fournie est conservée dans `history/0.3.5/alpha.2.fix.1.md`.
## Objectif
Fermer la première adaptation fiable WebTransport vers `game-realtime-transport-lib` sans introduire encore la robustesse/lifecycle avancés, le navigateur/WASM, les datagrams ou le smoke public.
La version passe à :
```text
0.3.5-alpha.3
```
## Stream primaire
Une `WebTransportSession` peut désormais être consommée de deux façons :
```text
client -> open_primary_connection()
server -> accept_primary_connection()
```
Chaque chemin sélectionne exactement un stream bidirectionnel fiable et retourne `WebTransportConnection`.
Le backend `web-transport-quinn` écrit lui-même l'en-tête WebTransport nécessaire pendant `open_bi()`. Le serveur peut donc accepter le stream avant toute frame applicative. Aucun préambule games.sasedev supplémentaire n'est ajouté : après l'en-tête protocolaire géré par la dépendance, le premier octet applicatif appartient directement au framing prévu.
## Framing fiable privé
Le framing du stream primaire est :
```text
u32 big-endian payload length
payload bytes
```
Il reste privé à `game-realtime-webtransport-lib` et n'est pas un wire codec gameplay.
La borne POC actuelle est de 1 MiB par message. Elle est vérifiée :
- avant écriture côté sender ;
- immédiatement après décodage des quatre octets de longueur et avant toute allocation côté receiver.
Une longueur hors limite produit `TransportErrorKind::MessageTooLarge`.
La limite n'est pas encore exposée comme configuration produit. `alpha.4` possède cette décision avec les autres limites et deadlines.
## Contrat commun
`WebTransportConnection` implémente `RealtimeConnection` et produit :
```text
WebTransportSender
WebTransportReceiver
```
Les deux moitiés conservent chacune une référence à la session WebTransport. Le `split()` ne ferme donc pas accidentellement la session au moment où l'objet connexion est consommé.
`WebTransportSender::send(...)` écrit le header puis le payload sur le stream fiable et respecte la backpressure naturelle de QUIC pendant les écritures asynchrones.
`WebTransportReceiver::receive(...)` reconstruit exactement un `TransportMessage`, y compris les payloads vides et binaires non UTF-8.
`RealtimeSender::close()` termine proprement la direction locale du stream primaire. Lorsque le pair a consommé les messages précédents puis atteint le FIN, `RealtimeReceiver::receive()` retourne `TransportReceive::Closed`.
La fermeture complète de session, reset, abort, cancellation, deadlines et mapping fin des erreurs restent hors de cette tranche.
## API et documentation
`src/lib.rs` réexporte les nouveaux types publics conformément aux règles du workspace.
Le README local est réconcilié avec le stream primaire et ses frontières. Un `USAGE.md` durable est ajouté car l'ordre session -> stream primaire -> `RealtimeConnection` et la contrainte d'accept serveur nécessitent désormais un guide d'utilisation distinct du delta.
Le plan `005` enregistre les décisions réellement matérialisées sans modifier le forecast de `alpha.4+`.
`ROADMAP.md` et `CHANGELOG.md` restent inchangés : cette alpha ne modifie ni la mission macro de `0.3.5` ni une livraison stable.
## Tests
Le test unitaire du backend ajoute la preuve que :
- la longueur est encodée en `u32` big-endian ;
- la borne de frame refuse une taille supérieure à 1 MiB avec `MessageTooLarge`.
Le nouveau test d'intégration `tests/realtime_connection.rs` prouve en loopback :
- ouverture du stream primaire côté client ;
- ouverture cliente puis accept du stream primaire côté serveur avant la première frame applicative ;
- adaptation `RealtimeConnection` ;
- payload vide ;
- payload binaire non UTF-8 ;
- ordre de plusieurs messages ;
- echo bidirectionnel ;
- FIN client observé comme `TransportReceive::Closed` côté serveur ;
- FIN serveur observé comme `TransportReceive::Closed` côté client.
Les sessions restent vivantes pendant toute la preuve afin que le test ne confonde pas FIN du stream logique et drop de session.
## Fichiers modifiés
```text
Cargo.toml
README.md
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
docs/plans/005-V0_3_5_WEBTRANSPORT_QUIC_POC_PLAN.md
```
Nouveaux fichiers :
```text
crates/common/game-realtime-webtransport-lib/USAGE.md
crates/common/game-realtime-webtransport-lib/tests/realtime_connection.rs
history/0.3.5/alpha.2.fix.1.md
deltas/0.3.5/alpha.3.md
```
Aucune dépendance Cargo n'est ajoutée ou modifiée dans cette tranche.
## Validation exécutée dans l'environnement de génération
L'environnement de génération ne possède pas de toolchain Rust. Aucun `cargo fmt`, `cargo check`, Clippy ou test n'est donc attribué à cette livraison.
Les audits statiques disponibles ont été exécutés sur le candidat final :
```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), 273 file(s))
Distribution layout audit: clean (50 required path(s), 8 forbidden path(s) absent)
```
Le compteur de fichiers Markdown correspond à la reconstruction de travail issue de l'archive taggée et des deltas fournis. Il n'est pas utilisé comme invariant contre le checkout utilisateur, qui contient davantage de fichiers suivis localement.
## Validation utilisateur demandée
Cette tranche modifie le backend Rust et ajoute un test d'intégration. La gate ciblée est :
```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 tree -i game-realtime-webtransport-lib --workspace --edges normal
```
Le contrat commun est retesté parce que `alpha.3` en devient un nouvel implémenteur, même si sa crate n'est pas modifiée.
Le `cargo tree` inverse vérifie qu'aucune crate moteur ou gameplay n'a acquis de dépendance vers le backend concret. Les arbres complets `web-transport-quinn` de `alpha.2` ne sont pas répétés puisque le graphe de dépendances n'a pas changé.
Aucun smoke executable n'est encore attendu : le smoke natif public reste `alpha.5`, après la tranche de robustesse `alpha.4`.
## Suite après validation
Si la gate est propre, ouvrir `0.3.5-alpha.4` pour :
- limites configurables si justifiées ;
- deadlines ;
- backpressure/erreurs observables ;
- close/reset/abort ;
- cancellation/drop ;
- cas négatifs de framing ;
- mapping d'erreurs détaillé ;
- tests de robustesse ciblés.
Un défaut fermé de cette tranche produit d'abord `0.3.5-alpha.3.fix.N` au lieu d'ouvrir `alpha.4`.