Files
2026-08-23 00:12:39 +02:00

190 lines
6.7 KiB
Markdown

<!-- file: deltas/0.2.7/pre.010.md -->
<!-- version: 1 -->
# Delta `0.2.7-pre.010` — wrappers WebSocket stables lot B
## Base
Base requise :
```text
0.2.7-pre.009-fix.002
workspace.package.version = 0.2.7-pre.9.fix.2
```
Le checkpoint opérateur de cette base est entièrement vert : `cargo fmt --all`, audit Python KSP, `cargo check --workspace`, `cargo clippy --workspace --all-targets`, 295 tests unitaires Transport, 33 tests d'API publique, 22 tests de release completeness puis `cargo test --workspace`.
Le canari ajouté par `pre.009-fix.002` pour une première connexion HTTP locale abandonnée passe dans le run Transport isolé comme dans le run workspace.
## Signal de version
```text
livraison = 0.2.7-pre.010
workspace.package.version = 0.2.7-pre.10
commit = v0.2.7-pre.010
tag = aucun
```
## Objectif
Compléter les six familles WebSocket standard non instables en ajoutant le lot B :
```text
signatureSubscribe / signatureUnsubscribe
slotSubscribe / slotUnsubscribe
rootSubscribe / rootUnsubscribe
```
Les trois familles unstable `block`, `slotsUpdates` et `vote` restent explicitement différées à `pre.011`.
## `signatureSubscribe`
Nouvelle configuration publique :
```text
SolanaSignatureSubscribeConfig
commitment
enable_received_notification
```
Les deux options sont indépendamment optionnelles. `enableReceivedNotification = false` explicite est préservé comme distinct de l'option omise ; un config explicitement vide est canonisé en absence du second paramètre.
Le résultat typed conserve les deux variantes wire actuelles :
```text
SolanaRpcResponse<SolanaSignatureNotification>
SolanaSignatureNotification::ReceivedSignature
SolanaSignatureNotification::Processed { err }
```
`ReceivedSignature` correspond au littéral wire `receivedSignature` et reste non terminal. `Processed { err }` est terminal ; `err = None` représente un succès et `err = Some(Value)` conserve sans interprétation locale le `TransactionError` wire.
Un littéral string inconnu ou un objet terminal sans champ `err` est rejeté comme `invalid_response` pour la subscription concernée, sans faire tomber une session physique autrement saine.
## Terminaison one-shot signature
Le serveur Solana annule automatiquement `signatureSubscribe` après la notification terminale. Le runtime KSP doit donc fermer le handle au même instant logique, sans envoyer d'unsubscribe redondant et surtout sans restaurer cette subscription après une reconnexion ultérieure.
Le moteur typed acquiert pour cela une classification interne :
```text
Delivered
DeliveredTerminal
ReceiverClosed
QueueFull
DecodeFailed
```
La notification terminale est d'abord insérée dans la queue typed, puis l'actor retire la subscription du registry et du mapping remote/local et publie `WsSubscriptionState::Closed` avec `terminal_error_code = None`.
Cette séquence garantit :
```text
consumer reçoit la valeur terminale
-> handle Closed
-> canal se ferme après la valeur déjà queueée
-> aucune signatureUnsubscribe automatique
-> aucune présence dans une sélection de resubscribe future
```
Une cancellation explicite avant la notification terminale conserve le chemin générique `WsSubscription::unsubscribe()` et émet `signatureUnsubscribe` avec le remote ID détenu uniquement par l'actor. Après la terminaison observée, `unsubscribe()` retourne `false` localement.
## `slotSubscribe`
Nouveau DTO public :
```text
SolanaSlotNotification
slot
parent
root
```
`WsSession::slot_subscribe()` n'accepte aucun paramètre et retourne :
```text
WsSubscription<SolanaSlotNotification>
```
La subscription est continue et utilise normalement reconnect, resubscribe, backpressure et cancellation.
## `rootSubscribe`
`WsSession::root_subscribe()` n'accepte aucun paramètre et retourne directement :
```text
WsSubscription<u64>
```
Le `u64` conserve le dernier root slot rapporté par `rootNotification`. La subscription est continue et son unsubscribe passe par le handle générique.
## Tests déterministes ajoutés
Cinq tests unitaires supplémentaires couvrent :
```text
signature config commitment + enableReceivedNotification omitted/false/true
signature decoder receivedSignature + succès terminal + erreur transactionnelle terminale
signature variants invalides -> invalid_response typed
signatureUnsubscribe exact avant terminaison
signature terminale -> valeur livrée puis Closed sans terminal_error_code
signature terminale -> aucun signatureUnsubscribe redondant
perte physique après signature terminale -> session reconnectée, aucune resubscription signature
slotNotification -> slot/parent/root exacts
slotSubscribe/rootSubscribe -> params vides et notifications typed exactes
slotUnsubscribe/rootUnsubscribe -> remote IDs internes via handles
```
Un canari d'API publique supplémentaire vérifie les trois nouvelles méthodes et les DTOs depuis la racine de crate.
Comptages attendus après compilation :
```text
Transport unit tests = 300
Transport public API tests = 34
release completeness = 22
```
## Sécurité / observabilité
Aucun remote subscription ID n'est ajouté à l'API publique. La signature fournie au wrapper n'est pas ajoutée aux logs de lifecycle. Le log de terminaison one-shot contient uniquement `session_id`, `subscription_id` local et `subscription_kind`.
La valeur `err` terminale reste accessible au consumer dans le DTO typed mais n'est jamais projetée dans `terminal_error_code`, car une transaction échouée reste une notification métier valide et non une erreur Transport.
## Fichiers ajoutés ou modifiés
```text
Cargo.toml
crates/ksp-onchain-transport-lib/README.md
crates/ksp-onchain-transport-lib/USAGE.md
crates/ksp-onchain-transport-lib/src/lib.rs
crates/ksp-onchain-transport-lib/src/ws_cluster.rs
crates/ksp-onchain-transport-lib/src/ws_session.rs
crates/ksp-onchain-transport-lib/src/ws_subscription.rs
crates/ksp-onchain-transport-lib/src/ws_transactions.rs
crates/ksp-onchain-transport-lib/tests/public_api.rs
crates/ksp-onchain-transport-lib/unit_tests/ws_cluster.rs
crates/ksp-onchain-transport-lib/unit_tests/ws_transactions.rs
docs/plans/014-V0_2_7_ONCHAIN_WEBSOCKET_PLAN.md
docs/validation/010-V0_2_7_ONCHAIN_WEBSOCKET.md
deltas/0.2.7/pre.010.md
```
`ROADMAP.md` et `CHANGELOG.md` restent inchangés pendant cette tranche.
## Validation opérateur requise
```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
```
## Tranche suivante
Si ce checkpoint est vert, `0.2.7-pre.011` ouvre les trois familles unstable : `blockSubscribe`, `slotsUpdatesSubscribe` et `voteSubscribe`, avec warnings centralisés, variantes wire évolutives et compliance `KSP-TRANSPORT-007`.