v0.2.8-pre.004

This commit is contained in:
2026-08-23 14:08:12 +02:00
parent b3363073c4
commit f2a3ec62aa
11 changed files with 335 additions and 75 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: crates/ksp-config-lib/USAGE.md -->
<!-- version: 8 -->
<!-- version: 9 -->
# Utilisation de ksp-config-lib
@@ -140,7 +140,9 @@ let ws_settings = transport.ws_settings();
let _ = (http_settings, ws_settings);
```
`std.transport` V2 conserve `retry` et `profiles[].endpoints[]` pour HTTP, ajoute `ws_defaults` et `profiles[].ws_endpoints[]`, puis exige actuellement `kind = "solana_standard"`. Un `ws_endpoints[].session` optionnel surcharge seulement les paramètres génériques de `WsSessionSettings`.
`std.transport` V2 conserve `retry` et `profiles[].endpoints[]` pour HTTP, ajoute `ws_defaults` et `profiles[].ws_endpoints[]`, puis accepte les protocoles WebSocket `kind = "solana_standard"` et `kind = "helius_laserstream"`. Ce second discriminateur appartient exclusivement au namespace WebSocket et mappe vers `WsProtocolKind::HeliusLaserStream`; il ne préfigure aucun contrat LaserStream gRPC. Un `ws_endpoints[].session` optionnel surcharge seulement les paramètres génériques de `WsSessionSettings`.
Pour Helius LaserStream WebSocket, l'exemple versionné compose l'URL provider avec `${KSP_SECRET_HELIUS_API_KEY:-replace-me}`. Config reste l'unique propriétaire de cette variable : il résout la clé dans l'URL effective, transmet au Transport un `WsEndpointUrl` utilisable au runtime et redige la valeur dans la projection sûre et les représentations `Debug`. Transport ne lit jamais directement l'environnement.
Le même schema enregistré conserve la lecture stricte du V1 historique : dans ce cas `http_settings()` reste disponible et `ws_settings()` retourne `None`. Aucun `WsTransportSettings` vide n'est inventé pour simuler l'absence de WebSocket.

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-config-lib/src/transport.rs
// version: 3
// version: 4
/// Effective standard on-chain Transport configuration resolved from Config and mapped to HTTP and optional WebSocket runtime contracts.
#[derive(Clone, Eq, PartialEq)]
@@ -443,6 +443,7 @@ fn map_ws_protocol_kind(
) -> ksp_core_lib::Result<ksp_onchain_transport_lib::WsProtocolKind> {
return match value {
"solana_standard" => std::result::Result::Ok(ksp_onchain_transport_lib::WsProtocolKind::SolanaStandard),
"helius_laserstream" => std::result::Result::Ok(ksp_onchain_transport_lib::WsProtocolKind::HeliusLaserStream),
_ => std::result::Result::Err(
effective_error(profile, "effective WebSocket protocol kind is unsupported")
.with_context("endpoint_name", endpoint_name)

View File

@@ -71,6 +71,14 @@
"notification_queue_capacity": 48,
"max_pending_requests": 24
}
},
{
"name": "fixture_helius_ws",
"enabled": true,
"provider": "helius",
"cluster": "mainnet-beta",
"kind": "helius_laserstream",
"url": "wss://mainnet.helius-rpc.com/?api-key=${KSP_SECRET_HELIUS_API_KEY:-fixture-helius-key}"
}
]
}

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-config-lib/unit_tests/transport.rs
// version: 4
// version: 5
#[test]
fn fixture_transport_profile_maps_complete_runtime_contract() {
@@ -44,7 +44,7 @@ fn fixture_transport_profile_maps_complete_runtime_contract() {
let ws = resolved.ws_settings();
assert!(ws.is_some(), "V2 fixture should expose WebSocket settings");
if let std::option::Option::Some(ws) = ws {
assert_eq!(ws.endpoints().len(), 1);
assert_eq!(ws.endpoints().len(), 2);
let endpoint = &ws.endpoints()[0];
assert_eq!(endpoint.name(), "fixture_private_ws");
assert_eq!(endpoint.provider().as_str(), "fixture-provider");
@@ -64,6 +64,13 @@ fn fixture_transport_profile_maps_complete_runtime_contract() {
assert_eq!(endpoint.session().max_message_size_bytes(), 33_554_432);
assert_eq!(endpoint.session().max_frame_size_bytes(), 8_388_608);
assert_eq!(endpoint.session().max_write_buffer_size_bytes(), 524_288);
let helius = &ws.endpoints()[1];
assert_eq!(helius.name(), "fixture_helius_ws");
assert_eq!(helius.provider().as_str(), "helius");
assert_eq!(helius.cluster().as_str(), "mainnet-beta");
assert_eq!(helius.protocol(), ksp_onchain_transport_lib::WsProtocolKind::HeliusLaserStream);
assert_eq!(helius.url().as_str(), "wss://mainnet.helius-rpc.com/?api-key=fixture-helius-key");
let _connect_future = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::connect(helius.clone());
}
}
@@ -259,6 +266,46 @@ fn secret_websocket_url_is_runtime_available_but_safe_projection_is_redacted() {
assert!(debug.contains(crate::REDACTED_CONFIG_VALUE));
}
#[test]
fn helius_laserstream_secret_api_key_maps_to_provider_protocol_and_safe_redaction() {
let engine = fixture_engine();
let engine = match engine {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let canary = "helius-api-key-canary";
let mut process = std::collections::BTreeMap::<String, String>::new();
process.insert("KSP_SECRET_HELIUS_API_KEY".to_owned(), canary.to_owned());
let environment = crate::ConfigEnvironment::from_maps(process, std::collections::BTreeMap::new());
let resolved = engine.load_resolved_transport_config(std::option::Option::None, &environment);
assert!(resolved.is_ok(), "Helius LaserStream WebSocket endpoint should map without exposing its API key: {resolved:?}");
let resolved = match resolved {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let ws = resolved.ws_settings();
assert!(ws.is_some(), "V2 fixture should expose WebSocket settings");
if let std::option::Option::Some(ws) = ws {
assert_eq!(ws.endpoints().len(), 2);
let endpoint = &ws.endpoints()[1];
assert_eq!(endpoint.provider().as_str(), "helius");
assert_eq!(endpoint.protocol(), ksp_onchain_transport_lib::WsProtocolKind::HeliusLaserStream);
assert_eq!(endpoint.url().as_str(), "wss://mainnet.helius-rpc.com/?api-key=helius-api-key-canary");
}
let safe_url = resolved.effective().safe_value().pointer("/ws_endpoints/1/url").and_then(serde_json::Value::as_str);
assert_eq!(safe_url, std::option::Option::Some(crate::REDACTED_CONFIG_VALUE));
let provenance = resolved.effective().provenance_at("/ws_endpoints/1/url");
assert!(provenance.is_some(), "Helius endpoint URL should retain secret environment provenance");
if let std::option::Option::Some(provenance) = provenance {
assert_eq!(provenance.len(), 1);
assert_eq!(provenance[0].environment_source(), std::option::Option::Some(crate::ConfigEnvironmentSource::Process));
assert_eq!(provenance[0].variable_name(), std::option::Option::Some("KSP_SECRET_HELIUS_API_KEY"));
}
let debug = format!("{resolved:?}");
assert!(!debug.contains(canary));
assert!(debug.contains(crate::REDACTED_CONFIG_VALUE));
}
#[test]
fn transport_secret_url_provenance_uses_process_and_process_beats_dotenv() {
let engine = fixture_engine();