v0.2.7-pre.004

This commit is contained in:
2026-08-22 18:21:20 +02:00
parent b0461f15ec
commit 778ea58ee1
15 changed files with 1155 additions and 74 deletions

View File

@@ -56,18 +56,18 @@ La documentation Solana reste l'autorité pour la **surface publique annoncée**
Le plan et la compliance suivent désormais explicitement les SIMDs pertinents :
| SIMD | Statut | Décision KSP principale |
|------------------------------------------------|-----------|----------------------------------------------------------------------------------------------------------------------|
| `0118` Partitioned Epoch Rewards Distribution | Activated | réutiliser les DTOs bloc/rewards lossless déjà acquis par HTTP |
| `0291` Commission Rate in Basis Points | Review | ne pas dériver localement une représentation de commission depuis une autre |
| `0296` Larger Transaction Size | Review | proposition jusqu'à 4096 octets ; aucune limite WS dérivée en dur de l'ancienne taille transaction de 1232 octets |
| `0298` Bank Hash in Block Footer | Idea | aucun `bankHash` spéculatif |
| `0301` parent bank hash | PR fermé | aucun `parentBankHash` spéculatif ; PR non mergée |
| `0307` Add Block Footer | Review | aucun `footer` spéculatif ; réaudit lorsque l'upstream l'expose |
| `0326` Alpenglow | Review | ne pas figer les sémantiques TowerBFT des flux unstable |
| `0337` Alpenglow Fast Leader Handover Markers | Review | surveiller l'impact futur sur shape/taille des blocs |
| `0384` Alpenglow migration | Review | ne pas supposer une séquence exhaustive de notifications commitment/optimistic confirmation |
| `0385` Transaction V1 | Review | conserver versions transaction et `maxSupportedTransactionVersion` génériques |
| SIMD | Statut | Décision KSP principale |
|-----------------------------------------------|-----------|-------------------------------------------------------------------------------------------------------------------|
| `0118` Partitioned Epoch Rewards Distribution | Activated | réutiliser les DTOs bloc/rewards lossless déjà acquis par HTTP |
| `0291` Commission Rate in Basis Points | Review | ne pas dériver localement une représentation de commission depuis une autre |
| `0296` Larger Transaction Size | Review | proposition jusqu'à 4096 octets ; aucune limite WS dérivée en dur de l'ancienne taille transaction de 1232 octets |
| `0298` Bank Hash in Block Footer | Idea | aucun `bankHash` spéculatif |
| `0301` parent bank hash | PR fermé | aucun `parentBankHash` spéculatif ; PR non mergée |
| `0307` Add Block Footer | Review | aucun `footer` spéculatif ; réaudit lorsque l'upstream l'expose |
| `0326` Alpenglow | Review | ne pas figer les sémantiques TowerBFT des flux unstable |
| `0337` Alpenglow Fast Leader Handover Markers | Review | surveiller l'impact futur sur shape/taille des blocs |
| `0384` Alpenglow migration | Review | ne pas supposer une séquence exhaustive de notifications commitment/optimistic confirmation |
| `0385` Transaction V1 | Review | conserver versions transaction et `maxSupportedTransactionVersion` génériques |
Aucun de ces SIMDs n'ajoute, dans la baseline Agave `v4.2.1`, une dixième famille WebSocket standard.

240
deltas/0.2.7/pre.004.md Normal file
View File

