v0.3.15-pre.006-fix.001

This commit is contained in:
2026-09-13 15:47:32 +02:00
parent 0a8ce6e5f9
commit f3ed86e54c
19 changed files with 676 additions and 341 deletions

View File

@@ -1,5 +1,5 @@
<!-- file: crates/ksp-app-raw-transaction-ingest-desk/README.md -->
<!-- version: 2 -->
<!-- version: 3 -->
# `ksp-app-raw-transaction-ingest-desk`
@@ -27,6 +27,8 @@ Worker -> acquisition continue et lifecycle d'exécution
L'inventaire de routes est calculé côté Rust à partir du composite Config validé et des settings Transport/Store résolus. Il ne lance aucun probe réseau et n'ouvre ni Store ni Worker.
Les profils applicatifs sont réseau-centriques (`devnet`, `mainnet`, `testnet`). Un profil peut agréger plusieurs profils Transport du même réseau : le provider reste une source de capability et ne devient jamais une identité réseau ni un choix de profil applicatif.
Le frontend ne reçoit aucune URL, credential, URI Store, metadata secrète, source key, handle runtime ou payload `RawTransaction`.
## Routes V1

View File

@@ -1,5 +1,5 @@
<!-- file: crates/ksp-app-raw-transaction-ingest-desk/USAGE.md -->
<!-- version: 2 -->
<!-- version: 3 -->
# Utilisation de `ksp-app-raw-transaction-ingest-desk`
@@ -17,7 +17,7 @@ Le runtime prépare les ressources Config nécessaires, charge le composite déd
## 2. Vue Routes
La vue Routes charge un inventaire déterministe construit côté Rust depuis le composite Config validé. Le sélecteur présente les profils logiques du composite et la vue projette, pour chaque route V1 :
La vue Routes charge un inventaire déterministe construit côté Rust depuis le composite Config validé. Le sélecteur présente les réseaux logiques `devnet`, `mainnet` et `testnet`, jamais les providers. Chaque réseau agrège les profils Transport same-network configurés pour ses capabilities. La vue projette, pour chaque route V1 :
```text
route_id
@@ -31,7 +31,7 @@ génération d'inventaire
`Configured` signifie uniquement que toutes les requirements Config nécessaires à la route sont cohérentes. Aucun probe réseau, aucune ouverture de Store et aucun Worker ne sont déclenchés par l'inventaire.
Un refresh reconstruit l'inventaire depuis Config et publie une nouvelle génération. La sélection visuelle d'un profil ne choisit aucune URL ou ressource physique et ne démarre aucune acquisition.
Un refresh reconstruit l'inventaire depuis Config et publie une nouvelle génération. La sélection visuelle d'un réseau ne choisit aucune URL, provider ou ressource physique et ne démarre aucune acquisition. Une capability optionnelle dont le secret n'est pas résolu rend uniquement la route qui en dépend indisponible ; les routes satisfaites par le Transport de base du même réseau restent composables.
Les URLs, tokens, metadata secrètes, handles Transport/Store/Worker, URI Store, source keys et payloads RAW restent backend-only.

View File

@@ -1,5 +1,5 @@
<!-- file: crates/ksp-app-raw-transaction-ingest-desk/frontend/main.html -->
<!-- version: 3 -->
<!-- version: 4 -->
<!DOCTYPE html>
<html lang="fr">
@@ -59,8 +59,8 @@
</div>
<div class="row g-3 align-items-end mb-4">
<div class="col-12 col-md-6">
<label class="form-label" for="routeProfile">Profil applicatif</label>
<select id="routeProfile" class="form-select" aria-label="Profil Raw Transaction Ingest Desk"></select>
<label class="form-label" for="routeProfile">Réseau logique</label>
<select id="routeProfile" class="form-select" aria-label="Réseau Raw Transaction Ingest Desk"></select>
</div>
<div class="col-6 col-md-3">
<div class="small text-body-secondary">Réseau</div>
@@ -74,7 +74,7 @@
<div class="alert alert-info" role="status">
<strong>Configured</strong> signifie uniquement que Config prouve la composabilité. Les connexions, le Store et le Worker seront revalidés au Start dans les tranches suivantes.
</div>
<div class="small text-body-secondary mb-3">Profil affiché : <span id="routeSelectedProfile" class="app-route-code"></span></div>
<div class="small text-body-secondary mb-3">Réseau affiché : <span id="routeSelectedProfile" class="app-route-code"></span></div>
<div id="routeFoundation" class="row g-3 app-route-grid" aria-live="polite"></div>
</section>

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-raw-transaction-ingest-desk/frontend/ts/main.ts
// version: 3
// version: 4
import "bootstrap";
import ResizeObserver from "resize-observer-polyfill";
@@ -226,7 +226,7 @@ function bindRefreshControls(): void {
return;
}
selectedProfileId = selector.value;
frontendDebug("main", "Raw Transaction Ingest Desk logical profile selected", { profileId: selectedProfileId });
frontendDebug("main", "Raw Transaction Ingest Desk logical network selected", { profileId: selectedProfileId });
renderSelectedProfile();
});
}

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-raw-transaction-ingest-desk/src/constants.rs
// version: 2
// version: 3
//! Application-owned tracing targets and Config component identifiers.
@@ -9,6 +9,12 @@ pub(crate) const COMPOSITE_COMPONENT_ID_LOGGING: &str = "logging";
pub(crate) const COMPOSITE_COMPONENT_ID_STORE: &str = "store";
/// Composite component identifier for Transport.
pub(crate) const COMPOSITE_COMPONENT_ID_TRANSPORT: &str = "transport";
/// Composite-local optional Transport source for Helius WebSocket capabilities.
pub(crate) const COMPOSITE_COMPONENT_ID_TRANSPORT_HELIUS: &str = "transport.helius";
/// Prefix used by optional same-network Transport capability sources.
pub(crate) const COMPOSITE_COMPONENT_ID_TRANSPORT_PREFIX: &str = "transport.";
/// Composite-local optional Transport source for Yellowstone gRPC capabilities.
pub(crate) const COMPOSITE_COMPONENT_ID_TRANSPORT_YELLOWSTONE: &str = "transport.yellowstone";
/// Structured domain used while bootstrapping Config and Logging.
pub(crate) const TRACING_DOMAIN_BOOTSTRAP: &str = "raw_transaction_ingest.bootstrap";
/// Structured domain used by technical frontend events.

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-raw-transaction-ingest-desk/src/lib.rs
// version: 2
// version: 3
//! Tauri desktop application scaffold for composing and supervising KSP live RAW transaction ingest routes.
@@ -44,6 +44,12 @@ pub(crate) use self::constants::COMPOSITE_COMPONENT_ID_LOGGING;
pub(crate) use self::constants::COMPOSITE_COMPONENT_ID_STORE;
/// Composite-local identifier for the standard Transport component.
pub(crate) use self::constants::COMPOSITE_COMPONENT_ID_TRANSPORT;
/// Composite-local optional Transport source for Helius WebSocket capabilities.
pub(crate) use self::constants::COMPOSITE_COMPONENT_ID_TRANSPORT_HELIUS;
/// Prefix used by optional same-network Transport capability sources.
pub(crate) use self::constants::COMPOSITE_COMPONENT_ID_TRANSPORT_PREFIX;
/// Composite-local optional Transport source for Yellowstone gRPC capabilities.
pub(crate) use self::constants::COMPOSITE_COMPONENT_ID_TRANSPORT_YELLOWSTONE;
/// Structured domain used while bootstrapping Config and Logging.
pub(crate) use self::constants::TRACING_DOMAIN_BOOTSTRAP;
/// Structured domain used by technical frontend events.

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-raw-transaction-ingest-desk/src/route_inventory.rs
// version: 1
// version: 2
//! Config-only logical route inventory for Raw Transaction Ingest Desk.
@@ -8,28 +8,74 @@ struct CompositeProfileCatalog {
profile_ids: std::vec::Vec<String>,
}
#[derive(Default)]
struct RouteCapabilities {
has_get_transaction: bool,
has_http_block_scan: bool,
has_yellowstone: bool,
has_standard_logs: bool,
has_standard_block: bool,
has_helius_transaction: bool,
helius_source_missing_secret: bool,
yellowstone_source_missing_secret: bool,
}
impl RouteCapabilities {
fn absorb_transport(&mut self, transport: &ksp_config_lib::ResolvedTransportConfig, network: &str) {
self.has_get_transaction |= http_role_supports_methods(transport.http_settings(), &["getTransaction"]);
self.has_http_block_scan |= http_role_supports_methods(transport.http_settings(), &["getSlot", "getBlocksWithLimit", "getBlock"]);
self.has_yellowstone |= has_yellowstone_grpc(transport, network);
self.has_standard_logs |= has_ws_capability(
transport,
network,
ksp_onchain_transport_lib::WsProtocolKind::SolanaStandard,
ksp_onchain_transport_lib::WsSubscriptionKind::Logs,
);
self.has_standard_block |= has_ws_capability(
transport,
network,
ksp_onchain_transport_lib::WsProtocolKind::SolanaStandard,
ksp_onchain_transport_lib::WsSubscriptionKind::Block,
);
self.has_helius_transaction |= has_ws_capability(
transport,
network,
ksp_onchain_transport_lib::WsProtocolKind::HeliusLaserStream,
ksp_onchain_transport_lib::WsSubscriptionKind::HeliusTransaction,
);
}
}
/// Rebuilds the complete safe route inventory from validated Config without opening any network, Store or Worker resource.
pub(crate) fn build_route_inventory(management: &ksp_config_lib::ConfigManagement, generation: u32) -> ksp_core_lib::Result<crate::RawIngestRouteInventoryDto> {
let catalog = composite_profile_catalog(management);
let catalog = match catalog {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let environment = ksp_config_lib::ConfigEnvironment::load();
let environment = match environment {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
return build_route_inventory_with_environment(management, &environment, generation);
}
fn build_route_inventory_with_environment(
management: &ksp_config_lib::ConfigManagement,
environment: &ksp_config_lib::ConfigEnvironment,
generation: u32,
) -> ksp_core_lib::Result<crate::RawIngestRouteInventoryDto> {
let catalog = composite_profile_catalog(management);
let catalog = match catalog {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let mut profiles = std::vec::Vec::with_capacity(catalog.profile_ids.len());
for profile_id in &catalog.profile_ids {
profiles.push(build_profile_inventory(management, &environment, profile_id.as_str(), profile_id == &catalog.default_profile));
profiles.push(build_profile_inventory(management, environment, profile_id.as_str(), profile_id == &catalog.default_profile));
}
ksp_logging_lib::debug!(
target: crate::TRACING_TARGET,
domain = crate::TRACING_DOMAIN_INVENTORY,
generation,
profile_count = profiles.len(),
"rebuilt Raw Transaction Ingest Desk Config-only route inventory"
"rebuilt Raw Transaction Ingest Desk network-centric Config-only route inventory"
);
return std::result::Result::Ok(crate::RawIngestRouteInventoryDto { default_profile: catalog.default_profile, generation, profiles });
}
@@ -92,14 +138,6 @@ fn build_profile_inventory(
return unavailable_profile(profile_id, is_default, std::option::Option::None, crate::RawIngestRouteUnavailableReason::ProfileUnresolved);
},
};
let transport_profile =
crate::required_composite_component_profile(&composite, crate::COMPOSITE_COMPONENT_ID_TRANSPORT, ksp_config_lib::FILE_ID_STD_TRANSPORT);
let transport_profile = match transport_profile {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => {
return unavailable_profile(profile_id, is_default, std::option::Option::None, crate::RawIngestRouteUnavailableReason::ProfileUnresolved);
},
};
let store_profile = crate::required_composite_component_profile(&composite, crate::COMPOSITE_COMPONENT_ID_STORE, ksp_config_lib::FILE_ID_STD_STORE);
let store_profile = match store_profile {
std::result::Result::Ok(value) => value,
@@ -107,91 +145,152 @@ fn build_profile_inventory(
return unavailable_profile(profile_id, is_default, std::option::Option::None, crate::RawIngestRouteUnavailableReason::ProfileUnresolved);
},
};
let transport = management.engine().resolve_transport_config_profile(&transport_profile, environment);
let store = management.engine().resolve_store_config_profile(&store_profile, environment);
let network_hint = resolved_network_hint(&transport, &store);
if transport.is_err() || store.is_err() {
let reason = resolution_failure_reason(&transport, &store);
return unavailable_profile(profile_id, is_default, network_hint.as_deref(), reason);
}
let transport = match transport {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => {
return unavailable_profile(profile_id, is_default, network_hint.as_deref(), crate::RawIngestRouteUnavailableReason::ProfileUnresolved);
},
};
let store = match store {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => {
return unavailable_profile(profile_id, is_default, network_hint.as_deref(), crate::RawIngestRouteUnavailableReason::ProfileUnresolved);
std::result::Result::Err(error) => {
let reason = resolution_error_reason(&error);
return unavailable_profile(profile_id, is_default, std::option::Option::None, reason);
},
};
let store_network = store.settings().network().as_str().to_owned();
if !transport_matches_network(&transport, store_network.as_str()) {
let network = store.settings().network().as_str().to_owned();
let base_transport_profile =
crate::required_composite_component_profile(&composite, crate::COMPOSITE_COMPONENT_ID_TRANSPORT, ksp_config_lib::FILE_ID_STD_TRANSPORT);
let base_transport_profile = match base_transport_profile {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => {
return unavailable_profile(
profile_id,
is_default,
std::option::Option::Some(network.as_str()),
crate::RawIngestRouteUnavailableReason::ProfileUnresolved,
);
},
};
let base_transport = management.engine().resolve_transport_config_profile(&base_transport_profile, environment);
let base_transport = match base_transport {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
return unavailable_profile(profile_id, is_default, std::option::Option::Some(network.as_str()), resolution_error_reason(&error));
},
};
if !transport_matches_network(&base_transport, network.as_str()) {
return unavailable_profile(
profile_id,
is_default,
std::option::Option::Some(store_network.as_str()),
std::option::Option::Some(network.as_str()),
crate::RawIngestRouteUnavailableReason::NetworkMismatch,
);
}
let routes = build_configured_profile_routes(&transport, store_network.as_str());
return crate::RawIngestProfileInventoryDto {
is_default,
network: std::option::Option::Some(store_network),
profile_id: profile_id.to_owned(),
routes,
};
let mut capabilities = RouteCapabilities::default();
capabilities.absorb_transport(&base_transport, network.as_str());
for (component_id, component) in composite.components() {
if component_id == crate::COMPOSITE_COMPONENT_ID_TRANSPORT {
continue;
}
if !component_id.starts_with(crate::COMPOSITE_COMPONENT_ID_TRANSPORT_PREFIX) {
continue;
}
if component_id != crate::COMPOSITE_COMPONENT_ID_TRANSPORT_HELIUS && component_id != crate::COMPOSITE_COMPONENT_ID_TRANSPORT_YELLOWSTONE {
return unavailable_profile(
profile_id,
is_default,
std::option::Option::Some(network.as_str()),
crate::RawIngestRouteUnavailableReason::ProfileUnresolved,
);
}
if component.resolved().file_id().as_str() != ksp_config_lib::FILE_ID_STD_TRANSPORT {
return unavailable_profile(
profile_id,
is_default,
std::option::Option::Some(network.as_str()),
crate::RawIngestRouteUnavailableReason::ProfileUnresolved,
);
}
let resolved = management.engine().resolve_transport_config_profile(component.resolved(), environment);
let resolved = match resolved {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) if error.code() == ksp_config_lib::ERROR_CODE_ENVIRONMENT_VARIABLE_MISSING => {
mark_optional_source_missing_secret(&mut capabilities, component_id.as_str());
continue;
},
std::result::Result::Err(_) => {
return unavailable_profile(
profile_id,
is_default,
std::option::Option::Some(network.as_str()),
crate::RawIngestRouteUnavailableReason::ProfileUnresolved,
);
},
};
if !transport_matches_network(&resolved, network.as_str()) {
return unavailable_profile(
profile_id,
is_default,
std::option::Option::Some(network.as_str()),
crate::RawIngestRouteUnavailableReason::NetworkMismatch,
);
}
capabilities.absorb_transport(&resolved, network.as_str());
}
let routes = build_configured_profile_routes(&capabilities, network.as_str());
return crate::RawIngestProfileInventoryDto { is_default, network: std::option::Option::Some(network), profile_id: profile_id.to_owned(), routes };
}
fn build_configured_profile_routes(transport: &ksp_config_lib::ResolvedTransportConfig, network: &str) -> std::vec::Vec<crate::RawIngestRouteDto> {
let has_get_transaction = http_role_supports_methods(transport.http_settings(), &["getTransaction"]);
let has_http_block_scan = http_role_supports_methods(transport.http_settings(), &["getSlot", "getBlocksWithLimit", "getBlock"]);
let has_yellowstone = has_yellowstone_grpc(transport, network);
let has_standard_logs =
has_ws_capability(transport, network, ksp_onchain_transport_lib::WsProtocolKind::SolanaStandard, ksp_onchain_transport_lib::WsSubscriptionKind::Logs);
let has_standard_block =
has_ws_capability(transport, network, ksp_onchain_transport_lib::WsProtocolKind::SolanaStandard, ksp_onchain_transport_lib::WsSubscriptionKind::Block);
let has_helius_transaction = has_ws_capability(
transport,
network,
ksp_onchain_transport_lib::WsProtocolKind::HeliusLaserStream,
ksp_onchain_transport_lib::WsSubscriptionKind::HeliusTransaction,
);
fn mark_optional_source_missing_secret(capabilities: &mut RouteCapabilities, component_id: &str) {
if component_id == crate::COMPOSITE_COMPONENT_ID_TRANSPORT_HELIUS {
capabilities.helius_source_missing_secret = true;
}
if component_id == crate::COMPOSITE_COMPONENT_ID_TRANSPORT_YELLOWSTONE {
capabilities.yellowstone_source_missing_secret = true;
}
}
fn build_configured_profile_routes(capabilities: &RouteCapabilities, network: &str) -> std::vec::Vec<crate::RawIngestRouteDto> {
let yellowstone_reason = if capabilities.yellowstone_source_missing_secret {
crate::RawIngestRouteUnavailableReason::MissingRequiredSecret
} else {
crate::RawIngestRouteUnavailableReason::MissingYellowstoneGrpc
};
let helius_reason = if capabilities.helius_source_missing_secret {
crate::RawIngestRouteUnavailableReason::MissingRequiredSecret
} else {
crate::RawIngestRouteUnavailableReason::MissingHeliusTransactionCapability
};
return vec![
route_with_requirements(
crate::RawIngestRouteId::YellowstoneHydrated,
network,
&[
(has_yellowstone, crate::RawIngestRouteUnavailableReason::MissingYellowstoneGrpc),
(has_get_transaction, crate::RawIngestRouteUnavailableReason::MissingHttpGetTransaction),
(capabilities.has_yellowstone, yellowstone_reason),
(capabilities.has_get_transaction, crate::RawIngestRouteUnavailableReason::MissingHttpGetTransaction),
],
),
route_with_requirements(
crate::RawIngestRouteId::StandardLogsHydrated,
network,
&[
(has_standard_logs, crate::RawIngestRouteUnavailableReason::MissingWsLogsCapability),
(has_get_transaction, crate::RawIngestRouteUnavailableReason::MissingHttpGetTransaction),
(capabilities.has_standard_logs, crate::RawIngestRouteUnavailableReason::MissingWsLogsCapability),
(capabilities.has_get_transaction, crate::RawIngestRouteUnavailableReason::MissingHttpGetTransaction),
],
),
route_with_requirements(
crate::RawIngestRouteId::StandardBlockDirect,
network,
&[(has_standard_block, crate::RawIngestRouteUnavailableReason::MissingWsBlockCapability)],
&[(capabilities.has_standard_block, crate::RawIngestRouteUnavailableReason::MissingWsBlockCapability)],
),
route_with_requirements(
crate::RawIngestRouteId::HeliusTransactionHydrated,
network,
&[
(has_helius_transaction, crate::RawIngestRouteUnavailableReason::MissingHeliusTransactionCapability),
(has_get_transaction, crate::RawIngestRouteUnavailableReason::MissingHttpGetTransaction),
(capabilities.has_helius_transaction, helius_reason),
(capabilities.has_get_transaction, crate::RawIngestRouteUnavailableReason::MissingHttpGetTransaction),
],
),
route_with_requirements(
crate::RawIngestRouteId::HttpBlockPolling,
network,
&[(has_http_block_scan, crate::RawIngestRouteUnavailableReason::MissingHttpBlockScan)],
&[(capabilities.has_http_block_scan, crate::RawIngestRouteUnavailableReason::MissingHttpBlockScan)],
),
];
}
@@ -222,40 +321,13 @@ fn unavailable_profile(
return crate::RawIngestProfileInventoryDto { is_default, network: network.map(str::to_owned), profile_id: profile_id.to_owned(), routes };
}
fn resolution_failure_reason(
transport: &ksp_core_lib::Result<ksp_config_lib::ResolvedTransportConfig>,
store: &ksp_core_lib::Result<ksp_config_lib::ResolvedStoreConfig>,
) -> crate::RawIngestRouteUnavailableReason {
let transport_missing_secret = match transport {
std::result::Result::Err(error) => error.code() == ksp_config_lib::ERROR_CODE_ENVIRONMENT_VARIABLE_MISSING,
std::result::Result::Ok(_) => false,
};
let store_missing_secret = match store {
std::result::Result::Err(error) => error.code() == ksp_config_lib::ERROR_CODE_ENVIRONMENT_VARIABLE_MISSING,
std::result::Result::Ok(_) => false,
};
if transport_missing_secret || store_missing_secret {
fn resolution_error_reason(error: &ksp_core_lib::Error) -> crate::RawIngestRouteUnavailableReason {
if error.code() == ksp_config_lib::ERROR_CODE_ENVIRONMENT_VARIABLE_MISSING {
return crate::RawIngestRouteUnavailableReason::MissingRequiredSecret;
}
return crate::RawIngestRouteUnavailableReason::ProfileUnresolved;
}
fn resolved_network_hint(
transport: &ksp_core_lib::Result<ksp_config_lib::ResolvedTransportConfig>,
store: &ksp_core_lib::Result<ksp_config_lib::ResolvedStoreConfig>,
) -> std::option::Option<String> {
if let std::result::Result::Ok(store) = store {
return std::option::Option::Some(store.settings().network().as_str().to_owned());
}
if let std::result::Result::Ok(transport) = transport {
let networks = enabled_transport_networks(transport);
if networks.len() == 1 {
return networks.into_iter().next();
}
}
return std::option::Option::None;
}
fn transport_matches_network(transport: &ksp_config_lib::ResolvedTransportConfig, network: &str) -> bool {
let networks = enabled_transport_networks(transport);
return networks.len() == 1 && networks.contains(network);

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-raw-transaction-ingest-desk/unit_tests/route_inventory.rs
// version: 1
// version: 2
#[test]
fn pre_006_route_requirement_projection_is_fail_closed_and_ordered() {
@@ -27,14 +27,10 @@ fn pre_006_route_requirement_projection_is_fail_closed_and_ordered() {
#[test]
fn pre_006_unavailable_profile_projects_all_five_routes_without_physical_material() {
let profile = super::unavailable_profile(
"provider_profile",
false,
std::option::Option::Some("testnet"),
crate::RawIngestRouteUnavailableReason::MissingRequiredSecret,
);
let profile =
super::unavailable_profile("mainnet", false, std::option::Option::Some("mainnet"), crate::RawIngestRouteUnavailableReason::MissingRequiredSecret);
assert_eq!(profile.routes.len(), 5);
assert_eq!(profile.network.as_deref(), std::option::Option::Some("testnet"));
assert_eq!(profile.network.as_deref(), std::option::Option::Some("mainnet"));
for route in profile.routes {
assert!(!route.selectable);
assert_eq!(route.reason, std::option::Option::Some(crate::RawIngestRouteUnavailableReason::MissingRequiredSecret));
@@ -42,60 +38,163 @@ fn pre_006_unavailable_profile_projects_all_five_routes_without_physical_materia
}
#[test]
fn pre_006_committed_devnet_public_inventory_proves_only_config_composability() {
let arguments = std::vec::Vec::<std::ffi::OsString>::new();
let management = crate::config_management(arguments.as_slice());
fn pre_006_fix_001_network_profiles_aggregate_same_network_transport_capabilities() {
let management = committed_management();
assert!(management.is_ok());
let management = match management {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let inventory = crate::build_route_inventory(&management, 7);
let environment = all_optional_source_secrets();
let inventory = super::build_route_inventory_with_environment(&management, &environment, 7);
assert!(inventory.is_ok());
let inventory = match inventory {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
assert_eq!(inventory.generation, 7);
assert_eq!(inventory.default_profile, "devnet_public");
let profile = inventory.profiles.iter().find(|profile| return profile.profile_id == "devnet_public");
assert!(profile.is_some());
let profile = match profile {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
assert!(profile.is_default);
assert_eq!(profile.network.as_deref(), std::option::Option::Some("devnet"));
assert_eq!(profile.routes.len(), 5);
assert_route(
profile,
crate::RawIngestRouteId::YellowstoneHydrated,
false,
std::option::Option::Some(crate::RawIngestRouteUnavailableReason::MissingYellowstoneGrpc),
assert_eq!(inventory.default_profile, "devnet");
assert_eq!(
inventory.profiles.iter().map(|profile| return profile.profile_id.as_str()).collect::<std::vec::Vec<_>>(),
vec!["devnet", "mainnet", "testnet"]
);
assert_route(profile, crate::RawIngestRouteId::StandardLogsHydrated, true, std::option::Option::None);
assert_route(
profile,
crate::RawIngestRouteId::StandardBlockDirect,
false,
std::option::Option::Some(crate::RawIngestRouteUnavailableReason::MissingWsBlockCapability),
);
assert_route(
profile,
crate::RawIngestRouteId::HeliusTransactionHydrated,
false,
std::option::Option::Some(crate::RawIngestRouteUnavailableReason::MissingHeliusTransactionCapability),
);
assert_route(profile, crate::RawIngestRouteId::HttpBlockPolling, true, std::option::Option::None);
let devnet = profile(&inventory, "devnet");
assert!(devnet.is_some());
if let std::option::Option::Some(devnet) = devnet {
assert!(devnet.is_default);
assert_eq!(devnet.network.as_deref(), std::option::Option::Some("devnet"));
assert_route(devnet, crate::RawIngestRouteId::YellowstoneHydrated, true, std::option::Option::None);
assert_route(devnet, crate::RawIngestRouteId::StandardLogsHydrated, true, std::option::Option::None);
assert_route(
devnet,
crate::RawIngestRouteId::StandardBlockDirect,
false,
std::option::Option::Some(crate::RawIngestRouteUnavailableReason::MissingWsBlockCapability),
);
assert_route(devnet, crate::RawIngestRouteId::HeliusTransactionHydrated, true, std::option::Option::None);
assert_route(devnet, crate::RawIngestRouteId::HttpBlockPolling, true, std::option::Option::None);
}
let mainnet = profile(&inventory, "mainnet");
assert!(mainnet.is_some());
if let std::option::Option::Some(mainnet) = mainnet {
assert_eq!(mainnet.network.as_deref(), std::option::Option::Some("mainnet"));
assert_route(mainnet, crate::RawIngestRouteId::YellowstoneHydrated, true, std::option::Option::None);
assert_route(mainnet, crate::RawIngestRouteId::StandardLogsHydrated, true, std::option::Option::None);
assert_route(mainnet, crate::RawIngestRouteId::HeliusTransactionHydrated, true, std::option::Option::None);
assert_route(mainnet, crate::RawIngestRouteId::HttpBlockPolling, true, std::option::Option::None);
}
let testnet = profile(&inventory, "testnet");
assert!(testnet.is_some());
if let std::option::Option::Some(testnet) = testnet {
assert_eq!(testnet.network.as_deref(), std::option::Option::Some("testnet"));
assert_route(testnet, crate::RawIngestRouteId::YellowstoneHydrated, true, std::option::Option::None);
assert_route(testnet, crate::RawIngestRouteId::StandardLogsHydrated, true, std::option::Option::None);
assert_route(
testnet,
crate::RawIngestRouteId::HeliusTransactionHydrated,
false,
std::option::Option::Some(crate::RawIngestRouteUnavailableReason::MissingHeliusTransactionCapability),
);
assert_route(testnet, crate::RawIngestRouteId::HttpBlockPolling, true, std::option::Option::None);
}
let serialized = serde_json::to_string(&inventory);
assert!(serialized.is_ok());
if let std::result::Result::Ok(serialized) = serialized {
for forbidden in ["http://", "https://", "ws://", "wss://", "api-key", "x-token", "connection_uri", "source_key", "endpoint_name"] {
assert!(!serialized.contains(forbidden), "safe inventory leaked forbidden marker {forbidden}");
for forbidden in [
"http://",
"https://",
"ws://",
"wss://",
"api-key",
"x-token",
"connection_uri",
"source_key",
"endpoint_name",
"publicnode_mainnet",
"helius_mainnet",
] {
assert!(!serialized.contains(forbidden), "safe network inventory leaked forbidden source marker {forbidden}");
}
}
}
#[test]
fn pre_006_fix_001_missing_optional_source_secret_does_not_disable_base_network_routes() {
let management = committed_management();
assert!(management.is_ok());
let management = match management {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let environment = ksp_config_lib::ConfigEnvironment::from_maps(std::collections::BTreeMap::new(), std::collections::BTreeMap::new());
let inventory = super::build_route_inventory_with_environment(&management, &environment, 11);
assert!(inventory.is_ok());
let inventory = match inventory {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let mainnet = profile(&inventory, "mainnet");
assert!(mainnet.is_some());
if let std::option::Option::Some(mainnet) = mainnet {
assert_route(mainnet, crate::RawIngestRouteId::StandardLogsHydrated, true, std::option::Option::None);
assert_route(mainnet, crate::RawIngestRouteId::HttpBlockPolling, true, std::option::Option::None);
assert_route(
mainnet,
crate::RawIngestRouteId::YellowstoneHydrated,
false,
std::option::Option::Some(crate::RawIngestRouteUnavailableReason::MissingRequiredSecret),
);
assert_route(
mainnet,
crate::RawIngestRouteId::HeliusTransactionHydrated,
false,
std::option::Option::Some(crate::RawIngestRouteUnavailableReason::MissingRequiredSecret),
);
}
}
fn committed_management() -> ksp_core_lib::Result<ksp_config_lib::ConfigManagement> {
let manifest = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let crates_root = manifest.parent();
let crates_root = match crates_root {
std::option::Option::Some(value) => value,
std::option::Option::None => {
return std::result::Result::Err(ksp_core_lib::Error::new(crate::ERROR_CODE_ROUTE_INVENTORY_INVALID, "test manifest has no crates parent"));
},
};
let workspace = crates_root.parent();
let workspace = match workspace {
std::option::Option::Some(value) => value,
std::option::Option::None => {
return std::result::Result::Err(ksp_core_lib::Error::new(crate::ERROR_CODE_ROUTE_INVENTORY_INVALID, "test crates root has no workspace parent"));
},
};
let bootstrap = ksp_config_lib::ConfigBootstrapOptions::from_paths(workspace.join("config"), workspace.join("config/schemas"));
let bootstrap = match bootstrap {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let registry = ksp_config_lib::ConfigFileRegistry::defaults();
let registry = match registry {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
return std::result::Result::Ok(ksp_config_lib::ConfigManagement::new(ksp_config_lib::ConfigDocumentEngine::new(bootstrap, registry)));
}
fn all_optional_source_secrets() -> ksp_config_lib::ConfigEnvironment {
let mut process = std::collections::BTreeMap::<String, String>::new();
process.insert("KSP_SECRET_HELIUS_API_KEY".to_owned(), "helius-route-inventory-canary".to_owned());
process.insert("KSP_SECRET_ORBITFLARE_DEVNET_GRPC_X_TOKEN".to_owned(), "orbitflare-route-inventory-canary".to_owned());
process.insert("KSP_SECRET_PUBLICNODE_MAINNET_GRPC_X_TOKEN".to_owned(), "publicnode-mainnet-route-inventory-canary".to_owned());
process.insert("KSP_SECRET_PUBLICNODE_TESTNET_GRPC_X_TOKEN".to_owned(), "publicnode-testnet-route-inventory-canary".to_owned());
return ksp_config_lib::ConfigEnvironment::from_maps(process, std::collections::BTreeMap::new());
}
fn profile<'a>(inventory: &'a crate::RawIngestRouteInventoryDto, profile_id: &str) -> std::option::Option<&'a crate::RawIngestProfileInventoryDto> {
return inventory.profiles.iter().find(|profile| return profile.profile_id == profile_id);
}
fn assert_route(
profile: &crate::RawIngestProfileInventoryDto,
route_id: crate::RawIngestRouteId,