v0.5.1-pre.008

This commit is contained in:
2026-08-10 11:21:07 +02:00
parent a2820062eb
commit 0e05c660c6
90 changed files with 2490 additions and 1613 deletions

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/app_state.rs
// version: 15
// version: 16
//! Shared Tauri application state and startup initialization.
@@ -7,6 +7,12 @@
pub(crate) struct AppState {
config_path: std::string::String,
logging_config_path: std::string::String,
transport_config_path: std::string::String,
listeners_config_path: std::string::String,
store_config_path: std::string::String,
wallet_config_path: std::string::String,
execution_config_path: std::string::String,
desktop_config: crate::DesktopApplicationConfig,
app_config: ks_config::AppConfig,
active_profile: ks_config::ProfileConfig,
logging_guard: std::sync::Mutex<ks_logging::LoggingGuard>,
@@ -44,8 +50,17 @@ impl crate::AppState {
std::result::Result::Ok(profile) => profile.clone(),
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let desktop_config = match crate::desktop_application_config(&composition_profile) {
std::result::Result::Ok(config) => config,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let logging_config_path =
resolve_logging_config_path(&workspace_root, &composed.logging_path);
let transport_config_path = composed.transport_path.display().to_string();
let listeners_config_path = composed.listeners_path.display().to_string();
let store_config_path = composed.store_path.display().to_string();
let wallet_config_path = composed.wallet_path.display().to_string();
let execution_config_path = composed.execution_path.display().to_string();
let app_config = composed.app_config;
let active_profile = match ks_config::active_profile(&app_config) {
std::result::Result::Ok(profile) => profile.clone(),
@@ -79,6 +94,12 @@ impl crate::AppState {
return std::result::Result::Ok(crate::AppState {
config_path: config_path.display().to_string(),
logging_config_path: logging_config_path.display().to_string(),
transport_config_path,
listeners_config_path,
store_config_path,
wallet_config_path,
execution_config_path,
desktop_config,
app_config,
active_profile,
logging_guard: std::sync::Mutex::new(logging_guard),
@@ -108,6 +129,36 @@ impl crate::AppState {
return self.logging_config_path.as_str();
}
/// Returns the path used to load the transport configuration file.
pub(crate) fn transport_config_path(&self) -> &str {
return self.transport_config_path.as_str();
}
/// Returns the path used to load the listeners configuration file.
pub(crate) fn listeners_config_path(&self) -> &str {
return self.listeners_config_path.as_str();
}
/// Returns the path used to load the store configuration file.
pub(crate) fn store_config_path(&self) -> &str {
return self.store_config_path.as_str();
}
/// Returns the path used to load the wallet configuration file.
pub(crate) fn wallet_config_path(&self) -> &str {
return self.wallet_config_path.as_str();
}
/// Returns the path used to load the execution configuration file.
pub(crate) fn execution_config_path(&self) -> &str {
return self.execution_config_path.as_str();
}
/// Returns desktop-owned settings selected from the active composition profile.
pub(crate) fn desktop_config(&self) -> &crate::DesktopApplicationConfig {
return &self.desktop_config;
}
/// Returns the complete parsed application configuration.
pub(crate) fn app_config(&self) -> &ks_config::AppConfig {
return &self.app_config;

View File

@@ -1,7 +1,7 @@
// file: kb-app-demo-desktop/src/demo_config.rs
// version: 3
// version: 5
//! Configuration demo payload and state projection.
//! Configuration demo payloads with explicit public and bounded diagnostic projections.
use ts_rs::TS; // rust-rules: derive-import
@@ -12,29 +12,432 @@ use ts_rs::TS; // rust-rules: derive-import
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigPayload.ts"
)]
pub(crate) struct DemoConfigPayload {
/// Path used to load the configuration file.
pub(crate) config_path: std::string::String,
/// Active profile name.
/// Active composition profile name.
pub(crate) active_profile_name: std::string::String,
/// Active profile environment.
/// Desktop-owned environment label.
pub(crate) environment: std::string::String,
/// Entire parsed configuration.
pub(crate) app_config: ks_config::AppConfig,
/// Active profile configuration.
pub(crate) active_profile: ks_config::ProfileConfig,
/// Embedded JSON Schema text used during loading.
pub(crate) schema_json: std::string::String,
/// Explicit public configuration projection.
pub(crate) public_config: crate::DemoConfigPublicPayload,
/// Explicit bounded diagnostic projection.
pub(crate) diagnostic_config: crate::DemoConfigDiagnosticPayload,
/// Generic binary-composition JSON Schema text.
pub(crate) composition_schema_json: std::string::String,
}
/// Public desktop configuration projection containing no secret or internal paths.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigPublicPayload.ts"
)]
pub(crate) struct DemoConfigPublicPayload {
/// Desktop application identity.
pub(crate) application_name: std::string::String,
/// Desktop environment label.
pub(crate) environment: std::string::String,
/// Active composed profile.
pub(crate) profile_name: std::string::String,
/// Public HTTP endpoint identities without URLs or credentials.
pub(crate) http_endpoints: std::vec::Vec<crate::DemoConfigPublicEndpointPayload>,
/// Public WebSocket endpoint identities without URLs or credentials.
pub(crate) ws_endpoints: std::vec::Vec<crate::DemoConfigPublicEndpointPayload>,
/// Listener summary without account-specific filters.
pub(crate) listeners: crate::DemoConfigPublicListenersPayload,
/// Wallet cluster only; wallet paths and aliases remain diagnostic/internal.
pub(crate) wallet_cluster: std::string::String,
/// Desktop-owned demo feature flags.
pub(crate) demo: crate::DemoConfigPublicDemoPayload,
}
/// Public endpoint identity with no URL or authentication material.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigPublicEndpointPayload.ts"
)]
pub(crate) struct DemoConfigPublicEndpointPayload {
/// Endpoint code.
pub(crate) name: std::string::String,
/// Whether the endpoint is enabled.
pub(crate) enabled: bool,
/// Provider code.
pub(crate) provider: std::string::String,
/// Cluster code.
pub(crate) cluster: std::string::String,
}
/// Public listener summary.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigPublicListenersPayload.ts"
)]
pub(crate) struct DemoConfigPublicListenersPayload {
/// Whether listener creation is enabled.
pub(crate) enabled: bool,
/// Default commitment used by subscriptions.
pub(crate) default_commitment: std::string::String,
/// Number of log listener declarations.
pub(crate) log_listener_count: u32,
/// Number of program listener declarations.
pub(crate) program_listener_count: u32,
/// Number of account listener declarations.
pub(crate) account_listener_count: u32,
}
/// Public desktop demo feature flags.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigPublicDemoPayload.ts"
)]
pub(crate) struct DemoConfigPublicDemoPayload {
/// Enables live demo pages.
pub(crate) live_demo_enabled: bool,
/// Enables trading demo pages.
pub(crate) trading_demo_enabled: bool,
}
/// Bounded diagnostic projection containing internal configuration metadata but no secret values.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigDiagnosticPayload.ts"
)]
pub(crate) struct DemoConfigDiagnosticPayload {
/// Filesystem sources selected by the active binary composition.
pub(crate) sources: std::vec::Vec<crate::DemoConfigSourceDiagnosticPayload>,
/// Endpoint runtime settings without endpoint URLs.
pub(crate) endpoints: std::vec::Vec<crate::DemoConfigEndpointDiagnosticPayload>,
/// Store diagnostics without database URLs or filesystem paths.
pub(crate) store: crate::DemoConfigStoreDiagnosticPayload,
/// Wallet diagnostics without wallet filesystem paths or key material.
pub(crate) wallet: crate::DemoConfigWalletDiagnosticPayload,
/// Execution-policy diagnostics.
pub(crate) execution: crate::DemoConfigExecutionDiagnosticPayload,
}
/// One selected configuration source exposed only through the explicit diagnostic surface.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigSourceDiagnosticPayload.ts"
)]
pub(crate) struct DemoConfigSourceDiagnosticPayload {
/// Source category.
pub(crate) category: std::string::String,
/// Resolved filesystem path.
pub(crate) path: std::string::String,
}
/// Endpoint diagnostic without URL content.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigEndpointDiagnosticPayload.ts"
)]
pub(crate) struct DemoConfigEndpointDiagnosticPayload {
/// Transport kind, either `http` or `ws`.
pub(crate) kind: std::string::String,
/// Endpoint code.
pub(crate) name: std::string::String,
/// Whether the endpoint is enabled.
pub(crate) enabled: bool,
/// Provider code.
pub(crate) provider: std::string::String,
/// Cluster code.
pub(crate) cluster: std::string::String,
/// URL state marker; the URL itself is never serialized.
pub(crate) url_state: std::string::String,
/// Connection timeout in milliseconds.
#[ts(type = "number")]
pub(crate) connect_timeout_ms: u64,
/// Request timeout in milliseconds.
#[ts(type = "number")]
pub(crate) request_timeout_ms: u64,
/// Optional unsubscribe timeout in milliseconds for WebSocket endpoints.
#[ts(type = "number | null")]
pub(crate) unsubscribe_timeout_ms: std::option::Option<u64>,
/// Optional reconnect policy for WebSocket endpoints.
pub(crate) auto_reconnect: std::option::Option<bool>,
/// Number of configured endpoint roles.
pub(crate) role_count: u32,
}
/// Store diagnostic projection without DSN or SQLite path content.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigStoreDiagnosticPayload.ts"
)]
pub(crate) struct DemoConfigStoreDiagnosticPayload {
/// Whether persistence is enabled.
pub(crate) enabled: bool,
/// Selected store backend.
pub(crate) backend: std::string::String,
/// Whether a PostgreSQL URL is configured.
pub(crate) postgres_url_state: std::string::String,
/// PostgreSQL connection pool ceiling.
pub(crate) postgres_max_connections: u32,
/// PostgreSQL connection timeout in milliseconds.
#[ts(type = "number")]
pub(crate) postgres_connect_timeout_ms: u64,
/// Whether PostgreSQL schema initialization is enabled.
pub(crate) postgres_auto_initialize_schema: bool,
/// Whether a SQLite path is configured.
pub(crate) sqlite_path_state: std::string::String,
/// SQLite connection pool ceiling.
pub(crate) sqlite_max_connections: u32,
/// Whether SQLite schema initialization is enabled.
pub(crate) sqlite_auto_initialize_schema: bool,
}
/// Wallet diagnostic projection without paths or secret key material.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigWalletDiagnosticPayload.ts"
)]
pub(crate) struct DemoConfigWalletDiagnosticPayload {
/// Whether a wallet directory is configured.
pub(crate) wallet_directory_state: std::string::String,
/// Wallet cluster.
pub(crate) cluster: std::string::String,
/// Whether the managed temporary wallet is enabled.
pub(crate) temporary_wallet_enabled: bool,
/// Temporary wallet alias, which is internal but not secret.
pub(crate) temporary_wallet_alias: std::string::String,
/// Whether the managed temporary wallet persists between restarts.
pub(crate) temporary_wallet_persist: bool,
}
/// Execution-policy diagnostic projection.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_config/DemoConfigExecutionDiagnosticPayload.ts"
)]
pub(crate) struct DemoConfigExecutionDiagnosticPayload {
/// Enables local-validator sends.
pub(crate) localnet_send_enabled: bool,
/// Enables Devnet sends.
pub(crate) devnet_send_enabled: bool,
/// Enables Testnet sends.
pub(crate) testnet_send_enabled: bool,
/// Enables Mainnet sends.
pub(crate) mainnet_send_enabled: bool,
/// Default dry-run policy.
pub(crate) dry_run_default: bool,
/// Requires simulation before send.
pub(crate) require_simulation: bool,
/// Requires explicit operator confirmation.
pub(crate) require_operator_confirmation: bool,
/// Maximum local-validator spend in lamports.
#[ts(type = "number")]
pub(crate) localnet_max_spend_lamports: u64,
/// Maximum Devnet spend in lamports.
#[ts(type = "number")]
pub(crate) devnet_max_spend_lamports: u64,
/// Maximum Testnet spend in lamports.
#[ts(type = "number")]
pub(crate) testnet_max_spend_lamports: u64,
/// Maximum Mainnet spend in lamports.
#[ts(type = "number")]
pub(crate) mainnet_max_spend_lamports: u64,
/// Maximum fee in lamports.
#[ts(type = "number")]
pub(crate) max_fee_lamports: u64,
/// Maximum compute-unit price in micro-lamports.
#[ts(type = "number")]
pub(crate) max_compute_unit_price_micro_lamports: u64,
/// Maximum recent-blockhash age in slots.
#[ts(type = "number")]
pub(crate) recent_blockhash_max_age_slots: u64,
/// Maximum send retries.
pub(crate) send_max_retries: u32,
/// Confirmation poll interval in milliseconds.
#[ts(type = "number")]
pub(crate) confirmation_poll_interval_ms: u64,
/// Maximum confirmation poll attempts.
pub(crate) confirmation_max_attempts: u32,
/// Maximum Devnet faucet airdrop in lamports.
#[ts(type = "number")]
pub(crate) devnet_airdrop_max_lamports: u64,
}
/// Builds the configuration payload from shared application state.
pub(crate) fn demo_config_payload(state: &crate::AppState) -> crate::DemoConfigPayload {
let active_profile = state.active_profile();
let desktop = state.desktop_config();
return crate::DemoConfigPayload {
config_path: state.config_path().to_owned(),
active_profile_name: state.active_profile().name.clone(),
environment: state.active_profile().app.environment.clone(),
app_config: state.app_config().clone(),
active_profile: state.active_profile().clone(),
schema_json: ks_config::config_json_schema_text().to_owned(),
active_profile_name: active_profile.name.clone(),
environment: desktop.environment.clone(),
public_config: public_config_payload(active_profile, desktop),
diagnostic_config: diagnostic_config_payload(state),
composition_schema_json: ks_config::composition_json_schema_text().to_owned(),
};
}
fn public_config_payload(
profile: &ks_config::ProfileConfig,
desktop: &crate::DesktopApplicationConfig,
) -> DemoConfigPublicPayload {
let http_endpoints = profile
.solana
.http_endpoints
.iter()
.map(|endpoint| {
return DemoConfigPublicEndpointPayload {
name: endpoint.name.clone(),
enabled: endpoint.enabled,
provider: endpoint.provider.clone(),
cluster: endpoint.cluster.clone(),
};
})
.collect::<std::vec::Vec<DemoConfigPublicEndpointPayload>>();
let ws_endpoints = profile
.solana
.ws_endpoints
.iter()
.map(|endpoint| {
return DemoConfigPublicEndpointPayload {
name: endpoint.name.clone(),
enabled: endpoint.enabled,
provider: endpoint.provider.clone(),
cluster: endpoint.cluster.clone(),
};
})
.collect::<std::vec::Vec<DemoConfigPublicEndpointPayload>>();
return DemoConfigPublicPayload {
application_name: desktop.name.clone(),
environment: desktop.environment.clone(),
profile_name: profile.name.clone(),
http_endpoints,
ws_endpoints,
listeners: DemoConfigPublicListenersPayload {
enabled: profile.solana.listeners.enabled,
default_commitment: profile.solana.listeners.default_commitment.clone(),
log_listener_count: bounded_len(profile.solana.listeners.log_listeners.len()),
program_listener_count: bounded_len(profile.solana.listeners.program_listeners.len()),
account_listener_count: bounded_len(profile.solana.listeners.account_listeners.len()),
},
wallet_cluster: profile.wallet.cluster.clone(),
demo: DemoConfigPublicDemoPayload {
live_demo_enabled: desktop.demo.live_demo_enabled,
trading_demo_enabled: desktop.demo.trading_demo_enabled,
},
};
}
fn diagnostic_config_payload(state: &crate::AppState) -> DemoConfigDiagnosticPayload {
let profile = state.active_profile();
let mut endpoints = std::vec::Vec::<DemoConfigEndpointDiagnosticPayload>::new();
for endpoint in &profile.solana.http_endpoints {
endpoints.push(DemoConfigEndpointDiagnosticPayload {
kind: "http".to_string(),
name: endpoint.name.clone(),
enabled: endpoint.enabled,
provider: endpoint.provider.clone(),
cluster: endpoint.cluster.clone(),
url_state: configured_state(endpoint.url.as_str()),
connect_timeout_ms: endpoint.connect_timeout_ms,
request_timeout_ms: endpoint.request_timeout_ms,
unsubscribe_timeout_ms: std::option::Option::None,
auto_reconnect: std::option::Option::None,
role_count: bounded_len(endpoint.roles.len()),
});
}
for endpoint in &profile.solana.ws_endpoints {
endpoints.push(DemoConfigEndpointDiagnosticPayload {
kind: "ws".to_string(),
name: endpoint.name.clone(),
enabled: endpoint.enabled,
provider: endpoint.provider.clone(),
cluster: endpoint.cluster.clone(),
url_state: configured_state(endpoint.url.as_str()),
connect_timeout_ms: endpoint.connect_timeout_ms,
request_timeout_ms: endpoint.request_timeout_ms,
unsubscribe_timeout_ms: std::option::Option::Some(endpoint.unsubscribe_timeout_ms),
auto_reconnect: std::option::Option::Some(endpoint.auto_reconnect),
role_count: bounded_len(endpoint.roles.len()),
});
}
return DemoConfigDiagnosticPayload {
sources: std::vec![
source_diagnostic("composition", state.config_path()),
source_diagnostic("logging", state.logging_config_path()),
source_diagnostic("transport", state.transport_config_path()),
source_diagnostic("listeners", state.listeners_config_path()),
source_diagnostic("store", state.store_config_path()),
source_diagnostic("wallet", state.wallet_config_path()),
source_diagnostic("execution", state.execution_config_path()),
],
endpoints,
store: DemoConfigStoreDiagnosticPayload {
enabled: profile.database.enabled,
backend: profile.database.backend.clone(),
postgres_url_state: configured_state(profile.database.postgres.url.as_str()),
postgres_max_connections: profile.database.postgres.max_connections,
postgres_connect_timeout_ms: profile.database.postgres.connect_timeout_ms,
postgres_auto_initialize_schema: profile.database.postgres.auto_initialize_schema,
sqlite_path_state: configured_state(profile.database.sqlite.path.as_str()),
sqlite_max_connections: profile.database.sqlite.max_connections,
sqlite_auto_initialize_schema: profile.database.sqlite.auto_initialize_schema,
},
wallet: DemoConfigWalletDiagnosticPayload {
wallet_directory_state: configured_state(profile.wallet.wallet_dir.as_str()),
cluster: profile.wallet.cluster.clone(),
temporary_wallet_enabled: profile.wallet.temporary_wallet_enabled,
temporary_wallet_alias: profile.wallet.temporary_wallet_alias.clone(),
temporary_wallet_persist: profile.wallet.temporary_wallet_persist,
},
execution: execution_diagnostic(&profile.execution),
};
}
fn source_diagnostic(category: &str, path: &str) -> DemoConfigSourceDiagnosticPayload {
return DemoConfigSourceDiagnosticPayload {
category: category.to_string(),
path: path.to_string(),
};
}
fn configured_state(value: &str) -> std::string::String {
if value.trim().is_empty() {
return "missing".to_string();
}
return "configured".to_string();
}
fn bounded_len(value: usize) -> u32 {
return match u32::try_from(value) {
std::result::Result::Ok(count) => count,
std::result::Result::Err(_) => u32::MAX,
};
}
fn execution_diagnostic(
execution: &ks_config::ExecutionConfig,
) -> DemoConfigExecutionDiagnosticPayload {
return DemoConfigExecutionDiagnosticPayload {
localnet_send_enabled: execution.localnet_send_enabled,
devnet_send_enabled: execution.devnet_send_enabled,
testnet_send_enabled: execution.testnet_send_enabled,
mainnet_send_enabled: execution.mainnet_send_enabled,
dry_run_default: execution.dry_run_default,
require_simulation: execution.require_simulation,
require_operator_confirmation: execution.require_operator_confirmation,
localnet_max_spend_lamports: execution.localnet_max_spend_lamports,
devnet_max_spend_lamports: execution.devnet_max_spend_lamports,
testnet_max_spend_lamports: execution.testnet_max_spend_lamports,
mainnet_max_spend_lamports: execution.mainnet_max_spend_lamports,
max_fee_lamports: execution.max_fee_lamports,
max_compute_unit_price_micro_lamports: execution.max_compute_unit_price_micro_lamports,
recent_blockhash_max_age_slots: execution.recent_blockhash_max_age_slots,
send_max_retries: execution.send_max_retries,
confirmation_poll_interval_ms: execution.confirmation_poll_interval_ms,
confirmation_max_attempts: execution.confirmation_max_attempts,
devnet_airdrop_max_lamports: execution.devnet_airdrop_max_lamports,
};
}
@@ -42,10 +445,126 @@ pub(crate) fn demo_config_payload(state: &crate::AppState) -> crate::DemoConfigP
mod tests {
use ts_rs::TS; // rust-rules: trait-import
fn active_fixture_profile() -> ks_config::ProfileConfig {
let parsed = ks_config::parse_config_json(include_str!(
"../../test-fixtures/config/resolved.app.config.json"
));
let config = match parsed {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => panic!("resolved fixture must parse: {error}"),
};
return match ks_config::active_profile(&config) {
std::result::Result::Ok(value) => value.clone(),
std::result::Result::Err(error) => {
panic!("resolved fixture active profile must exist: {error}")
},
};
}
fn desktop_fixture() -> crate::DesktopApplicationConfig {
return crate::DesktopApplicationConfig {
name: "kb-app-demo-desktop".to_string(),
environment: "test".to_string(),
demo: crate::DesktopDemoConfig {
live_demo_enabled: true,
trading_demo_enabled: false,
},
};
}
#[test]
fn payload_binding_uses_desktop_path() {
let config = ts_rs::Config::default();
let declaration = <crate::DemoConfigPayload as TS>::decl(&config);
assert!(declaration.contains("DemoConfigPayload"));
assert!(declaration.contains("DemoConfigPublicPayload"));
assert!(declaration.contains("DemoConfigDiagnosticPayload"));
assert!(!declaration.contains("AppConfig"));
assert!(!declaration.contains("ProfileConfig"));
}
#[test]
fn public_projection_excludes_internal_execution_and_storage_fields() {
let profile = active_fixture_profile();
let payload = super::public_config_payload(&profile, &desktop_fixture());
let serialized = match serde_json::to_string(&payload) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => panic!("public payload must serialize: {error}"),
};
assert!(!serialized.contains("mainnet_send_enabled"));
assert!(!serialized.contains("postgres"));
assert!(!serialized.contains("wallet_dir"));
assert!(!serialized.contains("url"));
}
#[test]
fn public_and_diagnostic_projections_never_serialize_secret_canaries() {
let mut profile = active_fixture_profile();
profile.database.postgres.url =
"postgres://operator:POSTGRES-SECRET-CANARY@localhost/solana".to_string();
profile.database.sqlite.path = "/private/SQLITE-PATH-CANARY.sqlite".to_string();
profile.wallet.wallet_dir = "/private/WALLET-PATH-CANARY".to_string();
if let std::option::Option::Some(endpoint) = profile.solana.http_endpoints.first_mut() {
endpoint.url = "https://provider.invalid/?api-key=HELIUS-SECRET-CANARY".to_string();
}
if let std::option::Option::Some(endpoint) = profile.solana.ws_endpoints.first_mut() {
endpoint.url = "wss://provider.invalid/WS-SECRET-CANARY".to_string();
}
let public = super::public_config_payload(&profile, &desktop_fixture());
let diagnostics = super::DemoConfigDiagnosticPayload {
sources: std::vec![],
endpoints: profile
.solana
.http_endpoints
.iter()
.map(|endpoint| {
return super::DemoConfigEndpointDiagnosticPayload {
kind: "http".to_string(),
name: endpoint.name.clone(),
enabled: endpoint.enabled,
provider: endpoint.provider.clone(),
cluster: endpoint.cluster.clone(),
url_state: super::configured_state(endpoint.url.as_str()),
connect_timeout_ms: endpoint.connect_timeout_ms,
request_timeout_ms: endpoint.request_timeout_ms,
unsubscribe_timeout_ms: std::option::Option::None,
auto_reconnect: std::option::Option::None,
role_count: super::bounded_len(endpoint.roles.len()),
};
})
.collect::<std::vec::Vec<super::DemoConfigEndpointDiagnosticPayload>>(),
store: super::DemoConfigStoreDiagnosticPayload {
enabled: profile.database.enabled,
backend: profile.database.backend.clone(),
postgres_url_state: super::configured_state(profile.database.postgres.url.as_str()),
postgres_max_connections: profile.database.postgres.max_connections,
postgres_connect_timeout_ms: profile.database.postgres.connect_timeout_ms,
postgres_auto_initialize_schema: profile.database.postgres.auto_initialize_schema,
sqlite_path_state: super::configured_state(profile.database.sqlite.path.as_str()),
sqlite_max_connections: profile.database.sqlite.max_connections,
sqlite_auto_initialize_schema: profile.database.sqlite.auto_initialize_schema,
},
wallet: super::DemoConfigWalletDiagnosticPayload {
wallet_directory_state: super::configured_state(profile.wallet.wallet_dir.as_str()),
cluster: profile.wallet.cluster.clone(),
temporary_wallet_enabled: profile.wallet.temporary_wallet_enabled,
temporary_wallet_alias: profile.wallet.temporary_wallet_alias.clone(),
temporary_wallet_persist: profile.wallet.temporary_wallet_persist,
},
execution: super::execution_diagnostic(&profile.execution),
};
let serialized = match serde_json::to_string(&(public, diagnostics)) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => panic!("safe projections must serialize: {error}"),
};
for secret in [
"POSTGRES-SECRET-CANARY",
"SQLITE-PATH-CANARY",
"WALLET-PATH-CANARY",
"HELIUS-SECRET-CANARY",
"WS-SECRET-CANARY",
] {
assert!(!serialized.contains(secret));
}
}
}

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_http.rs
// version: 14
// version: 16
//! HTTP JSON-RPC demo commands.
@@ -53,6 +53,24 @@ pub(crate) struct DemoHttpOptionsPayload {
pub(crate) methods: std::vec::Vec<crate::DemoHttpMethodOption>,
}
/// UI-safe snapshot of one configured HTTP endpoint.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_http/DemoHttpEndpointPayload.ts"
)]
pub(crate) struct DemoHttpEndpointPayload {
/// Logical endpoint name.
pub(crate) endpoint_name: std::string::String,
/// Provider name.
pub(crate) provider: std::string::String,
/// UI-safe role and local-limit snapshots.
pub(crate) roles: std::vec::Vec<crate::DemoEndpointRolePayload>,
/// Local endpoint status.
pub(crate) status: std::string::String,
}
/// Request payload for one HTTP JSON-RPC demo execution.
#[derive(Clone, Debug, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")]
@@ -85,8 +103,6 @@ pub(crate) struct DemoHttpExecutionPayload {
pub(crate) endpoint_name: std::string::String,
/// Selected provider name.
pub(crate) provider: std::string::String,
/// Selected endpoint URL.
pub(crate) endpoint_url: std::string::String,
/// Required role used by the selection.
pub(crate) role: std::string::String,
/// JSON-RPC method name.
@@ -146,7 +162,6 @@ pub(crate) async fn demo_http_execute_request(
return std::result::Result::Ok(crate::DemoHttpExecutionPayload {
endpoint_name: selected_client.endpoint_name().to_string(),
provider: selected_client.provider().to_string(),
endpoint_url: selected_client.endpoint_url().to_string(),
role,
request_kind: ks_onchain_transport::request_kind_from_method(&method),
method,
@@ -157,8 +172,13 @@ pub(crate) async fn demo_http_execute_request(
pub(crate) fn demo_http_list_pool_clients(
state: tauri::State<'_, crate::AppState>,
) -> std::vec::Vec<ks_onchain_transport::HttpPoolClientSnapshot> {
return state.http_pool().snapshot();
) -> std::vec::Vec<crate::DemoHttpEndpointPayload> {
let snapshots = state.http_pool().snapshot();
let mut endpoints = std::vec::Vec::new();
for snapshot in snapshots {
endpoints.push(http_endpoint_payload(snapshot));
}
return endpoints;
}
pub(crate) fn demo_http_options(
@@ -170,6 +190,21 @@ pub(crate) fn demo_http_options(
};
}
fn http_endpoint_payload(
snapshot: ks_onchain_transport::HttpPoolClientSnapshot,
) -> crate::DemoHttpEndpointPayload {
let mut roles = std::vec::Vec::new();
for role in snapshot.roles {
roles.push(crate::DemoEndpointRolePayload::from_snapshot(role));
}
return crate::DemoHttpEndpointPayload {
endpoint_name: snapshot.endpoint_name,
provider: snapshot.provider,
roles,
status: snapshot.status,
};
}
fn build_http_role_options(
snapshots: std::vec::Vec<ks_onchain_transport::HttpPoolClientSnapshot>,
) -> std::vec::Vec<crate::DemoHttpRoleOption> {
@@ -412,4 +447,23 @@ mod tests {
}
assert!(!options.is_empty());
}
#[test]
fn endpoint_payload_never_serializes_resolved_url() {
let snapshot = ks_onchain_transport::HttpPoolClientSnapshot {
endpoint_name: "helius".to_string(),
provider: "helius".to_string(),
roles: std::vec::Vec::new(),
status: "idle".to_string(),
};
let payload = super::http_endpoint_payload(snapshot);
let serialized = match serde_json::to_string(&payload) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
panic!("cannot serialize HTTP endpoint payload: {error}")
},
};
assert!(!serialized.contains("HTTP-SECRET-CANARY"));
assert!(!serialized.contains("endpointUrl"));
}
}

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_spl_token_2022.rs
// version: 14
// version: 15
//! Thin Tauri adapter for independent public Token-2022 Devnet validation scenarios.
@@ -13,8 +13,6 @@ use ts_rs::TS; // rust-rules: derive-import
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_spl_token_2022/DemoSplToken2022FixturePayload.ts"
)]
pub(crate) struct DemoSplToken2022FixturePayload {
/// Fixture file used by the application.
pub(crate) fixture_path: std::string::String,
/// Token-2022 program ID.
pub(crate) program_id: std::string::String,
/// Mint account.
@@ -231,11 +229,10 @@ pub(crate) fn demo_spl_token_2022_fixture(
let fixture_path = wallet_dir.join("spl_token_2022_validation").join("fixture.env");
let contents = match std::fs::read_to_string(&fixture_path) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
return std::result::Result::Err(format!(
"unable to read Token-2022 fixture {}: {error}",
fixture_path.display()
));
std::result::Result::Err(_) => {
return std::result::Result::Err(
"unable to read configured Token-2022 fixture".to_string(),
);
},
};
let values = parse_fixture(contents.as_str());
@@ -292,7 +289,6 @@ pub(crate) fn demo_spl_token_2022_fixture(
},
};
return std::result::Result::Ok(crate::DemoSplToken2022FixturePayload {
fixture_path: fixture_path.display().to_string(),
program_id,
mint,
source,
@@ -581,6 +577,31 @@ mod tests {
};
}
#[test]
fn fixture_payload_never_serializes_wallet_path() {
let payload = crate::DemoSplToken2022FixturePayload {
program_id: "program".to_string(),
mint: "mint".to_string(),
source: "source".to_string(),
destination: "destination".to_string(),
close_account: "close".to_string(),
delegate: "delegate".to_string(),
authority: "authority".to_string(),
freeze_authority: "freeze".to_string(),
decimals: 9,
mint_amount_raw: "1".to_string(),
transfer_amount_raw: "1".to_string(),
approve_amount_raw: "1".to_string(),
burn_amount_raw: "1".to_string(),
};
let serialized = serde_json::to_string(&payload);
assert!(serialized.is_ok());
if let std::result::Result::Ok(json) = serialized {
assert!(!json.contains("fixturePath"));
assert!(!json.contains("WALLET-PATH-CANARY"));
}
}
#[test]
fn every_public_scenario_builds_one_typed_operation() {
for scenario in [

View File

@@ -0,0 +1,52 @@
// file: kb-app-demo-desktop/src/demo_transport.rs
// version: 1
//! UI-safe transport DTOs shared by HTTP and WebSocket demo surfaces.
use ts_rs::TS; // rust-rules: derive-import
/// UI-safe endpoint role and local routing limits.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_transport/DemoEndpointRolePayload.ts"
)]
pub(crate) struct DemoEndpointRolePayload {
/// Role code used by endpoint pools.
pub(crate) role: std::string::String,
/// Whether the role is enabled.
pub(crate) enabled: bool,
/// Request or subscription kinds handled by this role.
pub(crate) request_kinds: std::vec::Vec<std::string::String>,
/// Role priority where lower values are preferred.
pub(crate) priority: u32,
/// Requests per second allowed for this role.
pub(crate) requests_per_second: u32,
/// Burst capacity allowed for this role.
pub(crate) burst_capacity: u32,
/// Maximum concurrent requests allowed for this role.
pub(crate) max_concurrent_requests: u32,
/// Maximum subscriptions allowed for this role.
pub(crate) max_subscriptions: u32,
/// Pause after a rate limit response in milliseconds.
#[ts(type = "number")]
pub(crate) pause_after_rate_limit_ms: u64,
}
impl crate::DemoEndpointRolePayload {
/// Converts one backend transport role snapshot into the UI-safe application contract.
pub(crate) fn from_snapshot(snapshot: ks_onchain_transport::EndpointRoleSnapshot) -> Self {
return Self {
role: snapshot.role,
enabled: snapshot.enabled,
request_kinds: snapshot.request_kinds,
priority: snapshot.priority,
requests_per_second: snapshot.requests_per_second,
burst_capacity: snapshot.burst_capacity,
max_concurrent_requests: snapshot.max_concurrent_requests,
max_subscriptions: snapshot.max_subscriptions,
pause_after_rate_limit_ms: snapshot.pause_after_rate_limit_ms,
};
}
}

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/demo_ws.rs
// version: 20
// version: 23
//! Standard Solana WebSocket demo commands backed by `ks_onchain_transport::WsSession`.
@@ -59,6 +59,24 @@ pub(crate) struct DemoWsOptionsPayload {
pub(crate) methods: std::vec::Vec<crate::DemoWsMethodOption>,
}
/// UI-safe snapshot of one configured WebSocket endpoint.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_app_demo_desktop/demo_ws/DemoWsEndpointPayload.ts"
)]
pub(crate) struct DemoWsEndpointPayload {
/// Logical endpoint name.
pub(crate) endpoint_name: std::string::String,
/// Provider name.
pub(crate) provider: std::string::String,
/// UI-safe role and local-limit snapshots.
pub(crate) roles: std::vec::Vec<crate::DemoEndpointRolePayload>,
/// Local endpoint status.
pub(crate) status: std::string::String,
}
/// Request payload for one WebSocket subscription demo command.
#[derive(Clone, Debug, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")]
@@ -91,8 +109,6 @@ pub(crate) struct DemoWsExecutionPayload {
pub(crate) endpoint_name: std::string::String,
/// Selected provider name.
pub(crate) provider: std::string::String,
/// Selected endpoint URL.
pub(crate) endpoint_url: std::string::String,
/// Required role used by the selection.
pub(crate) role: std::string::String,
/// JSON-RPC method name.
@@ -120,8 +136,6 @@ pub(crate) struct DemoWsStatusPayload {
pub(crate) connected: bool,
/// Selected endpoint name.
pub(crate) endpoint_name: std::option::Option<std::string::String>,
/// Selected endpoint URL.
pub(crate) endpoint_url: std::option::Option<std::string::String>,
/// Last subscription method.
pub(crate) method: std::option::Option<std::string::String>,
/// Last unsubscribe method.
@@ -230,7 +244,6 @@ pub(crate) async fn demo_ws_connect(
return std::result::Result::Ok(crate::DemoWsExecutionPayload {
endpoint_name: selected_client.endpoint_name().to_string(),
provider: selected_client.provider().to_string(),
endpoint_url: selected_client.endpoint_url().to_string(),
role,
method: method.clone(),
request_kind: ks_onchain_transport::request_kind_from_method(&method),
@@ -259,15 +272,17 @@ pub(crate) async fn demo_ws_status(
/// Lists WebSocket endpoints available through the configured pool.
pub(crate) fn demo_ws_list_pool_clients(
state: tauri::State<'_, crate::AppState>,
) -> std::result::Result<
std::vec::Vec<ks_onchain_transport::WsPoolClientSnapshot>,
std::string::String,
> {
) -> std::result::Result<std::vec::Vec<crate::DemoWsEndpointPayload>, std::string::String> {
let pool = match state.demo_ws_pool() {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error.to_string()),
};
return std::result::Result::Ok(pool.snapshot());
let snapshots = pool.snapshot();
let mut endpoints = std::vec::Vec::new();
for snapshot in snapshots {
endpoints.push(ws_endpoint_payload(snapshot));
}
return std::result::Result::Ok(endpoints);
}
/// Lists selectable WebSocket roles and methods for the demo UI.
@@ -393,7 +408,7 @@ async fn ensure_session(
if let std::option::Option::Some(session) = existing {
let snapshot = session.snapshot().await;
if snapshot.state != ks_onchain_transport::WsSessionState::Disconnected {
if snapshot.endpoint_url != selected_client.endpoint_url() {
if snapshot.endpoint_name.as_str() != selected_client.endpoint_name() {
return std::result::Result::Err(format!(
"demo WebSocket session already uses endpoint '{}'; disconnect before selecting '{}'",
snapshot.endpoint_name,
@@ -569,7 +584,6 @@ fn status_from_snapshot(
return crate::DemoWsStatusPayload {
connected: snapshot.state != ks_onchain_transport::WsSessionState::Disconnected,
endpoint_name: std::option::Option::Some(snapshot.endpoint_name),
endpoint_url: std::option::Option::Some(snapshot.endpoint_url),
method,
unsubscribe_method,
subscription_id,
@@ -585,7 +599,6 @@ fn disconnected_status() -> crate::DemoWsStatusPayload {
return crate::DemoWsStatusPayload {
connected: false,
endpoint_name: std::option::Option::None,
endpoint_url: std::option::Option::None,
method: std::option::Option::None,
unsubscribe_method: std::option::Option::None,
subscription_id: std::option::Option::None,
@@ -594,6 +607,21 @@ fn disconnected_status() -> crate::DemoWsStatusPayload {
};
}
fn ws_endpoint_payload(
snapshot: ks_onchain_transport::WsPoolClientSnapshot,
) -> crate::DemoWsEndpointPayload {
let mut roles = std::vec::Vec::new();
for role in snapshot.roles {
roles.push(crate::DemoEndpointRolePayload::from_snapshot(role));
}
return crate::DemoWsEndpointPayload {
endpoint_name: snapshot.endpoint_name,
provider: snapshot.provider,
roles,
status: snapshot.status,
};
}
fn build_ws_role_options(
snapshots: std::vec::Vec<ks_onchain_transport::WsPoolClientSnapshot>,
) -> std::vec::Vec<crate::DemoWsRoleOption> {
@@ -957,10 +985,46 @@ mod tests {
);
}
#[test]
fn endpoint_and_status_payloads_never_serialize_resolved_url() {
let endpoint_snapshot = ks_onchain_transport::WsPoolClientSnapshot {
endpoint_name: "helius".to_string(),
provider: "helius".to_string(),
roles: std::vec::Vec::new(),
status: "idle".to_string(),
};
let endpoint_payload = super::ws_endpoint_payload(endpoint_snapshot);
let endpoint_json = match serde_json::to_string(&endpoint_payload) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
panic!("cannot serialize WebSocket endpoint payload: {error}")
},
};
assert!(!endpoint_json.contains("WS-SECRET-CANARY"));
assert!(!endpoint_json.contains("endpointUrl"));
let status = super::status_from_snapshot(ks_onchain_transport::WsSessionSnapshot {
endpoint_name: "helius".to_string(),
provider: "helius".to_string(),
state: ks_onchain_transport::WsSessionState::Connected,
reconnect_count: 0,
capabilities: ks_onchain_transport::StandardWsCapabilities::default(),
subscriptions: std::vec::Vec::new(),
});
let status_json = match serde_json::to_string(&status) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
panic!("cannot serialize WebSocket status payload: {error}")
},
};
assert!(!status_json.contains("WS-SECRET-CANARY"));
assert!(!status_json.contains("endpointUrl"));
}
#[test]
fn tauri_numeric_bindings_use_json_compatible_numbers() {
let config = ts_rs::Config::default();
let declarations = [
<crate::DemoEndpointRolePayload as TS>::decl(&config),
<crate::DemoWsExecutionPayload as TS>::decl(&config),
<crate::DemoWsStatusPayload as TS>::decl(&config),
<crate::DemoWsSubscriptionStatusPayload as TS>::decl(&config),

View File

@@ -0,0 +1,96 @@
// file: kb-app-demo-desktop/src/desktop_config.rs
// version: 2
//! Desktop-owned application settings embedded in one generic binary composition profile.
const DESKTOP_APPLICATION_SCHEMA: &str =
include_str!("../../config/schemas/kb-app-demo-desktop.application.config.schema.json");
/// Desktop-owned settings for one selected composition profile.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub(crate) struct DesktopApplicationConfig {
/// Application display/name identity.
pub(crate) name: std::string::String,
/// Human-readable environment classification.
pub(crate) environment: std::string::String,
/// Desktop demo feature flags.
pub(crate) demo: crate::DesktopDemoConfig,
}
/// Desktop-owned demo feature flags.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
pub(crate) struct DesktopDemoConfig {
/// Enables live demo pages.
pub(crate) live_demo_enabled: bool,
/// Enables trading demo pages.
pub(crate) trading_demo_enabled: bool,
}
/// Parses and validates desktop-owned settings from one generic composition profile.
pub(crate) fn desktop_application_config(
profile: &ks_config::CompositionProfileConfig,
) -> ks_core::Result<DesktopApplicationConfig> {
let application = match profile.application.as_ref() {
std::option::Option::Some(value) => value,
std::option::Option::None => {
return std::result::Result::Err(ks_core::Error::new(
"desktop_application_config_missing",
profile.name.clone(),
));
},
};
match ks_config::validate_json_value_against_schema(
DESKTOP_APPLICATION_SCHEMA,
application,
"desktop_application_config_schema_validation_failed",
) {
std::result::Result::Ok(()) => (),
std::result::Result::Err(error) => return std::result::Result::Err(error),
}
return match serde_json::from_value::<DesktopApplicationConfig>(application.clone()) {
std::result::Result::Ok(value) => std::result::Result::Ok(value),
std::result::Result::Err(_) => std::result::Result::Err(ks_core::Error::new(
"desktop_application_config_decode_failed",
"desktop application configuration could not be decoded",
)),
};
}
#[cfg(test)]
mod tests {
#[test]
fn default_composition_contains_valid_desktop_application_fragments() {
let raw = include_str!("../../config/kb-app-demo-desktop.default.config.json");
let composition = match ks_config::parse_composition_json(raw) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => panic!("default composition must parse: {error}"),
};
for profile in &composition.profiles {
let result = super::desktop_application_config(profile);
assert!(result.is_ok());
}
}
#[test]
fn application_fragment_rejects_unknown_or_missing_fields() {
let profile = ks_config::CompositionProfileConfig {
name: "test".to_string(),
application: std::option::Option::Some(serde_json::json!({
"name": "kb-app-demo-desktop",
"environment": "test",
"demo": {
"live_demo_enabled": true,
"trading_demo_enabled": false
},
"secret": "must-not-be-accepted"
})),
logging_profile: std::option::Option::None,
transport_profile: std::option::Option::None,
listeners_profile: std::option::Option::None,
store_profile: std::option::Option::None,
wallet_profile: std::option::Option::None,
execution_profile: std::option::Option::None,
};
assert!(super::desktop_application_config(&profile).is_err());
}
}

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/lib.rs
// version: 34
// version: 37
//! Tauri desktop demo application for `khadhroony-bot3`.
@@ -29,7 +29,9 @@ mod demo_sql_diag;
mod demo_sql_pg_core;
mod demo_sql_pg_raw;
mod demo_sql_replay_candidates;
mod demo_transport;
mod demo_ws;
mod desktop_config;
mod frontend_log;
mod main_window;
mod splash;
@@ -64,8 +66,28 @@ pub(crate) use self::demo_backfill::demo_backfill_cancel;
pub(crate) use self::demo_backfill::demo_backfill_execute;
/// Returns endpoint roles, known programs and conservative backfill defaults.
pub(crate) use self::demo_backfill::demo_backfill_options;
/// Bounded internal configuration diagnostics shown by the configuration window.
pub(crate) use self::demo_config::DemoConfigDiagnosticPayload;
/// Bounded endpoint diagnostics shown by the configuration window.
pub(crate) use self::demo_config::DemoConfigEndpointDiagnosticPayload;
/// Bounded execution diagnostics shown by the configuration window.
pub(crate) use self::demo_config::DemoConfigExecutionDiagnosticPayload;
/// Configuration payload shown by the configuration window.
pub(crate) use self::demo_config::DemoConfigPayload;
/// Public desktop demo feature flags.
pub(crate) use self::demo_config::DemoConfigPublicDemoPayload;
/// Public endpoint identity shown by the configuration window.
pub(crate) use self::demo_config::DemoConfigPublicEndpointPayload;
/// Public listener summary shown by the configuration window.
pub(crate) use self::demo_config::DemoConfigPublicListenersPayload;
/// Explicit public configuration projection shown by the configuration window.
pub(crate) use self::demo_config::DemoConfigPublicPayload;
/// Bounded source-path diagnostics shown by the configuration window.
pub(crate) use self::demo_config::DemoConfigSourceDiagnosticPayload;
/// Bounded store diagnostics shown by the configuration window.
pub(crate) use self::demo_config::DemoConfigStoreDiagnosticPayload;
/// Bounded wallet diagnostics shown by the configuration window.
pub(crate) use self::demo_config::DemoConfigWalletDiagnosticPayload;
/// Builds the configuration payload from shared application state.
pub(crate) use self::demo_config::demo_config_payload;
/// Internal demo core extraction item.
@@ -228,6 +250,8 @@ pub(crate) use self::demo_execution_solana_core::select_devnet_profile;
pub(crate) use self::demo_execution_spl::DevnetSplValidationScenarioPayload;
/// Returns the complete ordered Devnet SPL validation inventory for milestone 0.4.6.
pub(crate) use self::demo_execution_spl::demo_execution_spl_validation_scenarios;
/// UI-safe HTTP endpoint snapshot.
pub(crate) use self::demo_http::DemoHttpEndpointPayload;
/// HTTP demo response payload.
pub(crate) use self::demo_http::DemoHttpExecutionPayload;
/// One selectable HTTP JSON-RPC method.
@@ -336,6 +360,10 @@ pub(crate) use self::demo_sql_replay_candidates::load_demo_sql_replay_entities;
pub(crate) use self::demo_sql_replay_candidates::load_demo_sql_replay_programs;
/// Loads bounded transaction replay candidates from PostgreSQL.
pub(crate) use self::demo_sql_replay_candidates::load_demo_sql_replay_transactions;
/// UI-safe endpoint role shared by HTTP and WebSocket diagnostics.
pub(crate) use self::demo_transport::DemoEndpointRolePayload;
/// UI-safe WebSocket endpoint snapshot.
pub(crate) use self::demo_ws::DemoWsEndpointPayload;
/// WebSocket execution response payload.
pub(crate) use self::demo_ws::DemoWsExecutionPayload;
/// WebSocket message emitted to the frontend.
@@ -368,6 +396,12 @@ pub(crate) use self::demo_ws::demo_ws_status;
pub(crate) use self::demo_ws::demo_ws_unsubscribe;
/// Disconnects the persistent WebSocket session during application shutdown.
pub(crate) use self::demo_ws::disconnect_demo_ws_app_state;
/// Desktop-owned application settings selected from the active composition profile.
pub(crate) use self::desktop_config::DesktopApplicationConfig;
/// Desktop-owned demo feature flags.
pub(crate) use self::desktop_config::DesktopDemoConfig;
/// Parses desktop-owned settings from one composition profile.
pub(crate) use self::desktop_config::desktop_application_config;
/// Frontend logging payload.
pub(crate) use self::frontend_log::FrontendLogPayload;
/// Emits one normalized frontend log event.

View File

@@ -1,5 +1,5 @@
// file: kb-app-demo-desktop/src/tauri.rs
// version: 37
// version: 38
//! Tauri runtime assembly and private command wrappers.
@@ -257,7 +257,7 @@ fn open_demo_http_window(
#[tauri::command]
fn demo_http_list_pool_clients(
state: tauri::State<'_, crate::AppState>,
) -> std::vec::Vec<ks_onchain_transport::HttpPoolClientSnapshot> {
) -> std::vec::Vec<crate::DemoHttpEndpointPayload> {
return crate::demo_http_list_pool_clients(state);
}
@@ -284,10 +284,7 @@ fn open_demo_ws_window(
#[tauri::command]
fn demo_ws_list_pool_clients(
state: tauri::State<'_, crate::AppState>,
) -> std::result::Result<
std::vec::Vec<ks_onchain_transport::WsPoolClientSnapshot>,
std::string::String,
> {
) -> std::result::Result<std::vec::Vec<crate::DemoWsEndpointPayload>, std::string::String> {
return crate::demo_ws_list_pool_clients(state);
}