# 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::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 ``` 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 ``` 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`.