From 9c0d4fc197264f3db563ff0ed15d484bb5255233 Mon Sep 17 00:00:00 2001 From: SinuS Von SifriduS Date: Sun, 23 Aug 2026 18:16:03 +0200 Subject: [PATCH] v0.2.8-pre.009 --- Cargo.toml | 4 +- crates/ksp-onchain-transport-lib/src/lib.rs | 10 +- .../src/ws_cluster.rs | 8 +- .../src/ws_protocol_session.rs | 11 +- .../tests/public_api.rs | 9 +- .../tests/release_completeness.rs | 98 ++++++- .../unit_tests/ws_helius_standard.rs | 7 +- deltas/0.2.8/pre.009.md | 262 ++++++++++++++++++ ...0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md | 129 ++++++--- ...011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md | 100 ++++++- 10 files changed, 579 insertions(+), 59 deletions(-) create mode 100644 deltas/0.2.8/pre.009.md diff --git a/Cargo.toml b/Cargo.toml index a587897..924e688 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ # file: Cargo.toml -# version: 232 +# version: 233 [workspace] resolver = "3" members = ["crates/ksp-app-config-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-logging-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-wallet-lib"] [workspace.package] -version = "0.2.8-pre.8" +version = "0.2.8-pre.9" edition = "2024" license = "MIT" repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project" diff --git a/crates/ksp-onchain-transport-lib/src/lib.rs b/crates/ksp-onchain-transport-lib/src/lib.rs index c55ad80..7ba9db3 100644 --- a/crates/ksp-onchain-transport-lib/src/lib.rs +++ b/crates/ksp-onchain-transport-lib/src/lib.rs @@ -1,5 +1,5 @@ // file: crates/ksp-onchain-transport-lib/src/lib.rs -// version: 33 +// version: 34 #![warn(missing_docs)] #![deny(unreachable_pub)] @@ -26,9 +26,11 @@ //! `0.2.7-pre.009` opens the first stable typed WebSocket wrappers for account, program-account and transaction-log subscriptions without exposing a raw //! provider-extension subscription API. `0.2.8-pre.002` adds a Helius LaserStream WebSocket protocol discriminator and two typed protocol facades while //! keeping the `WsSession` actor/socket implementation unique and the historical generic constructor standard-only. -//! `0.2.8-pre.003` exposes the six standard families Helius supports through the provider facade, while `0.2.8-pre.005` adds the typed Helius -//! `transactionSubscribe` request contract and provider filter/options validation. `0.2.8-pre.006` integrates the live transaction handle and typed -//! `transactionNotification` union into the same actor-owned registry, remote-ID remap, unsubscribe-race handling and per-subscription backpressure path. +//! `0.2.8-pre.003` initially exposed the six standard families unambiguously supported by the audited Helius pages; `0.2.8-pre.009` reconciles the current +//! Helius documentation and adds the now-documented unstable `slotsUpdatesSubscribe` pair while keeping explicitly unsupported block/vote pairs absent. +//! `0.2.8-pre.005` adds the typed Helius `transactionSubscribe` request contract and provider filter/options validation. `0.2.8-pre.006` integrates the live +//! transaction handle and typed `transactionNotification` union into the same actor-owned registry, remote-ID remap, unsubscribe-race handling and +//! per-subscription backpressure path. mod client; mod constants; diff --git a/crates/ksp-onchain-transport-lib/src/ws_cluster.rs b/crates/ksp-onchain-transport-lib/src/ws_cluster.rs index f27376b..edca42f 100644 --- a/crates/ksp-onchain-transport-lib/src/ws_cluster.rs +++ b/crates/ksp-onchain-transport-lib/src/ws_cluster.rs @@ -1,5 +1,5 @@ // file: crates/ksp-onchain-transport-lib/src/ws_cluster.rs -// version: 4 +// version: 5 /// Slot relationship reported by the standard Solana `slotNotification` WebSocket method. #[derive(Clone, Copy, Debug, Eq, PartialEq)] @@ -433,6 +433,12 @@ impl crate::HeliusLaserStreamWsSession { pub async fn root_subscribe(&self) -> ksp_core_lib::Result> { return self.physical_session().root_subscribe().await; } + + /// Subscribes to unstable slot-lifecycle notifications through the standard `slotsUpdatesSubscribe` wire currently documented by Helius LaserStream + /// WebSocket. + pub async fn slots_updates_subscribe(&self) -> ksp_core_lib::Result> { + return self.physical_session().slots_updates_subscribe().await; + } } #[cfg(test)] diff --git a/crates/ksp-onchain-transport-lib/src/ws_protocol_session.rs b/crates/ksp-onchain-transport-lib/src/ws_protocol_session.rs index 44e30bc..5ba2982 100644 --- a/crates/ksp-onchain-transport-lib/src/ws_protocol_session.rs +++ b/crates/ksp-onchain-transport-lib/src/ws_protocol_session.rs @@ -1,5 +1,5 @@ // file: crates/ksp-onchain-transport-lib/src/ws_protocol_session.rs -// version: 5 +// version: 6 /// Typed facade for one standard Solana WebSocket physical session. /// @@ -67,7 +67,8 @@ impl std::fmt::Debug for SolanaStandardWsSession { /// Typed facade for one Helius LaserStream WebSocket physical session. /// -/// The facade exposes the six standard Solana subscription families that Helius documents as supported plus the Helius-specific typed +/// The facade exposes the seven standard Solana subscription families that the current Helius method pages support or document as available plus the +/// Helius-specific typed /// `transactionSubscribe` lifecycle. Transaction notifications, reconnect/resubscribe, unsubscribe races and bounded backpressure all delegate to the same /// shared [`crate::WsSession`] actor; the facade owns no second socket, registry or queue. No public inner handle is exposed, so callers cannot bypass the /// provider-specific surface by recovering a generic [`crate::WsSession`]. @@ -79,12 +80,6 @@ impl std::fmt::Debug for SolanaStandardWsSession { /// ``` /// /// ```compile_fail -/// async fn unsupported_slots_updates(session: &ksp_onchain_transport_lib::HeliusLaserStreamWsSession) { -/// let _ = session.slots_updates_subscribe().await; -/// } -/// ``` -/// -/// ```compile_fail /// async fn unsupported_vote(session: &ksp_onchain_transport_lib::HeliusLaserStreamWsSession) { /// let _ = session.vote_subscribe().await; /// } diff --git a/crates/ksp-onchain-transport-lib/tests/public_api.rs b/crates/ksp-onchain-transport-lib/tests/public_api.rs index c618642..30f71e8 100644 --- a/crates/ksp-onchain-transport-lib/tests/public_api.rs +++ b/crates/ksp-onchain-transport-lib/tests/public_api.rs @@ -1,5 +1,5 @@ // file: crates/ksp-onchain-transport-lib/tests/public_api.rs -// version: 37 +// version: 38 //! Integration tests for the public `ksp-onchain-transport-lib` consumer contract. @@ -753,3 +753,10 @@ fn public_v0_2_8_pre_006_helius_transaction_live_handle_and_notification_types_a let _signature = std::any::type_name::(); assert_eq!(ksp_onchain_transport_lib::WsSubscriptionKind::HeliusTransaction.as_str(), "helius_transaction"); } + +#[test] +fn public_v0_2_8_pre_009_helius_slots_updates_surface_reuses_shared_typed_contract() { + let _slots_updates = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::slots_updates_subscribe; + let _shared_slot_update = std::any::type_name::(); + assert_eq!(ksp_onchain_transport_lib::WsSubscriptionKind::SlotsUpdates.as_str(), "slots_updates"); +} diff --git a/crates/ksp-onchain-transport-lib/tests/release_completeness.rs b/crates/ksp-onchain-transport-lib/tests/release_completeness.rs index 5c67452..be09f22 100644 --- a/crates/ksp-onchain-transport-lib/tests/release_completeness.rs +++ b/crates/ksp-onchain-transport-lib/tests/release_completeness.rs @@ -1,5 +1,5 @@ // file: crates/ksp-onchain-transport-lib/tests/release_completeness.rs -// version: 30 +// version: 31 //! Release-level completeness canaries for staged HTTP and WebSocket Transport coverage. @@ -797,7 +797,7 @@ fn release_v0_2_8_pre_002_protocol_facades_preserve_the_standard_partition() { } #[test] -fn release_v0_2_8_pre_003_helius_surface_is_exactly_six_standard_families_before_transaction_extension() { +fn release_v0_2_8_pre_003_original_six_standard_families_remain_available_after_provider_evolution() { let _account = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::account_subscribe; let _program = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::program_subscribe; let _logs = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::logs_subscribe; @@ -806,7 +806,6 @@ fn release_v0_2_8_pre_003_helius_surface_is_exactly_six_standard_families_before let _root = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::root_subscribe; let source = include_str!("../src/ws_protocol_session.rs"); assert!(source.contains("unsupported_block")); - assert!(source.contains("unsupported_slots_updates")); assert!(source.contains("unsupported_vote")); assert!(!source.contains("pub async fn transaction_subscribe")); assert_eq!(ksp_onchain_transport_lib::WsProtocolKind::HeliusLaserStream.as_str(), "helius_laserstream"); @@ -847,7 +846,6 @@ fn release_v0_2_8_pre_006_helius_transaction_lifecycle_is_actor_integrated_witho assert!(!source.contains("tokio_tungstenite::connect_async")); let protocol_source = include_str!("../src/ws_protocol_session.rs"); assert!(protocol_source.contains("unsupported_block")); - assert!(protocol_source.contains("unsupported_slots_updates")); assert!(protocol_source.contains("unsupported_vote")); } @@ -871,7 +869,6 @@ fn release_v0_2_8_pre_008_adversarial_guards_preserve_provider_isolation_and_saf let protocol_source = include_str!("../src/ws_protocol_session.rs"); assert!(protocol_source.contains("unsupported_helius_transaction")); assert!(protocol_source.contains("unsupported_block")); - assert!(protocol_source.contains("unsupported_slots_updates")); assert!(protocol_source.contains("unsupported_vote")); let helius_source = include_str!("../src/ws_helius_transactions.rs"); assert!(helius_source.contains("impl std::fmt::Debug for HeliusFullTransactionNotification")); @@ -886,3 +883,94 @@ fn release_v0_2_8_pre_008_adversarial_guards_preserve_provider_isolation_and_saf assert!(actor_source.contains("ERROR_CODE_WS_BACKPRESSURE_OVERFLOW")); assert!(actor_source.contains("remote_to_local.remove")); } + +#[test] +fn release_v0_2_8_pre_009_http_and_standard_websocket_inventories_remain_exact() { + assert_eq!(ksp_onchain_transport_lib::current_http_rpc_methods().len(), 52); + assert_eq!(ksp_onchain_transport_lib::historical_http_rpc_methods().len(), 14); + let standard = [ + ksp_onchain_transport_lib::WsSubscriptionKind::Account, + ksp_onchain_transport_lib::WsSubscriptionKind::Block, + ksp_onchain_transport_lib::WsSubscriptionKind::Logs, + ksp_onchain_transport_lib::WsSubscriptionKind::Program, + ksp_onchain_transport_lib::WsSubscriptionKind::Root, + ksp_onchain_transport_lib::WsSubscriptionKind::Signature, + ksp_onchain_transport_lib::WsSubscriptionKind::Slot, + ksp_onchain_transport_lib::WsSubscriptionKind::SlotsUpdates, + ksp_onchain_transport_lib::WsSubscriptionKind::Vote, + ]; + assert_eq!(standard.len(), 9); + let lifecycle_source = include_str!("../src/ws_lifecycle.rs"); + for method in [ + "accountSubscribe", + "accountUnsubscribe", + "blockSubscribe", + "blockUnsubscribe", + "logsSubscribe", + "logsUnsubscribe", + "programSubscribe", + "programUnsubscribe", + "rootSubscribe", + "rootUnsubscribe", + "signatureSubscribe", + "signatureUnsubscribe", + "slotSubscribe", + "slotUnsubscribe", + "slotsUpdatesSubscribe", + "slotsUpdatesUnsubscribe", + "voteSubscribe", + "voteUnsubscribe", + ] { + assert!(lifecycle_source.contains(method), "missing standard WebSocket method mapping: {method}"); + } + let _account = ksp_onchain_transport_lib::SolanaStandardWsSession::account_subscribe; + let _block = ksp_onchain_transport_lib::SolanaStandardWsSession::block_subscribe; + let _logs = ksp_onchain_transport_lib::SolanaStandardWsSession::logs_subscribe; + let _program = ksp_onchain_transport_lib::SolanaStandardWsSession::program_subscribe; + let _root = ksp_onchain_transport_lib::SolanaStandardWsSession::root_subscribe; + let _signature = ksp_onchain_transport_lib::SolanaStandardWsSession::signature_subscribe; + let _slot = ksp_onchain_transport_lib::SolanaStandardWsSession::slot_subscribe; + let _slots_updates = ksp_onchain_transport_lib::SolanaStandardWsSession::slots_updates_subscribe; + let _vote = ksp_onchain_transport_lib::SolanaStandardWsSession::vote_subscribe; +} + +#[test] +fn release_v0_2_8_pre_009_helius_surface_is_seven_standard_families_plus_transaction() { + let _account = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::account_subscribe; + let _program = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::program_subscribe; + let _logs = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::logs_subscribe; + let _signature = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::signature_subscribe; + let _slot = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::slot_subscribe; + let _root = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::root_subscribe; + let _slots_updates = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::slots_updates_subscribe; + let _transaction = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::transaction_subscribe; + let protocol_source = include_str!("../src/ws_protocol_session.rs"); + assert!(protocol_source.contains("unsupported_block")); + assert!(protocol_source.contains("unsupported_vote")); + assert!(!protocol_source.contains("unsupported_slots_updates")); + let cluster_source = include_str!("../src/ws_cluster.rs"); + assert!(cluster_source.contains("impl crate::HeliusLaserStreamWsSession")); + assert!(cluster_source.contains("pub async fn slots_updates_subscribe")); + assert_eq!(ksp_onchain_transport_lib::WsSubscriptionKind::SlotsUpdates.as_str(), "slots_updates"); + assert_eq!(ksp_onchain_transport_lib::WsSubscriptionKind::HeliusTransaction.as_str(), "helius_transaction"); +} + +#[test] +fn release_v0_2_8_pre_009_config_secret_and_dependency_boundaries_remain_wired() { + let manifest_directory = std::path::Path::new(env!("CARGO_MANIFEST_DIR")); + let workspace = manifest_directory.parent().and_then(std::path::Path::parent).expect("Transport integration test must resolve the workspace root"); + let transport_manifest = std::fs::read_to_string(manifest_directory.join("Cargo.toml")).expect("Transport manifest must be readable"); + for forbidden in ["ksp-config-lib", "ksp-store-api", "ksp-store-lib", "ksp-program-api", "ksp-program-lib", "tracing =", "tracing."] { + assert!(!transport_manifest.contains(forbidden), "forbidden direct Transport dependency detected: {forbidden}"); + } + let config_manifest = std::fs::read_to_string(workspace.join("crates/ksp-config-lib/Cargo.toml")).expect("Config manifest must be readable"); + assert!(config_manifest.contains("ksp-onchain-transport-lib")); + let config_transport = + std::fs::read_to_string(workspace.join("crates/ksp-config-lib/src/transport.rs")).expect("Config Transport adapter source must be readable"); + assert!(config_transport.contains("WsProtocolKind::HeliusLaserStream")); + let transport_example = std::fs::read_to_string(workspace.join("config/examples/std.transport.example.json")).expect("Transport example must be readable"); + assert!(transport_example.contains("\"kind\": \"helius_laserstream\"")); + assert!(transport_example.contains("${KSP_SECRET_HELIUS_API_KEY")); + let env_example = std::fs::read_to_string(workspace.join(".env.example")).expect(".env.example must be readable"); + assert!(env_example.contains("KSP_SECRET_HELIUS_API_KEY")); +} diff --git a/crates/ksp-onchain-transport-lib/unit_tests/ws_helius_standard.rs b/crates/ksp-onchain-transport-lib/unit_tests/ws_helius_standard.rs index 520095d..296dbad 100644 --- a/crates/ksp-onchain-transport-lib/unit_tests/ws_helius_standard.rs +++ b/crates/ksp-onchain-transport-lib/unit_tests/ws_helius_standard.rs @@ -1,5 +1,5 @@ // file: crates/ksp-onchain-transport-lib/unit_tests/ws_helius_standard.rs -// version: 1 +// version: 2 use futures_util::SinkExt; // rust-rules: trait-import use futures_util::StreamExt; // rust-rules: trait-import @@ -63,7 +63,7 @@ async fn wait_for_close_frame(websocket: &mut tokio_tungstenite::WebSocketStream } #[tokio::test(flavor = "current_thread")] -async fn helius_facade_reuses_exact_standard_wire_for_all_six_supported_families() { +async fn helius_facade_reuses_exact_standard_wire_for_all_seven_currently_supported_families() { let (listener, url) = bind_local_listener().await; let server = tokio::spawn(async move { let (stream, _) = listener.accept().await.expect("local server must accept client"); @@ -95,6 +95,7 @@ async fn helius_facade_reuses_exact_standard_wire_for_all_six_supported_families .await; expect_pair(&mut websocket, "slotSubscribe", serde_json::json!([]), "slotUnsubscribe", 105).await; expect_pair(&mut websocket, "rootSubscribe", serde_json::json!([]), "rootUnsubscribe", 106).await; + expect_pair(&mut websocket, "slotsUpdatesSubscribe", serde_json::json!([]), "slotsUpdatesUnsubscribe", 107).await; wait_for_close_frame(&mut websocket).await; }); let session = crate::HeliusLaserStreamWsSession::connect(helius_endpoint(url.as_str())).await.expect("Helius facade must connect"); @@ -134,6 +135,8 @@ async fn helius_facade_reuses_exact_standard_wire_for_all_six_supported_families assert!(slot.unsubscribe().await.expect("Helius slotUnsubscribe must complete")); let mut root = session.root_subscribe().await.expect("Helius rootSubscribe must register"); assert!(root.unsubscribe().await.expect("Helius rootUnsubscribe must complete")); + let mut slots_updates = session.slots_updates_subscribe().await.expect("Helius slotsUpdatesSubscribe must register"); + assert!(slots_updates.unsubscribe().await.expect("Helius slotsUpdatesUnsubscribe must complete")); session.close().await.expect("Helius facade close must complete"); server.await.expect("local Helius peer task must complete"); } diff --git a/deltas/0.2.8/pre.009.md b/deltas/0.2.8/pre.009.md new file mode 100644 index 0000000..ce31b71 --- /dev/null +++ b/deltas/0.2.8/pre.009.md @@ -0,0 +1,262 @@ + + + +# Delta `0.2.8-pre.009` — compliance Helius courant + `slotsUpdates` + non-régressions finales + +## 1. Base et objet + +Base appliquée : + +```text +0.2.8-pre.8 +``` + +Le checkpoint opérateur `pre.008` est intégralement vert : + +```text +cargo fmt --all OK +python3 scripts/audit_rust_workspace_rules.py clean +cargo check --workspace OK +cargo clippy --workspace --all-targets OK +Transport unit 335/335 +Transport public API 40/40 +Transport release completeness 30/30 +Transport doctests 5/5 +cargo test --workspace OK +``` + +`pre.009` réalise la compliance finale Helius WebSocket prévue, mais le réaudit courant révèle une évolution de la documentation provider qui impose une petite extension fonctionnelle : `slotsUpdatesSubscribe`/`slotsUpdatesUnsubscribe` est désormais retenu comme disponible sur Helius. + +## 2. Version technique + +```text +workspace.package.version = 0.2.8-pre.9 +commit attendu = v0.2.8-pre.009 +Git tag = aucun tag prerelease +``` + +Le header root `Cargo.toml` passe en version `233`. + +## 3. Réconciliation documentaire Helius du 2026-08-23 + +Sources officielles relues : + +```text +https://www.helius.dev/docs/rpc/websocket +https://www.helius.dev/docs/api-reference/rpc/websocket/slotsupdatessubscribe +https://www.helius.dev/docs/api-reference/rpc/websocket/slotsupdatesunsubscribe +https://www.helius.dev/docs/api-reference/rpc/websocket/blocksubscribe +https://www.helius.dev/docs/api-reference/rpc/websocket/votesubscribe +https://www.helius.dev/docs/api-reference/rpc/websocket/accountsubscribe +https://www.helius.dev/docs/api-reference/rpc/websocket/transactionsubscribe +``` + +État courant : + +```text +overview LaserStream WebSocket + -> annonce le support du jeu complet des méthodes standard + +blockSubscribe + -> page spécifique : unstable + explicitement non supporté Helius + +voteSubscribe + -> page spécifique : unstable + explicitement non supporté Helius + +slotsUpdatesSubscribe + -> page spécifique : unstable + -> endpoints Helius mainnet/devnet + -> request, notification et subscription ID documentés + -> aucune mention de non-support Helius + +slotsUpdatesUnsubscribe + -> subscriptionId entier + -> result bool +``` + +Arbitrage KSP : lorsqu'une formule globale et une page de méthode divergent, **la page spécifique prévaut**. + +Surface Helius retenue après réaudit : + +```text +standard : account, logs, program, root, signature, slot, slotsUpdates +extension: transaction +absent : block, vote +``` + +## 4. `slotsUpdates` rejoint la façade Helius + +`HeliusLaserStreamWsSession` expose désormais : + +```rust +pub async fn slots_updates_subscribe( + &self, +) -> ksp_core_lib::Result> +``` + +Aucun nouveau DTO ni nouveau wire n'est créé. La façade délègue au même chemin déjà stabilisé : + +```text +HeliusLaserStreamWsSession + -> physical_session() + -> WsSession::slots_updates_subscribe() + -> WsSubscriptionKind::SlotsUpdates + -> slotsUpdatesSubscribe + -> slotsUpdatesNotification + -> slotsUpdatesUnsubscribe via handle +``` + +Le caractère unstable reste celui de la famille standard : le warning central `warn_if_unstable()` est donc conservé automatiquement. + +## 5. Capability guards réconciliés + +Le compile-fail historique : + +```text +Helius -X-> slotsUpdatesSubscribe +``` + +est supprimé car il contredirait la surface courante. + +Restent obligatoires : + +```text +Helius -X-> blockSubscribe +Helius -X-> voteSubscribe +Helius -X-> into_inner +SolanaStandard -X-> transactionSubscribe +``` + +Aucun escape hatch vers le `WsSession` générique n'est ajouté. + +## 6. `accountSubscribe` enhanced : pas de wire inventé + +L'overview Helius mentionne désormais des « advanced filters » sur `accountSubscribe`, mais la page API spécifique ne publie actuellement que : + +```text +pubkey +encoding +commitment +notifyOn deprecated/no-op +``` + +Aucun DTO provider-specific supplémentaire n'est ajouté tant qu'un wire exact n'est pas publié. `notifyOn` reste volontairement absent. + +## 7. Canaris de compliance transversaux + +Trois canaris sont ajoutés dans `tests/release_completeness.rs`. + +### 7.1 HTTP + Standard WebSocket + +Ils verrouillent : + +```text +HTTP current 52 +HTTP historical 14 +Standard WS 9 familles +Standard operations 18 subscribe/unsubscribe +``` + +Les neuf méthodes typed de `SolanaStandardWsSession` restent adressables. + +### 7.2 Helius courant + +Ils verrouillent : + +```text +7 familles standard : + account + logs + program + root + signature + slot + slotsUpdates + +1 extension : + transaction + +absentes : + block + vote +``` + +Le source canary vérifie également que le guard `unsupported_slots_updates` a disparu tandis que `unsupported_block` et `unsupported_vote` restent présents. + +### 7.3 Config / secret / dependency firewall + +La compliance finale vérifie durablement : + +```text +Transport -X-> Config/Store/Program/tracing direct +Config -> Transport présent +Config mappe WsProtocolKind::HeliusLaserStream +example Transport contient kind = helius_laserstream +example Transport utilise ${KSP_SECRET_HELIUS_API_KEY...} +.env.example inventorie KSP_SECRET_HELIUS_API_KEY +``` + +Aucune nouvelle dépendance n'est introduite. + +## 8. Public API et fixture Helius standard + +Un public-API canary supplémentaire adresse `HeliusLaserStreamWsSession::slots_updates_subscribe` et le DTO partagé `SolanaSlotUpdate`. + +Le fixture Helius standard existant passe de six à sept familles et vérifie la paire exacte : + +```text +slotsUpdatesSubscribe params [] +slotsUpdatesUnsubscribe params [remoteSubscriptionId] +``` + +Le lifecycle, le decoder, le remote-ID mapping et l'unsubscribe restent ceux du moteur commun. + +## 9. Comptages attendus + +```text +Transport unit 335 +Transport public API 41 +release completeness 33 +doctests compile-fail 4 +``` + +La diminution de 5 à 4 doctests est intentionnelle : le compile-fail Helius `slotsUpdatesSubscribe` est retiré parce que cette API devient supportée. + +## 10. Fichiers modifiés + +```text +Cargo.toml +crates/ksp-onchain-transport-lib/src/lib.rs +crates/ksp-onchain-transport-lib/src/ws_cluster.rs +crates/ksp-onchain-transport-lib/src/ws_protocol_session.rs +crates/ksp-onchain-transport-lib/tests/public_api.rs +crates/ksp-onchain-transport-lib/tests/release_completeness.rs +crates/ksp-onchain-transport-lib/unit_tests/ws_helius_standard.rs +docs/plans/015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md +docs/validation/011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md +deltas/0.2.8/pre.009.md +``` + +## 11. Hors scope + +Restent hors `pre.009` : + +```text +smoke Helius live opt-in + README/USAGE + cargo tree final pre.010 +fermeture workspace/docs/indexes + prompt 0.2.9 pre.011 +LaserStream gRPC futur backend distinct +Gatekeeper beta / preconfirmations hors 0.2.8 +``` + +## 12. Gate opérateur + +```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 +``` + +Critère de fermeture : zéro warning, audit clean, **335 unit / 41 public API / 33 completeness / 4 doctests** et workspace vert. diff --git a/docs/plans/015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md b/docs/plans/015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md index b6ad5df..17e9a11 100644 --- a/docs/plans/015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md +++ b/docs/plans/015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md @@ -1,9 +1,9 @@ - + # Plan `0.2.8` — Helius LaserStream WebSocket -> **Statut : `0.2.8-pre.007-fix.004` est validé intégralement par l’opérateur : fmt/audit/check/Clippy, 331 unit Transport, 40 API, 29 completeness, 4 doctests et workspace complet verts. `0.2.8-pre.008` est préparé pour les guards adversariaux provider, limites/payload, isolation de session et redaction des diagnostics Helius.** +> **Statut : `0.2.8-pre.008` est validé intégralement par l’opérateur : fmt/audit/check/Clippy, 335 unit Transport, 40 API, 30 completeness, 5 doctests et workspace complet verts. `0.2.8-pre.009` réconcilie la documentation Helius courante, ajoute `slotsUpdates` à la façade Helius et ferme les canaris de compliance HTTP/WS/Config/dependencies.** ## 1. Objet, base et état courant @@ -77,9 +77,9 @@ pre.007 DONE — heartbeat Helius WebSocket/idle + timers + interaction reconne fix.002 DONE — diagnostic de propagation scheduler établi fix.003 DONE — canari heartbeat périodique stabilisé sans changer le runtime fix.004 DONE — dependency-firewall aligné sur `io-util, net, rt, test-util` -pre.008 PREPARED — provider adversarial lifecycle + capability guards + payload/backpressure + security/redaction -pre.009 compliance Helius WebSocket + non-régressions Solana standard 18/18 + HTTP 52/14 - + Config/API/dependency-firewall canaries +pre.008 DONE — provider adversarial lifecycle + capability guards + payload/backpressure + security/redaction +pre.009 PREPARED — compliance Helius WebSocket + réconciliation documentaire `slotsUpdates` + + non-régressions Solana standard 18/18 + HTTP 52/14 + Config/API/dependency-firewall canaries pre.010 smoke Helius WebSocket live opt-in si stratégie sûre + README/USAGE + cargo tree direct/duplicates final pre.011 validation workspace finale + fermeture plan/matrice/indexes + prompt 0.2.9 @@ -307,9 +307,9 @@ LaserStream gRPC = distinct, hors 0.2.8 ### 5.3 Inventaire provider retenu ```text -standard supporté : account, logs, program, root, signature, slot +standard supporté : account, logs, program, root, signature, slot, slotsUpdates Helius extension : transactionSubscribe / transactionUnsubscribe -non supporté : block, slotsUpdates, vote +non supporté : block, vote ``` `transactionUnsubscribe` est documenté dans la référence `transactionSubscribe` avec : @@ -322,21 +322,24 @@ result = true La référence précise que quelques notifications in-flight peuvent encore arriver après l'unsubscribe. -### 5.4 Divergence `slotsUpdatesSubscribe` +### 5.4 Réconciliation `slotsUpdatesSubscribe` au réaudit `pre.009` -Les sources Helius se contredisent : +La documentation Helius courante a évolué depuis `pre.001` : -- `websocket-methods` classe `slotsUpdatesSubscribe`/`slotsUpdatesUnsubscribe` parmi les méthodes unstable non supportées ; -- la page individuelle indique que la méthode est unstable et peut ne pas être supportée ; -- `websocket/llms.txt` la place aussi dans une section « Stable, Helius-supported ». +- l'overview LaserStream WebSocket affirme désormais supporter le jeu complet des méthodes standard et énumère explicitement `slotsUpdatesSubscribe` avec son unsubscribe ; +- la page spécifique `slotsUpdatesSubscribe` la documente comme unstable, avec endpoints mainnet/devnet, request, notification et subscription ID, sans mention « Helius does not support » ; +- la page spécifique `slotsUpdatesUnsubscribe` documente l'ID numérique et la réponse booléenne ; +- à l'inverse, les pages spécifiques `blockSubscribe` et `voteSubscribe` gardent explicitement « Helius does not support ». -Décision KSP : +Arbitrage KSP `pre.009` : la page spécifique de chaque méthode prévaut sur une formule globale lorsqu'elles divergent. ```text -HeliusLaserStreamWsSession n'expose pas SlotsUpdates +slotsUpdatesSubscribe / slotsUpdatesUnsubscribe = support Helius retenu, unstable +blockSubscribe / blockUnsubscribe = non supporté Helius +voteSubscribe / voteUnsubscribe = non supporté Helius ``` -Une validation interne garde aussi un rejet avant I/O si un descriptor incompatible atteint le moteur par un chemin interne ou de compatibilité. +`HeliusLaserStreamWsSession` expose donc `slots_updates_subscribe()` à partir de `pre.009`, en réutilisant exactement le DTO, le wire, l'unsubscribe par handle, le warning unstable et l'actor standard existants. Aucun type provider-specific n'est créé pour cette famille. ### 5.5 `transactionSubscribe` @@ -388,24 +391,24 @@ Les pages continuent à employer « enhanced/filtered accountSubscribe » sans p ## 6. Matrice normative Helius WebSocket -| Famille | Paire | Classe | Support Helius retenu | Surface publique Helius | Paramètres/options utiles | Notification | Stratégie KSP/test | -|---------------------|-----------------------------------------------------|------------------|-----------------------|-------------------------|------------------------------------|---------------------------|----------------------------------------------------| -| `account` | `accountSubscribe` / `accountUnsubscribe` | Solana standard | Oui | présente | contrat standard ; `notifyOn` omis | `accountNotification` | DTO/wire standard partagé | -| `block` | `blockSubscribe` / `blockUnsubscribe` | Solana unstable | **Non** | **absente** | aucune émission provider | théorique | façade Helius sans méthode + guard interne | -| `logs` | `logsSubscribe` / `logsUnsubscribe` | Solana standard | Oui | présente | contrat standard | `logsNotification` | DTO/wire standard partagé | -| `program` | `programSubscribe` / `programUnsubscribe` | Solana standard | Oui | présente | contrat standard ; `notifyOn` omis | `programNotification` | DTO/wire standard partagé | -| `root` | `rootSubscribe` / `rootUnsubscribe` | Solana standard | Oui | présente | aucun paramètre | `rootNotification` | wrapper partagé | -| `signature` | `signatureSubscribe` / `signatureUnsubscribe` | Solana standard | Oui | présente | one-shot conservé | `signatureNotification` | wrapper partagé + terminal close | -| `slot` | `slotSubscribe` / `slotUnsubscribe` | Solana standard | Oui | présente | aucun paramètre | `slotNotification` | wrapper partagé | -| `slotsUpdates` | `slotsUpdatesSubscribe` / `slotsUpdatesUnsubscribe` | Solana unstable | **Non** | **absente** | aucune émission provider | théorique | façade Helius sans méthode + divergence documentée | -| `vote` | `voteSubscribe` / `voteUnsubscribe` | Solana unstable | **Non** | **absente** | aucune émission provider | théorique | façade Helius sans méthode + guard interne | -| `heliusTransaction` | `transactionSubscribe` / `transactionUnsubscribe` | Helius extension | Oui | présente | filtres/options/`tokenAccounts` | `transactionNotification` | DTOs Helius + actor partagé | +| Famille | Paire | Classe | Support Helius retenu | Surface publique Helius | Paramètres/options utiles | Notification | Stratégie KSP/test | +|---------------------|-----------------------------------------------------|------------------|-----------------------|-------------------------|------------------------------------|----------------------------|----------------------------------------------| +| `account` | `accountSubscribe` / `accountUnsubscribe` | Solana standard | Oui | présente | contrat standard ; `notifyOn` omis | `accountNotification` | DTO/wire standard partagé | +| `block` | `blockSubscribe` / `blockUnsubscribe` | Solana unstable | **Non** | **absente** | aucune émission provider | théorique | façade Helius sans méthode + guard interne | +| `logs` | `logsSubscribe` / `logsUnsubscribe` | Solana standard | Oui | présente | contrat standard | `logsNotification` | DTO/wire standard partagé | +| `program` | `programSubscribe` / `programUnsubscribe` | Solana standard | Oui | présente | contrat standard ; `notifyOn` omis | `programNotification` | DTO/wire standard partagé | +| `root` | `rootSubscribe` / `rootUnsubscribe` | Solana standard | Oui | présente | aucun paramètre | `rootNotification` | wrapper partagé | +| `signature` | `signatureSubscribe` / `signatureUnsubscribe` | Solana standard | Oui | présente | one-shot conservé | `signatureNotification` | wrapper partagé + terminal close | +| `slot` | `slotSubscribe` / `slotUnsubscribe` | Solana standard | Oui | présente | aucun paramètre | `slotNotification` | wrapper partagé | +| `slotsUpdates` | `slotsUpdatesSubscribe` / `slotsUpdatesUnsubscribe` | Solana unstable | Oui | présente | aucun paramètre | `slotsUpdatesNotification` | DTO/wire standard partagé + warning unstable | +| `vote` | `voteSubscribe` / `voteUnsubscribe` | Solana unstable | **Non** | **absente** | aucune émission provider | théorique | façade Helius sans méthode + guard interne | +| `heliusTransaction` | `transactionSubscribe` / `transactionUnsubscribe` | Helius extension | Oui | présente | filtres/options/`tokenAccounts` | `transactionNotification` | DTOs Helius + actor partagé | Statut : ```text SolanaStandardWsSession : 9 familles / 18 opérations standard -HeliusLaserStreamWsSession : 6 familles standard supportées + 1 famille Helius +HeliusLaserStreamWsSession : 7 familles standard supportées + 1 famille Helius ``` La compliance standard KSP reste **18/18** pour `SolanaStandard`. @@ -488,16 +491,16 @@ program root signature slot +slotsUpdates transaction ``` -`pre.003` matérialise exactement les six familles standard ; `transaction` reste réservé aux tranches provider-specific ultérieures du forecast. +`pre.003` matérialisait les six familles standard alors retenues ; `pre.009` ajoute `slotsUpdates` après évolution de la documentation Helius, tandis que `transaction` reste la famille provider-specific. -La façade Helius **n'expose jamais dans le scope courant** : +La façade Helius **n'expose pas dans le scope courant** les deux familles dont les pages spécifiques Helius restent explicitement non supportées : ```text block -slotsUpdates vote ``` @@ -813,7 +816,7 @@ Prévoir : ```text public API canary SolanaStandardWsSession public API canary HeliusLaserStreamWsSession -Helius facade sans block/slotsUpdates/vote +Helius facade sans block/vote ; slotsUpdates présent et unstable Solana facade sans transactionSubscribe Helius facade sans escape hatch vers WsSession générique WsSession historique standard toujours disponible @@ -1396,3 +1399,65 @@ warnings 0 `pre.009` reste bloqué jusqu'au replay intégralement vert de `pre.008`. +## 21. Fermeture `pre.008` et préparation `pre.009` + +Checkpoint opérateur `0.2.8-pre.8` reçu le 2026-08-23 : + +```text +[x] cargo fmt --all +[x] python3 scripts/audit_rust_workspace_rules.py = clean / 0 candidate +[x] cargo check --workspace = vert, sans warning +[x] cargo clippy --workspace --all-targets = vert, sans warning +[x] Transport unit = 335/335 +[x] Transport public API = 40/40 +[x] release completeness = 30/30 +[x] Transport doctests = 5/5 +[x] cargo test --workspace = vert +``` + +Verdict : **`pre.008` DONE.** + +Le réaudit final de conformité Helius révèle une évolution normative depuis `pre.001`. L'overview LaserStream WebSocket courant affirme désormais le support du jeu complet des méthodes standard. Les pages spécifiques permettent de résoudre la divergence sans extrapolation : + +```text +blockSubscribe page spécifique = explicitement non supporté Helius +voteSubscribe page spécifique = explicitement non supporté Helius +slotsUpdatesSubscribe page spécifique = unstable, documenté sur endpoints Helius, sans interdiction provider +slotsUpdatesUnsubscribe = documenté avec subscriptionId + bool +``` + +Décision `pre.009` : + +```text +Helius standard actuel retenu = account/logs/program/root/signature/slot/slotsUpdates +Helius extension = transaction +Helius absent = block/vote +SolanaStandard = 9 familles / 18 opérations inchangées +HTTP = 52 current + 14 historical inchangés +``` + +La tranche ajoute uniquement la façade Helius `slots_updates_subscribe()` en réutilisant `WsSubscriptionKind::SlotsUpdates`, `SolanaSlotUpdate`, le triplet wire standard et le lifecycle actor déjà existant. Elle retire le compile-fail Helius correspondant, conserve ceux de block/vote et garde le compile-fail inverse `SolanaStandard -X-> transactionSubscribe`. + +Canaris de fermeture prévus : + +```text +Transport unit 335 +Transport public API 41 +release completeness 33 +Transport doctests 4 +workspace vert +warnings 0 +``` + +Les trois nouveaux canaris `release_completeness` verrouillent : + +```text +1. HTTP 52/14 + Standard WebSocket 9 familles / 18 méthodes ; +2. Helius = 7 familles standard + transaction, avec block/vote toujours absents ; +3. Config -> Transport, KSP_SECRET_HELIUS_API_KEY et dependency firewall sans reverse dependency. +``` + +Aucune nouvelle dépendance, aucun nouveau DTO Helius pour `slotsUpdates`, aucun second socket/actor et aucune modification Config ne sont nécessaires. Le point « enhanced accountSubscribe » reste reporté : l'overview parle de filtres avancés, mais la page API spécifique ne publie toujours pas de wire provider-specific supplémentaire assez précis pour une API typed ; KSP ne devine donc aucun champ. + +`pre.010` reste réservé au smoke Helius live opt-in si une stratégie credential-safe est disponible, à README/USAGE et au `cargo tree` final. + diff --git a/docs/validation/011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md b/docs/validation/011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md index d54a7dc..349cb33 100644 --- a/docs/validation/011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md +++ b/docs/validation/011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md @@ -1,9 +1,9 @@ - + # Validation `0.2.8` — Helius LaserStream WebSocket -> **Statut : `pre.007-fix.003` est vert côté Transport à 331/331 + 40 API + 29 completeness + 4 doctests, mais `cargo test --workspace` échoue sur le canari `transport_manifest_preserves_ksp_dependency_firewall`, resté figé sur les anciennes features Tokio dev. `pre.007-fix.004` met ce canari en cohérence avec le manifest déjà livré, sans changement runtime.** +> **Statut : `pre.008` est entièrement vert : 335/335 unit Transport, 40/40 API, 30/30 completeness, 5/5 doctests et workspace complet. `pre.009` est préparé avec réconciliation de la documentation Helius courante : `slotsUpdates` rejoint la façade Helius ; `block` et `vote` restent explicitement non supportés.** ## 1. Références @@ -29,6 +29,8 @@ pre.007 test determinism fix deltas/0.2.8/pre.007-fix.001.md pre.007 scheduler observation fix deltas/0.2.8/pre.007-fix.002.md pre.007 paused-I/O observation fix deltas/0.2.8/pre.007-fix.003.md pre.007 dependency-firewall fix deltas/0.2.8/pre.007-fix.004.md +pre.008 adversarial/compliance guard deltas/0.2.8/pre.008.md +pre.009 compliance provider/current deltas/0.2.8/pre.009.md validation standard WS docs/validation/010-V0_2_7_ONCHAIN_WEBSOCKET.md HTTP compliance docs/validation/007-V0_2_4_HTTP_FINAL_COMPLIANCE.md KSP-TRANSPORT-007 docs/validation/005-V0_2_3_KSP_TRANSPORT_007_RETRO_AUDIT.md @@ -112,7 +114,7 @@ Verdict : **gate `0.2.8-pre.001` positif ; `pre.002` + `fix.001` et `pre.003` so | `signatureSubscribe` pair | oui | supporté | réutiliser standard | présente | one-shot conservé | | `slotSubscribe` pair | oui | supporté | réutiliser standard | présente | exact wire + no regression | | `blockSubscribe` pair | oui, unstable | non supporté | ne pas exposer Helius | **absente** | API absence + guard interne avant I/O | -| `slotsUpdatesSubscribe` pair | oui, unstable | docs divergentes ; index exhaustif = non supporté | ne pas exposer Helius | **absente** | API absence + divergence documentée | +| `slotsUpdatesSubscribe` pair | oui, unstable | page spécifique + overview courant = disponible | réutiliser wire standard | présente | exact wire + warning unstable | | `voteSubscribe` pair | oui, unstable | non supporté | ne pas exposer Helius | **absente** | API absence + guard interne avant I/O | | `transactionSubscribe` | non standard | extension Helius | ajouter typed | présente | request/ack/notification fixtures | | `transactionUnsubscribe` | non standard | documenté dans référence transaction | ajouter via handle | présente | exact method + late-message race | @@ -136,7 +138,7 @@ Verdict : **gate `0.2.8-pre.001` positif ; `pre.002` + `fix.001` et `pre.003` so | Root | oui | oui | partagé standard | | Signature | oui | oui | partagé standard | | Slot | oui | oui | partagé standard | -| SlotsUpdates | oui | **non** | standard seulement | +| SlotsUpdates | oui | oui | partagé standard | | Vote | oui | **non** | standard seulement | | Helius Transaction | **non** | oui | provider-specific | @@ -894,3 +896,93 @@ La correction `Debug` ne retire aucune donnée de l'API fonctionnelle : `transac Verdict courant : **`pre.008` PREPARED ; `pre.009` bloqué jusqu'au gate opérateur.** +## 23. Fermeture `pre.008` et gate `pre.009` + +Résultat opérateur `0.2.8-pre.8` : + +```text +[x] cargo fmt --all +[x] audit Rust workspace = clean / 0 candidate +[x] cargo check --workspace = vert, sans warning +[x] cargo clippy --workspace --all-targets = vert, sans warning +[x] Transport unit = 335/335 +[x] Transport public API = 40/40 +[x] release completeness = 30/30 +[x] Transport doctests = 5/5 +[x] cargo test --workspace = vert +``` + +Verdict : **`pre.008` DONE.** + +### 23.1 Réaudit Helius final avant compliance + +Le réaudit du 2026-08-23 révèle une évolution de la documentation Helius par rapport au checkpoint `pre.001` : + +```text +overview LaserStream WebSocket + -> annonce le support du jeu complet des méthodes standard + -> énumère account/block/logs/program/root/signature/slot/slotsUpdates/vote + unsubscribe + +page blockSubscribe + -> garde explicitement "Helius does not support" + +page voteSubscribe + -> garde explicitement "Helius does not support" + +page slotsUpdatesSubscribe + -> unstable + -> endpoints Helius mainnet/devnet + -> request/notification/result documentés + -> aucune mention de non-support Helius + +page slotsUpdatesUnsubscribe + -> subscriptionId entier + -> result bool +``` + +Arbitrage : **la page spécifique de méthode prévaut sur la formulation générale lorsqu'elles divergent**. Le support Helius final retenu devient : + +```text +standard Helius : account/logs/program/root/signature/slot/slotsUpdates +provider Helius : transaction +absent Helius : block/vote +``` + +Le point `accountSubscribe` « advanced filters » reste non matérialisé : l'overview le mentionne, mais la page API spécifique ne publie aucun wire provider-specific supplémentaire au-delà du contrat standard et de `notifyOn` deprecated/no-op. Aucun champ n'est inventé. + +### 23.2 Critères `pre.009` + +```text +[ ] workspace.package.version = 0.2.8-pre.9 +[ ] HeliusLaserStreamWsSession expose slots_updates_subscribe +[ ] Helius slotsUpdates réutilise SolanaSlotUpdate et WsSubscriptionKind::SlotsUpdates +[ ] wire exact slotsUpdatesSubscribe / slotsUpdatesUnsubscribe inchangé +[ ] warning unstable standard conservé +[ ] compile-fail Helius slotsUpdates retiré +[ ] compile-fail Helius block conservé +[ ] compile-fail Helius vote conservé +[ ] compile-fail Helius into_inner conservé +[ ] compile-fail SolanaStandard transactionSubscribe conservé +[ ] HTTP = 52 current + 14 historical +[ ] Standard WebSocket = 9 familles / 18 méthodes +[ ] Helius = 7 familles standard + transaction +[ ] Config -> Transport reste la seule direction +[ ] KSP_SECRET_HELIUS_API_KEY reste inventorié +[ ] Transport n'ajoute aucune dépendance Config/Store/Program/tracing direct +[ ] aucune nouvelle dépendance +[ ] aucun second actor/socket/registry +[ ] cargo fmt --all +[ ] audit Rust = clean +[ ] cargo check = sans warning +[ ] cargo clippy = sans warning +[ ] Transport unit = 335 +[ ] Transport public API = 41 +[ ] release completeness = 33 +[ ] Transport doctests = 4 +[ ] cargo test --workspace = vert +``` + +Le passage de 5 à 4 doctests est attendu : le canari compile-fail `Helius -X-> slotsUpdatesSubscribe` est supprimé parce que la méthode devient volontairement publique. Les quatre canaris négatifs restants sont `Helius -X-> block`, `Helius -X-> vote`, `Helius -X-> into_inner` et `SolanaStandard -X-> transactionSubscribe`. + +Verdict courant : **`pre.009` PREPARED ; `pre.010` bloqué jusqu'au gate opérateur.** +