@@ -0,0 +1,240 @@
<!-- file: deltas/0.2.7/pre.004.md -->
<!-- version: 1 -->
# Delta `0.2.7-pre.004` — runtime WebSocket physique + actor JSON-RPC
## 1. Base requise
```text
0.2.7-pre.003 appliquée
workspace.package.version = 0.2.7-pre.3
```
Le checkpoint opérateur reçu avant cette tranche est vert : `cargo fmt --all`, audit Python, `cargo check --workspace`, `cargo clippy --workspace --all-targets`, tests Transport, tests Config et `cargo test --workspace`.
## 2. Signal technique
Cette prerelease non-fix modifie dépendances, runtime Rust et tests. Conformément au workflow KSP :
```text
livraison = 0.2.7-pre.004
workspace.package.version = 0.2.7-pre.4
commit = v0.2.7-pre.004
```
Aucun tag prerelease.
## 3. Dépendances WebSocket matérialisées
Le réaudit du 22 août 2026 confirme les versions retenues depuis `pre.001` :
```text
tokio-tungstenite 0.30.0
futures-util 0.3.34
```
Le root déclare sans features consumer :
```toml
tokio-tungstenite = { version = "^0.30", default-features = false }
futures-util = { version = "^0.3", default-features = false }
```
Transport active seulement :
```text
tokio-tungstenite : connect + rustls-tls-webpki-roots
futures-util : sink + std
tokio : macros + rt + sync + time
```
Le fixture serveur local ajoute `tokio/net` côté dev.
Aucune dépendance Config, Store, Program, Wallet ou `tracing` direct n'est introduite.
## 4. `WsSession` physique
Nouvelle surface publique :
```text
WsSession::connect(WsEndpointSettings)
WsSession::id()
WsSession::state()
WsSession::snapshot()
```
Un appel de `connect` crée exactement une connexion physique. Deux appels avec le même endpoint créent deux sockets indépendants ; aucun singleton, pool ou scheduler automatique n'est ajouté.
Le caller ne reçoit jamais le socket brut.
## 5. Actor propriétaire du socket
Une tâche actor unique possède :
```text
WebSocketStream
compteur JSON-RPC request id
map pending requests
bounded command receiver
publication WsSessionSnapshot
```
Le handle communique avec l'actor par `tokio::sync::mpsc` borné selon `command_queue_capacity`.
Les snapshots sont publiés via `tokio::sync::watch` et conservent seulement les metadata sûres prévues en `pre.002`.
## 6. Handshake et `WebSocketConfig`
`WsSession::connect` attend le handshake sous `command_timeout` et configure explicitement :
```text
write_buffer_size = 0
max_write_buffer_size = WsSessionSettings.max_write_buffer_size_bytes
max_message_size = WsSessionSettings.max_message_size_bytes
max_frame_size = WsSessionSettings.max_frame_size_bytes
```
Le `write_buffer_size = 0` évite de rendre la validité de la configuration KSP dépendante du buffer par défaut interne de Tungstenite et garantit que le plafond configuré reste strictement supérieur au target buffer.
Les tests oversized et les recalibrages éventuels restent le gate `pre.005`.
## 7. Pending JSON-RPC
La primitive interne actor :
```text
execute_json_rpc(method, params)
```
reste **`pub(crate)`**. Elle n'est volontairement pas exposée comme API raw provider-extension publique.
Comportement :
- ID numérique KSP monotone par session ;
- sérialisation via `JsonRpcRequest` existant ;
- map `BTreeMap` bornée par `max_pending_requests` ;
- deadline par request issue de `command_timeout` ;
- dispatch des réponses par `id`, y compris si elles arrivent hors ordre ;
- erreurs JSON-RPC applicatives renvoyées au caller concerné sans teardown de la connexion ;
- ID réponse inconnu/stale ignoré avec diagnostic sûr ;
- JSON structurellement invalide classé erreur protocole session.
Cette primitive sera consommée par le moteur de subscriptions à partir de `pre.006`.
## 8. Lifecycle limité à la tranche
`pre.004` matérialise :
```text
Connecting -> Active
connection/read/write failure -> Failed
last handle dropped -> cleanup best-effort -> Closed
```
Le reconnect/resubscribe reste `pre.007`.
Le shutdown async public, les budgets de Close et les fixtures peer hostile restent `pre.005`.
Ping reçu est répondu par Pong afin de conserver l'interopérabilité du socket. Aucun heartbeat applicatif périodique n'est ajouté.
## 9. Erreurs
Nouveaux codes publics :
```text
ws_backpressure_overflow
ws_connection_failed
ws_protocol_error
ws_session_closed
```
Les erreurs de connexion WebSocket ne conservent volontairement pas la source Tungstenite brute : celle-ci pourrait contenir une request/URI ou d'autres détails provider. Les erreurs KSP exposent uniquement `session_id`, endpoint logique, provider et cluster.
## 10. Logging / tracing
Toutes les émissions passent exclusivement par `ksp-logging-lib` et réutilisent :
```text
crates/ksp-onchain-transport-lib/src/constants.rs
TRACING_TARGET = "ksp-onchain-transport-lib"
```
Répartition principale :
```text
trace -> ouverture socket, send/dispatch JSON-RPC, Ping/Pong, notification prématurée ignorée
debug -> actor start, handshake actif, réponse stale, timeout pending, remote close
warn -> handshake/read/write failure, malformed wire, capacité pending épuisée
```
Ne sont jamais loggés : URL complète, credentials, query token, payload JSON-RPC complet ou notification brute.
## 11. Serveur local déterministe
Nouveaux tests runtime sans Internet :
```text
handshake local + round-trip JSON-RPC
deux sessions physiques distinctes sur la même URL
deux requests concurrentes + réponses inversées
application error sans teardown de session
connection error sans fuite URL/credential
```
Le serveur utilise `tokio::net::TcpListener` + `tokio_tungstenite::accept_async`.
## 12. Canaris workspace/public API
Le canari workspace dependencies est synchronisé avec les nouvelles dépendances/features et continue de vérifier le firewall Transport.
Le canari public API vérifie la disponibilité de `WsSession` et les quatre nouveaux codes d'erreur.
## 13. Documentation synchronisée
Mis à jour :
```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 conformément à la politique de série prerelease.
## 14. Validation de préparation
Exécuté dans le sandbox :
```text
python3 scripts/audit_rust_workspace_rules.py
General Rust rule audit: clean
Rust export completeness audit: 0 candidate(s)
KSP workspace Rust rule audit: clean
inspection absence tracing direct OK
inspection TRACING_TARGET OK
inspection dépendances workspace/member OK
inspection Markdown tables OK
```
Cargo n'est pas disponible dans le sandbox de génération ; aucun résultat Cargo local n'est revendiqué.
## 15. 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.004
```
La tranche suivante est `0.2.7-pre.005` : adversarial limits frame/message/request, control frames, cancellation, close/shutdown explicite et peer hostile.