v0.2.8-pre.009

This commit is contained in:
2026-08-23 18:16:03 +02:00
parent 7c12ec886b
commit 9c0d4fc197
10 changed files with 579 additions and 59 deletions

View File

@@ -1,12 +1,12 @@
# file: Cargo.toml # file: Cargo.toml
# version: 232 # version: 233
[workspace] [workspace]
resolver = "3" 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"] 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] [workspace.package]
version = "0.2.8-pre.8" version = "0.2.8-pre.9"
edition = "2024" edition = "2024"
license = "MIT" license = "MIT"
repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project" repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project"

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/src/lib.rs // file: crates/ksp-onchain-transport-lib/src/lib.rs
// version: 33 // version: 34
#![warn(missing_docs)] #![warn(missing_docs)]
#![deny(unreachable_pub)] #![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 //! `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 //! 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. //! 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 //! `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
//! `transactionSubscribe` request contract and provider filter/options validation. `0.2.8-pre.006` integrates the live transaction handle and typed //! Helius documentation and adds the now-documented unstable `slotsUpdatesSubscribe` pair while keeping explicitly unsupported block/vote pairs absent.
//! `transactionNotification` union into the same actor-owned registry, remote-ID remap, unsubscribe-race handling and per-subscription backpressure path. //! `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 client;
mod constants; mod constants;

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/src/ws_cluster.rs // file: crates/ksp-onchain-transport-lib/src/ws_cluster.rs
// version: 4 // version: 5
/// Slot relationship reported by the standard Solana `slotNotification` WebSocket method. /// Slot relationship reported by the standard Solana `slotNotification` WebSocket method.
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -433,6 +433,12 @@ impl crate::HeliusLaserStreamWsSession {
pub async fn root_subscribe(&self) -> ksp_core_lib::Result<crate::WsSubscription<u64>> { pub async fn root_subscribe(&self) -> ksp_core_lib::Result<crate::WsSubscription<u64>> {
return self.physical_session().root_subscribe().await; 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<crate::WsSubscription<crate::SolanaSlotUpdate>> {
return self.physical_session().slots_updates_subscribe().await;
}
} }
#[cfg(test)] #[cfg(test)]

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/src/ws_protocol_session.rs // file: crates/ksp-onchain-transport-lib/src/ws_protocol_session.rs
// version: 5 // version: 6
/// Typed facade for one standard Solana WebSocket physical session. /// 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. /// 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 /// `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 /// 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`]. /// provider-specific surface by recovering a generic [`crate::WsSession`].
@@ -79,12 +80,6 @@ impl std::fmt::Debug for SolanaStandardWsSession {
/// ``` /// ```
/// ///
/// ```compile_fail /// ```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) { /// async fn unsupported_vote(session: &ksp_onchain_transport_lib::HeliusLaserStreamWsSession) {
/// let _ = session.vote_subscribe().await; /// let _ = session.vote_subscribe().await;
/// } /// }

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/tests/public_api.rs // 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. //! 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::<ksp_onchain_transport_lib::HeliusTransactionSignatureNotification>(); let _signature = std::any::type_name::<ksp_onchain_transport_lib::HeliusTransactionSignatureNotification>();
assert_eq!(ksp_onchain_transport_lib::WsSubscriptionKind::HeliusTransaction.as_str(), "helius_transaction"); 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::<ksp_onchain_transport_lib::SolanaSlotUpdate>();
assert_eq!(ksp_onchain_transport_lib::WsSubscriptionKind::SlotsUpdates.as_str(), "slots_updates");
}

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/tests/release_completeness.rs // 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. //! 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] #[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 _account = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::account_subscribe;
let _program = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::program_subscribe; let _program = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::program_subscribe;
let _logs = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::logs_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 _root = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::root_subscribe;
let source = include_str!("../src/ws_protocol_session.rs"); let source = include_str!("../src/ws_protocol_session.rs");
assert!(source.contains("unsupported_block")); assert!(source.contains("unsupported_block"));
assert!(source.contains("unsupported_slots_updates"));
assert!(source.contains("unsupported_vote")); assert!(source.contains("unsupported_vote"));
assert!(!source.contains("pub async fn transaction_subscribe")); assert!(!source.contains("pub async fn transaction_subscribe"));
assert_eq!(ksp_onchain_transport_lib::WsProtocolKind::HeliusLaserStream.as_str(), "helius_laserstream"); 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")); assert!(!source.contains("tokio_tungstenite::connect_async"));
let protocol_source = include_str!("../src/ws_protocol_session.rs"); let protocol_source = include_str!("../src/ws_protocol_session.rs");
assert!(protocol_source.contains("unsupported_block")); assert!(protocol_source.contains("unsupported_block"));
assert!(protocol_source.contains("unsupported_slots_updates"));
assert!(protocol_source.contains("unsupported_vote")); 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"); let protocol_source = include_str!("../src/ws_protocol_session.rs");
assert!(protocol_source.contains("unsupported_helius_transaction")); assert!(protocol_source.contains("unsupported_helius_transaction"));
assert!(protocol_source.contains("unsupported_block")); assert!(protocol_source.contains("unsupported_block"));
assert!(protocol_source.contains("unsupported_slots_updates"));
assert!(protocol_source.contains("unsupported_vote")); assert!(protocol_source.contains("unsupported_vote"));
let helius_source = include_str!("../src/ws_helius_transactions.rs"); let helius_source = include_str!("../src/ws_helius_transactions.rs");
assert!(helius_source.contains("impl std::fmt::Debug for HeliusFullTransactionNotification")); 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("ERROR_CODE_WS_BACKPRESSURE_OVERFLOW"));
assert!(actor_source.contains("remote_to_local.remove")); 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"));
}

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-onchain-transport-lib/unit_tests/ws_helius_standard.rs // 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::SinkExt; // rust-rules: trait-import
use futures_util::StreamExt; // 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")] #[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 (listener, url) = bind_local_listener().await;
let server = tokio::spawn(async move { let server = tokio::spawn(async move {
let (stream, _) = listener.accept().await.expect("local server must accept client"); 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; .await;
expect_pair(&mut websocket, "slotSubscribe", serde_json::json!([]), "slotUnsubscribe", 105).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, "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; wait_for_close_frame(&mut websocket).await;
}); });
let session = crate::HeliusLaserStreamWsSession::connect(helius_endpoint(url.as_str())).await.expect("Helius facade must connect"); 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")); assert!(slot.unsubscribe().await.expect("Helius slotUnsubscribe must complete"));
let mut root = session.root_subscribe().await.expect("Helius rootSubscribe must register"); let mut root = session.root_subscribe().await.expect("Helius rootSubscribe must register");
assert!(root.unsubscribe().await.expect("Helius rootUnsubscribe must complete")); 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"); session.close().await.expect("Helius facade close must complete");
server.await.expect("local Helius peer task must complete"); server.await.expect("local Helius peer task must complete");
} }

