v0.2.8-pre.004-fix.001

This commit is contained in:
2026-08-23 14:20:24 +02:00
parent f2a3ec62aa
commit 38fd62c256
8 changed files with 402 additions and 62 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: crates/ksp-config-lib/USAGE.md -->
<!-- version: 9 -->
<!-- version: 11 -->
# Utilisation de ksp-config-lib
@@ -142,7 +142,7 @@ let _ = (http_settings, ws_settings);
`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.
Pour Helius LaserStream WebSocket, l'exemple versionné couvre explicitement les deux réseaux supportés par ce contrat : mainnet via `wss://mainnet.helius-rpc.com/?api-key=${KSP_SECRET_HELIUS_API_KEY:-replace-me}` et devnet via `wss://devnet.helius-rpc.com/?api-key=${KSP_SECRET_HELIUS_API_KEY:-replace-me}`. Les deux réseaux vivent dans des profils Config distincts afin de ne pas mélanger des clusters dans un même profil logique. Config reste l'unique propriétaire de `KSP_SECRET_HELIUS_API_KEY` : il résout la clé dans l'URL effective et transmet au Transport un `WsEndpointUrl` utilisable au runtime. Dans `safe_value`, Config conserve les segments littéraux non sensibles d'une chaîne composée et remplace uniquement chaque segment secret par `********` ; les projections deviennent donc respectivement `wss://mainnet.helius-rpc.com/?api-key=********` et `wss://devnet.helius-rpc.com/?api-key=********`. Les représentations `Debug` restent sûres et n'exposent jamais la clé réelle. 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

@@ -81,6 +81,47 @@
"url": "wss://mainnet.helius-rpc.com/?api-key=${KSP_SECRET_HELIUS_API_KEY:-fixture-helius-key}"
}
]
},
{
"profile_id": "helius_devnet",
"endpoints": [
{
"name": "fixture_devnet_http",
"enabled": true,
"provider": "solana-public",
"cluster": "devnet",
"url": "https://api.devnet.solana.com",
"connect_timeout_ms": 750,
"request_timeout_ms": 2500,
"max_idle_connections_per_host": 3,
"roles": [
{
"role": "default",
"enabled": true,
"request_kinds": [
"*"
],
"priority": 7,
"limits": {
"requests_per_second": 9,
"burst_capacity": 12,
"max_concurrent_requests": 4,
"pause_after_rate_limit_ms": 650
}
}
]
}
],
"ws_endpoints": [
{
"name": "fixture_helius_devnet_ws",
"enabled": true,
"provider": "helius",
"cluster": "devnet",
"kind": "helius_laserstream",
"url": "wss://devnet.helius-rpc.com/?api-key=${KSP_SECRET_HELIUS_API_KEY:-fixture-helius-key}"
}
]
}
]
}

View File

@@ -267,7 +267,7 @@ fn secret_websocket_url_is_runtime_available_but_safe_projection_is_redacted() {
}
#[test]
fn helius_laserstream_secret_api_key_maps_to_provider_protocol_and_safe_redaction() {
fn helius_laserstream_mainnet_and_devnet_api_key_map_to_protocol_and_safe_redaction() {
let engine = fixture_engine();
let engine = match engine {
std::result::Result::Ok(value) => value,
@@ -277,33 +277,63 @@ fn helius_laserstream_secret_api_key_maps_to_provider_protocol_and_safe_redactio
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 {
let mainnet = engine.load_resolved_transport_config(std::option::Option::None, &environment);
assert!(mainnet.is_ok(), "Helius mainnet WebSocket endpoint should map without exposing its API key: {mainnet:?}");
let mainnet = match mainnet {
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 {
let mainnet_ws = mainnet.ws_settings();
assert!(mainnet_ws.is_some(), "V2 fixture should expose mainnet WebSocket settings");
if let std::option::Option::Some(ws) = mainnet_ws {
assert_eq!(ws.endpoints().len(), 2);
let endpoint = &ws.endpoints()[1];
assert_eq!(endpoint.provider().as_str(), "helius");
assert_eq!(endpoint.cluster().as_str(), "mainnet-beta");
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 {
let mainnet_safe_url = mainnet.effective().safe_value().pointer("/ws_endpoints/1/url").and_then(serde_json::Value::as_str);
assert_eq!(mainnet_safe_url, std::option::Option::Some("wss://mainnet.helius-rpc.com/?api-key=********"));
let mainnet_provenance = mainnet.effective().provenance_at("/ws_endpoints/1/url");
assert!(mainnet_provenance.is_some(), "Helius mainnet endpoint URL should retain secret environment provenance");
if let std::option::Option::Some(provenance) = mainnet_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));
let devnet = engine.load_resolved_transport_config(std::option::Option::Some("helius_devnet"), &environment);
assert!(devnet.is_ok(), "Helius devnet WebSocket endpoint should map without exposing its API key: {devnet:?}");
let devnet = match devnet {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let devnet_ws = devnet.ws_settings();
assert!(devnet_ws.is_some(), "V2 fixture should expose devnet WebSocket settings");
if let std::option::Option::Some(ws) = devnet_ws {
assert_eq!(ws.endpoints().len(), 1);
let endpoint = &ws.endpoints()[0];
assert_eq!(endpoint.provider().as_str(), "helius");
assert_eq!(endpoint.cluster().as_str(), "devnet");
assert_eq!(endpoint.protocol(), ksp_onchain_transport_lib::WsProtocolKind::HeliusLaserStream);
assert_eq!(endpoint.url().as_str(), "wss://devnet.helius-rpc.com/?api-key=helius-api-key-canary");
let _connect_future = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::connect(endpoint.clone());
}
let devnet_safe_url = devnet.effective().safe_value().pointer("/ws_endpoints/0/url").and_then(serde_json::Value::as_str);
assert_eq!(devnet_safe_url, std::option::Option::Some("wss://devnet.helius-rpc.com/?api-key=********"));
let devnet_provenance = devnet.effective().provenance_at("/ws_endpoints/0/url");
assert!(devnet_provenance.is_some(), "Helius devnet endpoint URL should retain secret environment provenance");
if let std::option::Option::Some(provenance) = devnet_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 mainnet_debug = format!("{mainnet:?}");
let devnet_debug = format!("{devnet:?}");
assert!(!mainnet_debug.contains(canary));
assert!(!devnet_debug.contains(canary));
assert!(mainnet_debug.contains(crate::REDACTED_CONFIG_VALUE));
assert!(devnet_debug.contains(crate::REDACTED_CONFIG_VALUE));
}
#[test]