v0.3.15-pre.002
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
# file: Cargo.toml
|
||||
# version: 594
|
||||
# version: 595
|
||||
|
||||
[workspace]
|
||||
resolver = "3"
|
||||
members = ["crates/ksp-app-backfill-desk", "crates/ksp-app-config-desk", "crates/ksp-app-solprices-desk", "crates/ksp-app-store-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-interface-lib", "crates/ksp-job-api", "crates/ksp-job-backfill-lib", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-program-api", "crates/ksp-raw-transaction-lib", "crates/ksp-store-api", "crates/ksp-store-lib", "crates/ksp-store-postgres-lib", "crates/ksp-wallet-lib", "crates/ksp-worker-api", "crates/ksp-worker-raw-transaction-ingest-lib"]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.3.15-pre.1"
|
||||
version = "0.3.15-pre.2"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: crates/ksp-onchain-transport-lib/USAGE.md -->
|
||||
<!-- version: 26 -->
|
||||
<!-- version: 27 -->
|
||||
|
||||
# Utilisation de `ksp-onchain-transport-lib`
|
||||
|
||||
@@ -82,7 +82,14 @@ let endpoint = ksp_onchain_transport_lib::WsEndpointSettings::new(
|
||||
ksp_onchain_transport_lib::WsProtocolKind::SolanaStandard,
|
||||
ws_url,
|
||||
ksp_onchain_transport_lib::WsSessionSettings::default(),
|
||||
);
|
||||
)
|
||||
.with_subscription_capabilities(vec![ksp_onchain_transport_lib::WsSubscriptionKind::Logs]);
|
||||
if !endpoint.supports_subscription(ksp_onchain_transport_lib::WsSubscriptionKind::Logs) {
|
||||
return Err(ksp_core_lib::Error::new(
|
||||
ksp_onchain_transport_lib::ERROR_CODE_INVALID_SETTINGS,
|
||||
"required WebSocket subscription capability is not declared",
|
||||
));
|
||||
}
|
||||
let session = match ksp_onchain_transport_lib::WsSession::connect(endpoint).await {
|
||||
Ok(value) => value,
|
||||
Err(error) => return Err(error),
|
||||
@@ -90,6 +97,8 @@ let session = match ksp_onchain_transport_lib::WsSession::connect(endpoint).awai
|
||||
let snapshot = session.snapshot();
|
||||
```
|
||||
|
||||
`with_subscription_capabilities(...)` porte une preuve explicite et typed des familles déclarées pour cet endpoint. Une déclaration vide, dupliquée ou incompatible avec `WsProtocolKind` est rejetée par `WsTransportSettings::validate()`. Un endpoint construit sans déclaration reste valide pour compatibilité, mais `subscription_capabilities()` retourne `None` et `supports_subscription(...)` retourne `false` : l'absence de déclaration n'est jamais une preuve implicite de support.
|
||||
|
||||
Deux appels `WsSession::connect` avec le même endpoint créent volontairement deux connexions physiques distinctes. Il n'existe encore aucun pool de sessions automatique.
|
||||
|
||||
Le socket brut et la primitive JSON-RPC générique ne sont pas publics. Le moteur générique de subscription typed reste `pub(crate)` ; il ne constitue donc pas une escape hatch provider-specific.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-onchain-transport-lib/src/ws_settings.rs
|
||||
// version: 4
|
||||
// version: 5
|
||||
|
||||
const DEFAULT_WS_CLOSE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(5);
|
||||
const DEFAULT_WS_COMMAND_QUEUE_CAPACITY: usize = 128;
|
||||
@@ -401,6 +401,7 @@ pub struct WsEndpointSettings {
|
||||
provider: crate::WsProviderName,
|
||||
cluster: crate::WsClusterName,
|
||||
protocol: crate::WsProtocolKind,
|
||||
subscription_capabilities: std::option::Option<std::vec::Vec<crate::WsSubscriptionKind>>,
|
||||
url: crate::WsEndpointUrl,
|
||||
session: crate::WsSessionSettings,
|
||||
}
|
||||
@@ -417,7 +418,42 @@ impl WsEndpointSettings {
|
||||
url: crate::WsEndpointUrl,
|
||||
session: crate::WsSessionSettings,
|
||||
) -> Self {
|
||||
return Self { name: name.into(), enabled, provider, cluster, protocol, url, session };
|
||||
return Self {
|
||||
name: name.into(),
|
||||
enabled,
|
||||
provider,
|
||||
cluster,
|
||||
protocol,
|
||||
subscription_capabilities: std::option::Option::None,
|
||||
url,
|
||||
session,
|
||||
};
|
||||
}
|
||||
|
||||
/// Declares the exact WebSocket subscription families supported by this endpoint.
|
||||
///
|
||||
/// An endpoint created without this builder remains valid for backward compatibility, but its capabilities are considered undeclared and therefore
|
||||
/// never constitute positive support evidence for a subscription family. Validation rejects an explicitly declared empty set, duplicates and
|
||||
/// capabilities that cannot belong to the selected protocol surface.
|
||||
#[must_use]
|
||||
pub fn with_subscription_capabilities(mut self, capabilities: std::vec::Vec<crate::WsSubscriptionKind>) -> Self {
|
||||
self.subscription_capabilities = std::option::Option::Some(capabilities);
|
||||
return self;
|
||||
}
|
||||
|
||||
/// Returns the explicitly declared WebSocket subscription capabilities, or `None` when the endpoint still uses the legacy undeclared form.
|
||||
#[must_use]
|
||||
pub fn subscription_capabilities(&self) -> std::option::Option<&[crate::WsSubscriptionKind]> {
|
||||
return self.subscription_capabilities.as_deref();
|
||||
}
|
||||
|
||||
/// Returns whether this endpoint explicitly declares support for one WebSocket subscription family.
|
||||
///
|
||||
/// Undeclared legacy capability state is fail-closed and therefore returns `false`.
|
||||
#[must_use]
|
||||
pub fn supports_subscription(&self, kind: crate::WsSubscriptionKind) -> bool {
|
||||
return ws_protocol_supports_subscription(self.protocol, kind)
|
||||
&& self.subscription_capabilities().is_some_and(|capabilities| return capabilities.contains(&kind));
|
||||
}
|
||||
|
||||
/// Returns the logical endpoint name.
|
||||
@@ -532,6 +568,32 @@ fn validate_ws_endpoint(endpoint: &crate::WsEndpointSettings, endpoint_index: us
|
||||
if let std::result::Result::Err(error) = validate_ws_descriptor(endpoint.cluster().as_str(), cluster_field.as_str()) {
|
||||
return std::result::Result::Err(error);
|
||||
}
|
||||
if let std::result::Result::Some(capabilities) = endpoint.subscription_capabilities() {
|
||||
if capabilities.is_empty() {
|
||||
return ws_invalid_settings(
|
||||
"explicit WebSocket subscription capabilities must not be empty",
|
||||
format!("ws_endpoints[{endpoint_index}].subscription_capabilities").as_str(),
|
||||
);
|
||||
}
|
||||
for (capability_index, capability) in capabilities.iter().copied().enumerate() {
|
||||
let field = format!("ws_endpoints[{endpoint_index}].subscription_capabilities[{capability_index}]");
|
||||
if !ws_protocol_supports_subscription(endpoint.protocol(), capability) {
|
||||
return std::result::Result::Err(
|
||||
ksp_core_lib::Error::new(crate::ERROR_CODE_INVALID_SETTINGS, "WebSocket subscription capability is incompatible with endpoint protocol")
|
||||
.with_context("field", field)
|
||||
.with_context("subscription_kind", capability.as_str())
|
||||
.with_context("protocol", endpoint.protocol().as_str()),
|
||||
);
|
||||
}
|
||||
if capabilities[..capability_index].contains(&capability) {
|
||||
return std::result::Result::Err(
|
||||
ksp_core_lib::Error::new(crate::ERROR_CODE_INVALID_SETTINGS, "WebSocket subscription capabilities must be unique")
|
||||
.with_context("field", field)
|
||||
.with_context("subscription_kind", capability.as_str()),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let std::result::Result::Err(error) = endpoint.session().validate() {
|
||||
return std::result::Result::Err(error);
|
||||
}
|
||||
@@ -547,6 +609,34 @@ fn validate_ws_endpoint(endpoint: &crate::WsEndpointSettings, endpoint_index: us
|
||||
return std::result::Result::Ok(());
|
||||
}
|
||||
|
||||
const fn ws_protocol_supports_subscription(protocol: crate::WsProtocolKind, kind: crate::WsSubscriptionKind) -> bool {
|
||||
return match protocol {
|
||||
crate::WsProtocolKind::SolanaStandard => matches!(
|
||||
kind,
|
||||
crate::WsSubscriptionKind::Account
|
||||
| crate::WsSubscriptionKind::Block
|
||||
| crate::WsSubscriptionKind::Logs
|
||||
| crate::WsSubscriptionKind::Program
|
||||
| crate::WsSubscriptionKind::Root
|
||||
| crate::WsSubscriptionKind::Signature
|
||||
| crate::WsSubscriptionKind::Slot
|
||||
| crate::WsSubscriptionKind::SlotsUpdates
|
||||
| crate::WsSubscriptionKind::Vote
|
||||
),
|
||||
crate::WsProtocolKind::HeliusLaserStream => matches!(
|
||||
kind,
|
||||
crate::WsSubscriptionKind::Account
|
||||
| crate::WsSubscriptionKind::Logs
|
||||
| crate::WsSubscriptionKind::Program
|
||||
| crate::WsSubscriptionKind::Root
|
||||
| crate::WsSubscriptionKind::Signature
|
||||
| crate::WsSubscriptionKind::Slot
|
||||
| crate::WsSubscriptionKind::SlotsUpdates
|
||||
| crate::WsSubscriptionKind::HeliusTransaction
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
fn validate_ws_descriptor(value: &str, field: &str) -> ksp_core_lib::Result<()> {
|
||||
if value.trim().is_empty() {
|
||||
return ws_invalid_settings("WebSocket transport descriptor must not be empty", field);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-onchain-transport-lib/tests/public_api.rs
|
||||
// version: 54
|
||||
// version: 55
|
||||
|
||||
//! Integration tests for the public `ksp-onchain-transport-lib` consumer contract.
|
||||
|
||||
@@ -1057,3 +1057,21 @@ fn public_v0_3_13_pre_002_yellowstone_subscribe_identity_is_opaque_and_available
|
||||
assert!(!debug.contains("bytes:"));
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn public_v0_3_15_pre_002_websocket_endpoint_capability_contract_is_available_from_crate_root() {
|
||||
let endpoint = ksp_onchain_transport_lib::WsEndpointSettings::new(
|
||||
"typed_public",
|
||||
true,
|
||||
ksp_onchain_transport_lib::WsProviderName::new("public"),
|
||||
ksp_onchain_transport_lib::WsClusterName::new("devnet"),
|
||||
ksp_onchain_transport_lib::WsProtocolKind::SolanaStandard,
|
||||
ksp_onchain_transport_lib::WsEndpointUrl::parse("wss://api.devnet.solana.com").expect("public WebSocket URL fixture must parse"),
|
||||
ksp_onchain_transport_lib::WsSessionSettings::default(),
|
||||
)
|
||||
.with_subscription_capabilities(std::vec![ksp_onchain_transport_lib::WsSubscriptionKind::Logs, ksp_onchain_transport_lib::WsSubscriptionKind::Block,]);
|
||||
assert!(endpoint.supports_subscription(ksp_onchain_transport_lib::WsSubscriptionKind::Logs));
|
||||
assert!(endpoint.supports_subscription(ksp_onchain_transport_lib::WsSubscriptionKind::Block));
|
||||
assert!(!endpoint.supports_subscription(ksp_onchain_transport_lib::WsSubscriptionKind::HeliusTransaction));
|
||||
assert_eq!(endpoint.subscription_capabilities().map(|capabilities| return capabilities.len()), std::option::Option::Some(2));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-onchain-transport-lib/tests/release_completeness.rs
|
||||
// version: 46
|
||||
// version: 47
|
||||
|
||||
//! Release-level completeness canaries for staged HTTP and WebSocket Transport coverage.
|
||||
|
||||
@@ -1399,3 +1399,16 @@ fn release_v0_3_14_pre_004_native_replay_evidence_never_conflates_attempt_delive
|
||||
assert!(!stream_source.contains("replay_coverage_proven_count"));
|
||||
return;
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn release_v0_3_15_pre_002_websocket_capabilities_are_endpoint_declared_typed_and_protocol_bounded() {
|
||||
let settings_source = include_str!("../src/ws_settings.rs");
|
||||
assert!(settings_source.contains("subscription_capabilities: std::option::Option<std::vec::Vec<crate::WsSubscriptionKind>>"));
|
||||
assert!(settings_source.contains("pub fn with_subscription_capabilities"));
|
||||
assert!(settings_source.contains("pub fn subscription_capabilities"));
|
||||
assert!(settings_source.contains("pub fn supports_subscription"));
|
||||
assert!(settings_source.contains("crate::WsProtocolKind::SolanaStandard => matches!("));
|
||||
assert!(settings_source.contains("crate::WsProtocolKind::HeliusLaserStream => matches!("));
|
||||
assert!(!settings_source.contains("provider().as_str() == \"helius\""));
|
||||
assert!(!settings_source.contains("provider().as_str() == \"publicnode\""));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-onchain-transport-lib/unit_tests/ws_settings.rs
|
||||
// version: 2
|
||||
// version: 3
|
||||
|
||||
fn valid_endpoint(name: &str, url_text: &str) -> crate::WsEndpointSettings {
|
||||
return crate::WsEndpointSettings::new(
|
||||
@@ -148,3 +148,80 @@ fn websocket_transport_settings_debug_never_exposes_endpoint_url() {
|
||||
assert!(!rendered.contains("provider.invalid"));
|
||||
assert!(!rendered.contains("password"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_15_pre_002_undeclared_websocket_capabilities_fail_closed_without_breaking_legacy_settings() {
|
||||
let endpoint = valid_endpoint("legacy", "wss://legacy.invalid/ws");
|
||||
assert_eq!(endpoint.subscription_capabilities(), std::option::Option::None);
|
||||
assert!(!endpoint.supports_subscription(crate::WsSubscriptionKind::Logs));
|
||||
assert!(!endpoint.supports_subscription(crate::WsSubscriptionKind::Block));
|
||||
let settings = crate::WsTransportSettings::new(std::vec![endpoint]);
|
||||
assert!(settings.validate().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_15_pre_002_standard_endpoint_declares_exact_typed_subscription_capabilities() {
|
||||
let endpoint = valid_endpoint("typed", "wss://typed.invalid/ws")
|
||||
.with_subscription_capabilities(std::vec![crate::WsSubscriptionKind::Logs, crate::WsSubscriptionKind::Block,]);
|
||||
assert_eq!(
|
||||
endpoint.subscription_capabilities(),
|
||||
std::option::Option::Some([crate::WsSubscriptionKind::Logs, crate::WsSubscriptionKind::Block].as_slice())
|
||||
);
|
||||
assert!(endpoint.supports_subscription(crate::WsSubscriptionKind::Logs));
|
||||
assert!(endpoint.supports_subscription(crate::WsSubscriptionKind::Block));
|
||||
assert!(!endpoint.supports_subscription(crate::WsSubscriptionKind::Vote));
|
||||
assert!(!endpoint.supports_subscription(crate::WsSubscriptionKind::HeliusTransaction));
|
||||
let settings = crate::WsTransportSettings::new(std::vec![endpoint]);
|
||||
assert!(settings.validate().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_15_pre_002_explicit_capability_set_rejects_empty_and_duplicate_entries() {
|
||||
let empty = valid_endpoint("empty", "wss://empty.invalid/ws").with_subscription_capabilities(std::vec![]);
|
||||
let empty_error = crate::WsTransportSettings::new(std::vec![empty]).validate().expect_err("explicit empty capabilities must fail");
|
||||
assert_eq!(empty_error.code(), crate::ERROR_CODE_INVALID_SETTINGS);
|
||||
let duplicate = valid_endpoint("duplicate_caps", "wss://duplicate.invalid/ws")
|
||||
.with_subscription_capabilities(std::vec![crate::WsSubscriptionKind::Logs, crate::WsSubscriptionKind::Logs,]);
|
||||
let duplicate_error = crate::WsTransportSettings::new(std::vec![duplicate]).validate().expect_err("duplicate capabilities must fail");
|
||||
assert_eq!(duplicate_error.code(), crate::ERROR_CODE_INVALID_SETTINGS);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_15_pre_002_capabilities_must_belong_to_selected_protocol_surface() {
|
||||
let standard =
|
||||
valid_endpoint("standard_bad", "wss://standard.invalid/ws").with_subscription_capabilities(std::vec![crate::WsSubscriptionKind::HeliusTransaction]);
|
||||
assert!(!standard.supports_subscription(crate::WsSubscriptionKind::HeliusTransaction));
|
||||
let standard_error =
|
||||
crate::WsTransportSettings::new(std::vec![standard]).validate().expect_err("standard protocol must reject Helius transaction capability");
|
||||
assert_eq!(standard_error.code(), crate::ERROR_CODE_INVALID_SETTINGS);
|
||||
let helius_block = crate::WsEndpointSettings::new(
|
||||
"helius_block",
|
||||
true,
|
||||
crate::WsProviderName::new("helius"),
|
||||
crate::WsClusterName::new("mainnet"),
|
||||
crate::WsProtocolKind::HeliusLaserStream,
|
||||
crate::WsEndpointUrl::parse("wss://helius.invalid/ws").expect("test URL must parse"),
|
||||
crate::WsSessionSettings::default(),
|
||||
)
|
||||
.with_subscription_capabilities(std::vec![crate::WsSubscriptionKind::Block]);
|
||||
assert!(!helius_block.supports_subscription(crate::WsSubscriptionKind::Block));
|
||||
let helius_block_error =
|
||||
crate::WsTransportSettings::new(std::vec![helius_block]).validate().expect_err("Helius protocol must reject unsupported block capability");
|
||||
assert_eq!(helius_block_error.code(), crate::ERROR_CODE_INVALID_SETTINGS);
|
||||
let helius_supported = crate::WsEndpointSettings::new(
|
||||
"helius_supported",
|
||||
true,
|
||||
crate::WsProviderName::new("helius"),
|
||||
crate::WsClusterName::new("mainnet"),
|
||||
crate::WsProtocolKind::HeliusLaserStream,
|
||||
crate::WsEndpointUrl::parse("wss://helius-supported.invalid/ws").expect("test URL must parse"),
|
||||
crate::WsSessionSettings::default(),
|
||||
)
|
||||
.with_subscription_capabilities(std::vec![crate::WsSubscriptionKind::Logs, crate::WsSubscriptionKind::HeliusTransaction]);
|
||||
assert!(helius_supported.supports_subscription(crate::WsSubscriptionKind::Logs));
|
||||
assert!(helius_supported.supports_subscription(crate::WsSubscriptionKind::HeliusTransaction));
|
||||
assert!(!helius_supported.supports_subscription(crate::WsSubscriptionKind::Block));
|
||||
assert!(!helius_supported.supports_subscription(crate::WsSubscriptionKind::Vote));
|
||||
let helius_settings = crate::WsTransportSettings::new(std::vec![helius_supported]);
|
||||
assert!(helius_settings.validate().is_ok());
|
||||
}
|
||||
|
||||
316
deltas/0.3.15/pre.002.md
Normal file
316
deltas/0.3.15/pre.002.md
Normal file
@@ -0,0 +1,316 @@
|
||||
<!-- file: deltas/0.3.15/pre.002.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Delta `0.3.15-pre.002` — capability WebSocket typed par endpoint
|
||||
|
||||
## Base requise
|
||||
|
||||
```text
|
||||
0.3.15-pre.001-fix.001 appliquée
|
||||
workspace.package.version = 0.3.15-pre.1
|
||||
deltas/0.3.15/pre.001-fix.001.md présent
|
||||
```
|
||||
|
||||
## Gate de la base
|
||||
|
||||
Le gate opérateur communiqué après `pre.001-fix.001` est propre :
|
||||
|
||||
```text
|
||||
cargo fmt --all -- --check : PASS
|
||||
General Rust rule audit : clean
|
||||
Rust export completeness audit : 0 candidate(s)
|
||||
KSP workspace Rust rule audit : clean
|
||||
Markdown table audit : clean (318 table(s), 185 file(s))
|
||||
cargo check --workspace : PASS
|
||||
```
|
||||
|
||||
Ce gate qualifie la base directe de `pre.002` avant toute modification Transport.
|
||||
|
||||
## Objectif
|
||||
|
||||
Implémenter strictement la tranche `pre.002` du plan `036` :
|
||||
|
||||
```text
|
||||
ajouter une déclaration WebSocket typed exacte par subscription au niveau Transport
|
||||
réutiliser WsSubscriptionKind comme identité de capability
|
||||
conserver la compatibilité des WsEndpointSettings existants
|
||||
faire de l'absence de déclaration un état fail-closed pour toute preuve de capability
|
||||
valider les déclarations explicites sans inférence par provider
|
||||
borner les capabilities à la surface réellement portée par WsProtocolKind
|
||||
exposer la preuve via la façade crate-root déjà existante
|
||||
documenter l'usage version-neutral
|
||||
ajouter les tests unitaires/public API/release completeness
|
||||
```
|
||||
|
||||
Cette tranche ne mappe encore aucun champ Config et ne modifie aucun constructeur Worker. Ces responsabilités restent respectivement `pre.003` et `pre.004`.
|
||||
|
||||
## Contrat `WsEndpointSettings`
|
||||
|
||||
`WsEndpointSettings` conserve son constructeur historique `new(...)` sans argument supplémentaire afin de ne pas forcer artificiellement Config à évoluer dans la même tranche.
|
||||
|
||||
Un endpoint possède désormais l'état privé :
|
||||
|
||||
```text
|
||||
subscription_capabilities: Option<Vec<WsSubscriptionKind>>
|
||||
```
|
||||
|
||||
Sémantique :
|
||||
|
||||
```text
|
||||
None = capabilities non déclarées ; compatibilité legacy ; aucune preuve positive
|
||||
Some(vec) = déclaration explicite des seules familles annoncées pour cet endpoint
|
||||
```
|
||||
|
||||
Le builder public :
|
||||
|
||||
```text
|
||||
with_subscription_capabilities(Vec<WsSubscriptionKind>)
|
||||
```
|
||||
|
||||
permet d'attacher la déclaration exacte sans introduire de second enum ni de second registre de méthodes.
|
||||
|
||||
Les getters publics :
|
||||
|
||||
```text
|
||||
subscription_capabilities() -> Option<&[WsSubscriptionKind]>
|
||||
supports_subscription(WsSubscriptionKind) -> bool
|
||||
```
|
||||
|
||||
restent accessibles via `WsEndpointSettings`, déjà réexporté depuis la racine de crate.
|
||||
|
||||
`supports_subscription(...)` est volontairement fail-closed :
|
||||
|
||||
```text
|
||||
capability non déclarée -> false
|
||||
capability incompatible avec le protocole -> false même avant validate()
|
||||
capability explicitement déclarée et protocol-compatible -> true
|
||||
```
|
||||
|
||||
## Validation Transport
|
||||
|
||||
`WsTransportSettings::validate()` rejette maintenant une déclaration explicite :
|
||||
|
||||
```text
|
||||
vide
|
||||
dupliquée
|
||||
incompatible avec le WsProtocolKind de l'endpoint
|
||||
```
|
||||
|
||||
Les erreurs réutilisent `ERROR_CODE_INVALID_SETTINGS` et n'exposent que :
|
||||
|
||||
```text
|
||||
field
|
||||
subscription_kind stable
|
||||
protocol stable
|
||||
```
|
||||
|
||||
Aucune URL, credential, source key ou payload n'est ajouté aux contextes d'erreur.
|
||||
|
||||
## Partition protocolaire
|
||||
|
||||
La validation est protocol-owned et ne branche jamais sur `provider`.
|
||||
|
||||
`SolanaStandard` admet les neuf familles standard actuelles :
|
||||
|
||||
```text
|
||||
Account
|
||||
Block
|
||||
Logs
|
||||
Program
|
||||
Root
|
||||
Signature
|
||||
Slot
|
||||
SlotsUpdates
|
||||
Vote
|
||||
```
|
||||
|
||||
`HeliusLaserStream` admet la surface déjà portée par sa façade typed :
|
||||
|
||||
```text
|
||||
Account
|
||||
Logs
|
||||
Program
|
||||
Root
|
||||
Signature
|
||||
Slot
|
||||
SlotsUpdates
|
||||
HeliusTransaction
|
||||
```
|
||||
|
||||
Il n'admet donc pas `Block` ni `Vote`.
|
||||
|
||||
Cette partition est écrite positivement. Une future variante de `WsSubscriptionKind` ne devient donc pas implicitement compatible avec un protocole existant.
|
||||
|
||||
## Absence d'inférence provider
|
||||
|
||||
Aucune règle du type :
|
||||
|
||||
```text
|
||||
provider == helius -> capability X
|
||||
provider == publicnode -> capability Y
|
||||
```
|
||||
|
||||
n'est ajoutée.
|
||||
|
||||
Le provider reste un descriptor ouvert. La preuve de capability est attachée explicitement à l'endpoint et devra être alimentée par Config en `pre.003`.
|
||||
|
||||
## Documentation d'usage
|
||||
|
||||
`ksp-onchain-transport-lib/USAGE.md` montre maintenant la déclaration typed sur un endpoint standard et documente les deux propriétés importantes :
|
||||
|
||||
```text
|
||||
absence de déclaration != support implicite
|
||||
validation explicite des listes vide/dupliquée/protocol-incompatible
|
||||
```
|
||||
|
||||
Le guide reste version-neutral et ne sert pas de journal de gate.
|
||||
|
||||
## Tests ajoutés
|
||||
|
||||
Unitaires `ws_settings` :
|
||||
|
||||
```text
|
||||
legacy undeclared reste structurally valide mais fail-closed
|
||||
capabilities standard exactes et typed
|
||||
liste explicite vide rejetée
|
||||
capability dupliquée rejetée
|
||||
HeliusTransaction rejeté sous SolanaStandard
|
||||
Block rejeté sous HeliusLaserStream
|
||||
Logs + HeliusTransaction admis sous HeliusLaserStream
|
||||
Block/Vote restent non supportés sous HeliusLaserStream
|
||||
supports_subscription reste false sur capability protocol-incompatible avant validate
|
||||
```
|
||||
|
||||
Public API :
|
||||
|
||||
```text
|
||||
builder/getter/support check consommables depuis la crate root
|
||||
aucun nouveau module public requis
|
||||
```
|
||||
|
||||
Release completeness :
|
||||
|
||||
```text
|
||||
état capability porté par WsEndpointSettings
|
||||
WsSubscriptionKind réutilisé directement
|
||||
partition protocolaire présente
|
||||
absence de branche provider-name pour attribuer des capabilities
|
||||
```
|
||||
|
||||
## Fichiers ajoutés
|
||||
|
||||
```text
|
||||
deltas/0.3.15/pre.002.md
|
||||
```
|
||||
|
||||
## Fichiers modifiés
|
||||
|
||||
```text
|
||||
Cargo.toml
|
||||
crates/ksp-onchain-transport-lib/USAGE.md
|
||||
crates/ksp-onchain-transport-lib/src/ws_settings.rs
|
||||
crates/ksp-onchain-transport-lib/unit_tests/ws_settings.rs
|
||||
crates/ksp-onchain-transport-lib/tests/public_api.rs
|
||||
crates/ksp-onchain-transport-lib/tests/release_completeness.rs
|
||||
```
|
||||
|
||||
## Fichiers supprimés
|
||||
|
||||
```text
|
||||
aucun
|
||||
```
|
||||
|
||||
## Version Cargo
|
||||
|
||||
Cette tranche modifie le contrat/runtime settings Transport. Conformément à la policy de versioning :
|
||||
|
||||
```text
|
||||
header Cargo.toml : 594 -> 595
|
||||
workspace.package.version : 0.3.15-pre.1 -> 0.3.15-pre.2
|
||||
```
|
||||
|
||||
Versions des fichiers modifiés :
|
||||
|
||||
```text
|
||||
ksp-onchain-transport-lib/USAGE.md : 26 -> 27
|
||||
ksp-onchain-transport-lib/src/ws_settings.rs : 4 -> 5
|
||||
ksp-onchain-transport-lib/unit_tests/ws_settings.rs : 2 -> 3
|
||||
ksp-onchain-transport-lib/tests/public_api.rs : 54 -> 55
|
||||
ksp-onchain-transport-lib/tests/release_completeness.rs : 46 -> 47
|
||||
```
|
||||
|
||||
## Frontières préservées
|
||||
|
||||
```text
|
||||
aucun changement Config/schema/composite
|
||||
aucun changement Worker
|
||||
aucun changement Store
|
||||
aucune crate Desk ajoutée
|
||||
aucun Start/Stop Worker applicatif
|
||||
aucun I/O réseau supplémentaire
|
||||
aucune nouvelle dépendance
|
||||
aucune nouvelle feature
|
||||
aucun provider SDK
|
||||
aucune inférence capability par provider name
|
||||
aucun nouveau type public nécessitant une réexportation lib.rs
|
||||
```
|
||||
|
||||
## Audits statiques d'assemblage
|
||||
|
||||
Après modification et ajout du delta :
|
||||
|
||||
```text
|
||||
General Rust rule audit : clean
|
||||
Rust export completeness audit : 0 candidate(s)
|
||||
KSP workspace Rust rule audit : clean
|
||||
Markdown table audit : clean (318 table(s), 186 file(s))
|
||||
```
|
||||
|
||||
## Gates Cargo non exécutés dans l'environnement d'assemblage
|
||||
|
||||
L'environnement d'assemblage ne fournit pas Cargo/Rustfmt. Aucun faux PASS n'est revendiqué pour :
|
||||
|
||||
```text
|
||||
cargo fmt --all -- --check
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
cargo test -p ksp-onchain-transport-lib --all-targets --all-features
|
||||
```
|
||||
|
||||
Ils doivent être exécutés par l'opérateur après application du delta.
|
||||
|
||||
## Archive d'échange
|
||||
|
||||
Livraison attendue selon `VER-ARCHIVE-004` :
|
||||
|
||||
```text
|
||||
ksp-general-0.3.15-pre.002.zip
|
||||
```
|
||||
|
||||
Contenu exact :
|
||||
|
||||
```text
|
||||
Cargo.toml
|
||||
crates/ksp-onchain-transport-lib/USAGE.md
|
||||
crates/ksp-onchain-transport-lib/src/ws_settings.rs
|
||||
crates/ksp-onchain-transport-lib/unit_tests/ws_settings.rs
|
||||
crates/ksp-onchain-transport-lib/tests/public_api.rs
|
||||
crates/ksp-onchain-transport-lib/tests/release_completeness.rs
|
||||
deltas/0.3.15/pre.002.md
|
||||
```
|
||||
|
||||
Aucun fichier stable inchangé, lockfile, cache, sortie de build ou artefact temporaire n'est inclus.
|
||||
|
||||
## Gate opérateur après application
|
||||
|
||||
```bash
|
||||
cargo fmt --all
|
||||
cargo fmt --all -- --check
|
||||
python3 scripts/audit_rust_workspace_rules.py
|
||||
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.3.15
|
||||
cargo check --workspace
|
||||
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||
cargo test -p ksp-onchain-transport-lib --all-targets --all-features
|
||||
```
|
||||
|
||||
Si ce gate est propre, `pre.003` mappe cette capability depuis Config et prépare le composite/profils Raw Transaction Ingest Desk, sans frontend.
|
||||
Reference in New Issue
Block a user