262
deltas/0.2.8/pre.009.md Normal file
View File

@@ -0,0 +1,262 @@
<!-- file: deltas/0.2.8/pre.009.md -->
<!-- version: 1 -->
# 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<crate::WsSubscription<crate::SolanaSlotUpdate>>
```
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.

View File

@@ -1,9 +1,9 @@
<!-- file: docs/plans/015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md --> <!-- file: docs/plans/015-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET_PLAN.md -->
<!-- version: 22 --> <!-- version: 23 -->
# Plan `0.2.8` — Helius LaserStream WebSocket # Plan `0.2.8` — Helius LaserStream WebSocket
> **Statut : `0.2.8-pre.007-fix.004` est validé intégralement par lopé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 lopé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 ## 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.002 DONE — diagnostic de propagation scheduler établi
fix.003 DONE — canari heartbeat périodique stabilisé sans changer le runtime 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` 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.008 DONE — provider adversarial lifecycle + capability guards + payload/backpressure + security/redaction
pre.009 compliance Helius WebSocket + non-régressions Solana standard 18/18 + HTTP 52/14 pre.009 PREPARED — compliance Helius WebSocket + réconciliation documentaire `slotsUpdates`
+ Config/API/dependency-firewall canaries + 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 pre.010 smoke Helius WebSocket live opt-in si stratégie sûre + README/USAGE
+ cargo tree direct/duplicates final + cargo tree direct/duplicates final
pre.011 validation workspace finale + fermeture plan/matrice/indexes + prompt 0.2.9 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 ### 5.3 Inventaire provider retenu
```text ```text
standard supporté : account, logs, program, root, signature, slot standard supporté : account, logs, program, root, signature, slot, slotsUpdates
Helius extension : transactionSubscribe / transactionUnsubscribe Helius extension : transactionSubscribe / transactionUnsubscribe
non supporté : block, slotsUpdates, vote non supporté : block, vote
``` ```
`transactionUnsubscribe` est documenté dans la référence `transactionSubscribe` avec : `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. 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 ; - 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 individuelle indique que la méthode est unstable et peut ne pas être supportée ; - la page spécifique `slotsUpdatesSubscribe` la documente comme unstable, avec endpoints mainnet/devnet, request, notification et subscription ID, sans mention « Helius does not support » ;
- `websocket/llms.txt` la place aussi dans une section « Stable, Helius-supported ». - 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 ```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` ### 5.5 `transactionSubscribe`
@@ -388,24 +391,24 @@ Les pages continuent à employer « enhanced/filtered accountSubscribe » sans p
## 6. Matrice normative Helius WebSocket ## 6. Matrice normative Helius WebSocket
| Famille | Paire | Classe | Support Helius retenu | Surface publique Helius | Paramètres/options utiles | Notification | Stratégie KSP/test | | 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é | | `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 | | `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é | | `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é | | `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é | | `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 | | `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é | | `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 | | `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 | | `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é | | `heliusTransaction` | `transactionSubscribe` / `transactionUnsubscribe` | Helius extension | Oui | présente | filtres/options/`tokenAccounts` | `transactionNotification` | DTOs Helius + actor partagé |
Statut : Statut :
```text ```text
SolanaStandardWsSession : 9 familles / 18 opérations standard 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`. La compliance standard KSP reste **18/18** pour `SolanaStandard`.
@@ -488,16 +491,16 @@ program
root root
signature signature
slot slot
slotsUpdates
transaction 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 ```text
block block
slotsUpdates
vote vote
``` ```
@@ -813,7 +816,7 @@ Prévoir :
```text ```text
public API canary SolanaStandardWsSession public API canary SolanaStandardWsSession
public API canary HeliusLaserStreamWsSession public API canary HeliusLaserStreamWsSession
Helius facade sans block/slotsUpdates/vote Helius facade sans block/vote ; slotsUpdates présent et unstable
Solana facade sans transactionSubscribe Solana facade sans transactionSubscribe
Helius facade sans escape hatch vers WsSession générique Helius facade sans escape hatch vers WsSession générique
WsSession historique standard toujours disponible WsSession historique standard toujours disponible
@@ -1396,3 +1399,65 @@ warnings 0
`pre.009` reste bloqué jusqu'au replay intégralement vert de `pre.008`. `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.

View File

@@ -1,9 +1,9 @@
<!-- file: docs/validation/011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md --> <!-- file: docs/validation/011-V0_2_8_HELIUS_LASERSTREAM_WEBSOCKET.md -->
<!-- version: 21 --> <!-- version: 22 -->
# Validation `0.2.8` — Helius LaserStream WebSocket # 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 ## 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 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 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.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 validation standard WS docs/validation/010-V0_2_7_ONCHAIN_WEBSOCKET.md
HTTP compliance docs/validation/007-V0_2_4_HTTP_FINAL_COMPLIANCE.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 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é | | `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 | | `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 | | `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 | | `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 | | `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 | | `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 | | Root | oui | oui | partagé standard |
| Signature | oui | oui | partagé standard | | Signature | oui | oui | partagé standard |
| Slot | oui | oui | partagé standard | | Slot | oui | oui | partagé standard |
| SlotsUpdates | oui | **non** | standard seulement | | SlotsUpdates | oui | oui | partagé standard |
| Vote | oui | **non** | standard seulement | | Vote | oui | **non** | standard seulement |
| Helius Transaction | **non** | oui | provider-specific | | 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.** 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.**