173 lines
6.0 KiB
Markdown
173 lines
6.0 KiB
Markdown
<!-- file: deltas/0.2.7/pre.005.md -->
|
|
<!-- version: 1 -->
|
|
|
|
# Delta `0.2.7-pre.005` — limits adversariales + control frames + shutdown borné
|
|
|
|
## 1. Base requise
|
|
|
|
```text
|
|
0.2.7-pre.004-fix.001 appliqué
|
|
workspace.package.version = 0.2.7-pre.4.fix.1
|
|
```
|
|
|
|
Le checkpoint opérateur reçu avant cette tranche est vert : `cargo fmt --all`, audit Python, `cargo check --workspace`, `cargo clippy --workspace --all-targets` et `cargo test --workspace`. Les 261 tests unitaires Transport de `pre.004-fix.001` passent également.
|
|
|
|
## 2. Signal technique
|
|
|
|
Cette prerelease modifie le runtime Rust, les tests et la documentation. Conformément aux règles KSP :
|
|
|
|
```text
|
|
livraison = 0.2.7-pre.005
|
|
workspace.package.version = 0.2.7-pre.5
|
|
commit = v0.2.7-pre.005
|
|
```
|
|
|
|
Aucun tag prerelease.
|
|
|
|
## 3. Shutdown explicite `WsSession::close()`
|
|
|
|
Nouvelle surface publique :
|
|
|
|
```text
|
|
WsSession::close().await
|
|
```
|
|
|
|
Le signal de shutdown est transporté par un canal `watch` distinct de la command queue. Une command queue saturée ne peut donc pas empêcher la demande de fermeture.
|
|
|
|
Lifecycle :
|
|
|
|
```text
|
|
Active -> Closing -> Closed
|
|
remote Close propre -> Closed
|
|
I/O ou violation protocolaire -> Failed
|
|
```
|
|
|
|
`close()` :
|
|
|
|
1. publie la demande de shutdown avec une deadline issue de `close_timeout` ;
|
|
2. l'actor passe `Closing` ;
|
|
3. toutes les requests JSON-RPC pending reçoivent `ws_session_closed` ;
|
|
4. l'actor tente un Close WebSocket best-effort sous la deadline ;
|
|
5. l'actor publie `Closed` ;
|
|
6. le caller attend `Closed` sans pouvoir rester bloqué indéfiniment.
|
|
|
|
Le reconnect reste absent jusqu'à `pre.007`.
|
|
|
|
## 4. Control frames
|
|
|
|
Ping/Pong/Close sont maintenant testés explicitement.
|
|
|
|
Pour Ping, Tungstenite met automatiquement le Pong correspondant en file lors de la lecture ; KSP force le `flush` de cette réponse automatique. Aucun Pong duplicatif et aucun heartbeat applicatif périodique ne sont ajoutés.
|
|
|
|
Un Close distant propre est distingué d'une rupture I/O : il termine la session en `Closed`, alors qu'une rupture physique ou une violation de protocole termine en `Failed`.
|
|
|
|
## 5. Bornes frame/message/write
|
|
|
|
Les limites configurées depuis `pre.002` et raccordées à Tungstenite depuis `pre.004` sont désormais couvertes par des fixtures adversariales :
|
|
|
|
```text
|
|
max_message_size
|
|
max_frame_size
|
|
max_write_buffer_size
|
|
```
|
|
|
|
Un payload JSON-RPC outbound dépassant `max_message_size` ou `max_frame_size` est rejeté avant écriture avec `invalid_rpc_parameters`, sans teardown d'une session saine.
|
|
|
|
Un frame/message inbound surdimensionné est rejeté par Tungstenite avant que KSP tente le parse JSON ; l'anomalie est classée protocolaire et la session devient `Failed`.
|
|
|
|
Aucune limite legacy Solana de type 1232 bytes n'est introduite.
|
|
|
|
## 6. Pending requests et cancellation
|
|
|
|
Le runtime `pre.005` ajoute les preuves suivantes :
|
|
|
|
- `max_pending_requests` rejette uniquement la request excédentaire avec `ws_backpressure_overflow` ;
|
|
- une request pending silencieuse expire selon `command_timeout`, reçoit `timeout` et libère immédiatement sa capacité ;
|
|
- une fermeture explicite annule toutes les pending requests avec `ws_session_closed` ;
|
|
- un receiver caller abandonné est purgé du pending map au prochain cycle actor, et reste de toute façon borné par la deadline de request.
|
|
|
|
La cancellation de subscriptions et les races unsubscribe/reconnect restent dans `pre.006`/`pre.007`.
|
|
|
|
## 7. Socket I/O borné et shutdown prioritaire
|
|
|
|
Les writes JSON-RPC et le flush Pong surveillent le signal shutdown pendant leur attente. La fermeture peut donc préempter une opération socket qui serait autrement bloquante.
|
|
|
|
Un write JSON-RPC dépassant `command_timeout` provoque une erreur caller bornée et termine la session physique, car l'état de l'écriture devient impropre à une poursuite sûre.
|
|
|
|
## 8. Fixtures adversariales locales
|
|
|
|
Les tests Transport ajoutent notamment :
|
|
|
|
```text
|
|
pending capacity = 1 avec deuxième request rejetée isolément
|
|
oversized outbound request rejetée avant write
|
|
oversized inbound frame/message rejeté avant JSON
|
|
pending request timeout + purge
|
|
Ping -> Pong + session toujours Active
|
|
remote Close -> Closed
|
|
close explicite + pending cancellation + peer hostile
|
|
8 cycles connect/close bornés
|
|
```
|
|
|
|
Toutes les fixtures restent locales et déterministes ; aucun réseau Solana réel n'est requis.
|
|
|
|
## 9. Logging / sécurité
|
|
|
|
Toutes les émissions passent exclusivement par `ksp-logging-lib` et réutilisent :
|
|
|
|
```text
|
|
TRACING_TARGET = "ksp-onchain-transport-lib"
|
|
```
|
|
|
|
Les nouveaux diagnostics ne loggent que session ID, endpoint logique, méthode statique, compteurs et tailles numériques. Les URLs, credentials, query tokens et payloads JSON restent absents.
|
|
|
|
Les erreurs Tungstenite brutes ne sont pas projetées dans les erreurs KSP afin d'éviter une fuite de données provider.
|
|
|
|
## 10. Public API et documentation
|
|
|
|
Le canari public API vérifie désormais `WsSession::close` et les états `Closing`/`Closed`.
|
|
|
|
Synchronisés :
|
|
|
|
```text
|
|
crates/ksp-onchain-transport-lib/README.md
|
|
crates/ksp-onchain-transport-lib/USAGE.md
|
|
docs/plans/014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md
|
|
docs/validation/010-V0_2_7_ONCHAIN_WEBSOCKET.md
|
|
```
|
|
|
|
`ROADMAP.md` et `CHANGELOG.md` restent inchangés pendant la série prerelease.
|
|
|
|
## 11. Validation de préparation
|
|
|
|
Le sandbox de génération doit au minimum vérifier :
|
|
|
|
```text
|
|
python3 scripts/audit_rust_workspace_rules.py
|
|
absence de tracing direct
|
|
présence du TRACING_TARGET existant
|
|
absence de question-mark operator dans le runtime modifié
|
|
overlay exact du delta
|
|
```
|
|
|
|
Cargo n'est pas disponible dans le sandbox de génération ; aucun résultat Cargo local n'est revendiqué.
|
|
|
|
## 12. Gates opérateur avant commit
|
|
|
|
```bash
|
|
cargo fmt --all
|
|
python3 scripts/audit_rust_workspace_rules.py
|
|
cargo check --workspace
|
|
cargo clippy --workspace --all-targets
|
|
cargo test -p ksp-onchain-transport-lib
|
|
cargo test --workspace
|
|
```
|
|
|
|
Si le checkpoint est vert :
|
|
|
|
```text
|
|
commit = v0.2.7-pre.005
|
|
```
|
|
|
|
La tranche suivante est `0.2.7-pre.006` : registry subscriptions, IDs locaux stables, moteur generic subscribe/unsubscribe et channels typed bornés.
|