v0.3.7-pre.003

This commit is contained in:
2026-09-02 10:05:36 +02:00
parent bc7ccd97a5
commit 862f40ad26
27 changed files with 673 additions and 76 deletions

View File

@@ -1,12 +1,12 @@
# file: Cargo.toml # file: Cargo.toml
# version: 417 # version: 418
[workspace] [workspace]
resolver = "3" resolver = "3"
members = ["crates/ksp-app-backfill-desk", "crates/ksp-app-config-desk", "crates/ksp-app-solprices-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-interface-lib", "crates/ksp-job-api", "crates/ksp-job-backfill-lib", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-program-api", "crates/ksp-store-api", "crates/ksp-store-lib", "crates/ksp-store-postgres-lib", "crates/ksp-wallet-lib"] members = ["crates/ksp-app-backfill-desk", "crates/ksp-app-config-desk", "crates/ksp-app-solprices-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-interface-lib", "crates/ksp-job-api", "crates/ksp-job-backfill-lib", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-program-api", "crates/ksp-store-api", "crates/ksp-store-lib", "crates/ksp-store-postgres-lib", "crates/ksp-wallet-lib"]
[workspace.package] [workspace.package]
version = "0.3.7-pre.2" version = "0.3.7-pre.3"
edition = "2024" edition = "2024"
license = "MIT" license = "MIT"
repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project" repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project"

View File

@@ -0,0 +1,66 @@
{
"format_version": 1,
"default_profile": "devnet",
"profiles": [
{
"profile_id": "devnet",
"documents": [
{
"component_id": "logging",
"file_id": "cfg.std.logging",
"profile_id": "supertrace"
},
{
"component_id": "transport",
"file_id": "cfg.std.transport",
"profile_id": "devnet_public"
},
{
"component_id": "store",
"file_id": "cfg.std.store",
"profile_id": "devnet"
}
]
},
{
"profile_id": "mainnet",
"documents": [
{
"component_id": "logging",
"file_id": "cfg.std.logging",
"profile_id": "console_info"
},
{
"component_id": "transport",
"file_id": "cfg.std.transport",
"profile_id": "mainnet_public"
},
{
"component_id": "store",
"file_id": "cfg.std.store",
"profile_id": "mainnet"
}
]
},
{
"profile_id": "testnet",
"documents": [
{
"component_id": "logging",
"file_id": "cfg.std.logging",
"profile_id": "console_info"
},
{
"component_id": "transport",
"file_id": "cfg.std.transport",
"profile_id": "publicnode_testnet"
},
{
"component_id": "store",
"file_id": "cfg.std.store",
"profile_id": "testnet"
}
]
}
]
}

View File

@@ -1,7 +1,7 @@
// file: crates/ksp-app-backfill-desk/src/bootstrap.rs // file: crates/ksp-app-backfill-desk/src/bootstrap.rs
// version: 1 // version: 2
//! Config and Logging bootstrap for the Backfill Desk scaffold. //! Config composite and Logging bootstrap for Backfill Desk.
/// Crate-internal Logging startup state shared by the application state. /// Crate-internal Logging startup state shared by the application state.
pub(crate) struct LoggingStartup { pub(crate) struct LoggingStartup {
@@ -43,7 +43,48 @@ pub(crate) fn config_management(arguments: &[std::ffi::OsString]) -> ksp_core_li
return std::result::Result::Ok(ksp_config_lib::ConfigManagement::new(engine)); return std::result::Result::Ok(ksp_config_lib::ConfigManagement::new(engine));
} }
/// Initializes Logging from the standard managed Config document, with the common Desk fallback policy. /// Loads the concrete Backfill Desk Config composite using its registered logical `file_id` and autonomous default profile.
pub(crate) fn load_backfill_desk_composite(management: &ksp_config_lib::ConfigManagement) -> ksp_core_lib::Result<ksp_config_lib::ResolvedConfigComposite> {
let file_id = ksp_config_lib::ConfigFileId::new(ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_BACKFILL_DESK);
let file_id = match file_id {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
return management.engine().load_resolved_composite(&file_id, std::option::Option::None);
}
/// Returns one required standard profile from the Backfill Desk composite after validating the referenced logical `file_id`.
pub(crate) fn required_composite_component_profile(
composite: &ksp_config_lib::ResolvedConfigComposite,
component_id: &str,
expected_file_id: &str,
) -> ksp_core_lib::Result<ksp_config_lib::ResolvedConfigProfile> {
let component = composite.component(component_id);
let component = match component {
std::option::Option::Some(value) => value,
std::option::Option::None => {
return std::result::Result::Err(
ksp_core_lib::Error::new(crate::ERROR_CODE_CONFIG_COMPOSITE_INVALID, "Backfill Desk composite is missing a required component")
.with_context("composite_file_id", composite.file_id().as_str())
.with_context("composite_profile_id", composite.profile_id())
.with_context("component_id", component_id),
);
},
};
if component.resolved().file_id().as_str() != expected_file_id {
return std::result::Result::Err(
ksp_core_lib::Error::new(crate::ERROR_CODE_CONFIG_COMPOSITE_INVALID, "Backfill Desk composite component references an unexpected Config document")
.with_context("composite_file_id", composite.file_id().as_str())
.with_context("composite_profile_id", composite.profile_id())
.with_context("component_id", component_id)
.with_context("expected_file_id", expected_file_id)
.with_context("actual_file_id", component.resolved().file_id().as_str()),
);
}
return std::result::Result::Ok(component.resolved().clone());
}
/// Initializes Logging from the Backfill Desk composite, with a trace-level development fallback.
pub(crate) fn initialize_logging( pub(crate) fn initialize_logging(
management: &ksp_config_lib::ConfigManagement, management: &ksp_config_lib::ConfigManagement,
runtime_identity: &ksp_logging_lib::LoggingRuntimeIdentity, runtime_identity: &ksp_logging_lib::LoggingRuntimeIdentity,
@@ -58,7 +99,7 @@ pub(crate) fn initialize_logging(
target: crate::TRACING_TARGET, target: crate::TRACING_TARGET,
domain = crate::TRACING_DOMAIN_BOOTSTRAP, domain = crate::TRACING_DOMAIN_BOOTSTRAP,
active_profile = active_profile_id.as_str(), active_profile = active_profile_id.as_str(),
"initialized Backfill Desk logging from managed configuration" "initialized Backfill Desk logging from composite-managed configuration"
); );
std::result::Result::Ok(LoggingStartup { std::result::Result::Ok(LoggingStartup {
guard, guard,
@@ -78,7 +119,7 @@ pub(crate) fn initialize_logging(
fn fallback_logging_settings() -> ksp_logging_lib::LoggingSettings { fn fallback_logging_settings() -> ksp_logging_lib::LoggingSettings {
return ksp_logging_lib::LoggingSettings::new( return ksp_logging_lib::LoggingSettings::new(
ksp_logging_lib::LogFilterLevel::Info, ksp_logging_lib::LogFilterLevel::Trace,
ksp_logging_lib::SpanEvents::Off, ksp_logging_lib::SpanEvents::Off,
std::option::Option::Some(ksp_logging_lib::ConsoleSettings::stderr()), std::option::Option::Some(ksp_logging_lib::ConsoleSettings::stderr()),
std::vec::Vec::new(), std::vec::Vec::new(),
@@ -91,7 +132,26 @@ fn resolve_logging_startup(management: &ksp_config_lib::ConfigManagement) -> Log
std::result::Result::Ok(value) => value, std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return fallback_startup_plan(error), std::result::Result::Err(error) => return fallback_startup_plan(error),
}; };
let resolved = management.engine().load_resolved_logging_config(std::option::Option::None, &environment); let composite = crate::load_backfill_desk_composite(management);
let composite = match composite {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return fallback_startup_plan(error),
};
let logging_profile = crate::required_composite_component_profile(&composite, crate::COMPOSITE_COMPONENT_ID_LOGGING, ksp_config_lib::FILE_ID_STD_LOGGING);
let logging_profile = match logging_profile {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return fallback_startup_plan(error),
};
let transport_profile =
crate::required_composite_component_profile(&composite, crate::COMPOSITE_COMPONENT_ID_TRANSPORT, ksp_config_lib::FILE_ID_STD_TRANSPORT);
if let std::result::Result::Err(error) = transport_profile {
return fallback_startup_plan(error);
}
let store_profile = crate::required_composite_component_profile(&composite, crate::COMPOSITE_COMPONENT_ID_STORE, ksp_config_lib::FILE_ID_STD_STORE);
if let std::result::Result::Err(error) = store_profile {
return fallback_startup_plan(error);
}
let resolved = management.engine().resolve_logging_config_profile(&logging_profile, &environment);
let resolved = match resolved { let resolved = match resolved {
std::result::Result::Ok(value) => value, std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return fallback_startup_plan(error), std::result::Result::Err(error) => return fallback_startup_plan(error),
@@ -135,7 +195,7 @@ fn initialize_planned_fallback_logging(
domain = crate::TRACING_DOMAIN_BOOTSTRAP, domain = crate::TRACING_DOMAIN_BOOTSTRAP,
error_domain = diagnostic.domain.as_str(), error_domain = diagnostic.domain.as_str(),
error_code = diagnostic.code.as_str(), error_code = diagnostic.code.as_str(),
"managed Logging configuration is unavailable; using transient in-memory fallback" "managed Logging configuration is unavailable; using transient trace-level development fallback"
); );
return std::result::Result::Ok(LoggingStartup { return std::result::Result::Ok(LoggingStartup {
guard, guard,
@@ -144,3 +204,12 @@ fn initialize_planned_fallback_logging(
startup_diagnostic: std::option::Option::Some(diagnostic), startup_diagnostic: std::option::Option::Some(diagnostic),
}); });
} }
#[cfg(test)]
mod tests {
#[test]
fn development_fallback_keeps_trace_level_enabled() {
let settings = super::fallback_logging_settings();
assert_eq!(settings.default_filter(), ksp_logging_lib::LogFilterLevel::Trace);
}
}

View File

@@ -1,8 +1,14 @@
// file: crates/ksp-app-backfill-desk/src/constants.rs // file: crates/ksp-app-backfill-desk/src/constants.rs
// version: 1 // version: 2
//! Application-owned tracing targets and domains. //! Application-owned tracing targets and domains.
/// Composite component identifier for Logging.
pub(crate) const COMPOSITE_COMPONENT_ID_LOGGING: &str = "logging";
/// Composite component identifier for Store.
pub(crate) const COMPOSITE_COMPONENT_ID_STORE: &str = "store";
/// Composite component identifier for Transport.
pub(crate) const COMPOSITE_COMPONENT_ID_TRANSPORT: &str = "transport";
/// Structured domain used while bootstrapping Config and Logging. /// Structured domain used while bootstrapping Config and Logging.
pub(crate) const TRACING_DOMAIN_BOOTSTRAP: &str = "backfill.bootstrap"; pub(crate) const TRACING_DOMAIN_BOOTSTRAP: &str = "backfill.bootstrap";
/// Structured domain used by technical frontend events. /// Structured domain used by technical frontend events.

View File

@@ -1,8 +1,10 @@
// file: crates/ksp-app-backfill-desk/src/errors.rs // file: crates/ksp-app-backfill-desk/src/errors.rs
// version: 1 // version: 2
//! Application-local error codes for Backfill Desk composition and desktop runtime surfaces. //! Application-local error codes for Backfill Desk composition and desktop runtime surfaces.
/// Backfill Desk composite configuration is missing or references an unexpected document.
pub(crate) const ERROR_CODE_CONFIG_COMPOSITE_INVALID: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("backfill_desk", "config_composite_invalid");
/// Shared Backfill Desk runtime state is internally inconsistent. /// Shared Backfill Desk runtime state is internally inconsistent.
pub(crate) const ERROR_CODE_APP_STATE_INVALID: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("backfill_desk", "app_state_invalid"); pub(crate) const ERROR_CODE_APP_STATE_INVALID: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("backfill_desk", "app_state_invalid");
/// Shared Backfill Desk runtime state cannot be locked safely. /// Shared Backfill Desk runtime state cannot be locked safely.

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-backfill-desk/src/lib.rs // file: crates/ksp-app-backfill-desk/src/lib.rs
// version: 1 // version: 2
//! Tauri desktop application scaffold for controlling and inspecting KSP RAW backfill jobs. //! Tauri desktop application scaffold for controlling and inspecting KSP RAW backfill jobs.
@@ -28,8 +28,18 @@ pub(crate) use self::app_state::AppState;
pub(crate) use self::bootstrap::LoggingStartup; pub(crate) use self::bootstrap::LoggingStartup;
/// Builds the Config management facade from the common KSP CLI bootstrap contract. /// Builds the Config management facade from the common KSP CLI bootstrap contract.
pub(crate) use self::bootstrap::config_management; pub(crate) use self::bootstrap::config_management;
/// Initializes the scaffold Logging runtime from standard Config, with a bounded in-memory fallback. /// Initializes Logging from the Backfill Desk composite, with a trace-level development fallback.
pub(crate) use self::bootstrap::initialize_logging; pub(crate) use self::bootstrap::initialize_logging;
/// Loads the concrete Backfill Desk Config composite.
pub(crate) use self::bootstrap::load_backfill_desk_composite;
/// Returns one required component profile from the Backfill Desk composite.
pub(crate) use self::bootstrap::required_composite_component_profile;
/// Composite component identifier for Logging.
pub(crate) use self::constants::COMPOSITE_COMPONENT_ID_LOGGING;
/// Composite component identifier for Store.
pub(crate) use self::constants::COMPOSITE_COMPONENT_ID_STORE;
/// Composite component identifier for Transport.
pub(crate) use self::constants::COMPOSITE_COMPONENT_ID_TRANSPORT;
/// Structured domain used while bootstrapping Config and Logging. /// Structured domain used while bootstrapping Config and Logging.
pub(crate) use self::constants::TRACING_DOMAIN_BOOTSTRAP; pub(crate) use self::constants::TRACING_DOMAIN_BOOTSTRAP;
/// Structured domain used by technical frontend events. /// Structured domain used by technical frontend events.
@@ -54,6 +64,8 @@ pub(crate) use self::dto_common::ShellStatusDto;
pub(crate) use self::errors::ERROR_CODE_APP_STATE_INVALID; pub(crate) use self::errors::ERROR_CODE_APP_STATE_INVALID;
/// Shared Backfill Desk runtime state cannot be locked safely. /// Shared Backfill Desk runtime state cannot be locked safely.
pub(crate) use self::errors::ERROR_CODE_APP_STATE_LOCK_FAILED; pub(crate) use self::errors::ERROR_CODE_APP_STATE_LOCK_FAILED;
/// Backfill Desk composite configuration is missing or references an unexpected document.
pub(crate) use self::errors::ERROR_CODE_CONFIG_COMPOSITE_INVALID;
/// Frontend logging requested an unsupported level. /// Frontend logging requested an unsupported level.
pub(crate) use self::errors::ERROR_CODE_FRONTEND_LOG_LEVEL_INVALID; pub(crate) use self::errors::ERROR_CODE_FRONTEND_LOG_LEVEL_INVALID;
/// Frontend logging requested a target outside the application whitelist. /// Frontend logging requested a target outside the application whitelist.

View File

@@ -1,11 +1,16 @@
// file: crates/ksp-app-backfill-desk/src/tauri.rs // file: crates/ksp-app-backfill-desk/src/tauri.rs
// version: 1 // version: 2
//! Tauri runtime assembly for the KSP Backfill desktop application. //! Tauri runtime assembly for the KSP Backfill desktop application.
/// Runs the Backfill desktop application. /// Runs the Backfill desktop application.
#[cfg_attr(mobile, tauri::mobile_entry_point)] #[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run(arguments: &[std::ffi::OsString]) -> ksp_core_lib::Result<()> { pub fn run(arguments: &[std::ffi::OsString]) -> ksp_core_lib::Result<()> {
let context = tauri::generate_context!();
let runtime_layout = configure_packaged_runtime(&context);
if let std::result::Result::Err(error) = runtime_layout {
return std::result::Result::Err(error);
}
let app_state = crate::AppState::initialize(arguments); let app_state = crate::AppState::initialize(arguments);
let app_state = match app_state { let app_state = match app_state {
std::result::Result::Ok(value) => value, std::result::Result::Ok(value) => value,
@@ -16,7 +21,7 @@ pub fn run(arguments: &[std::ffi::OsString]) -> ksp_core_lib::Result<()> {
builder = configure_plugins(builder); builder = configure_plugins(builder);
builder = configure_commands(builder); builder = configure_commands(builder);
builder = configure_setup(builder); builder = configure_setup(builder);
let run_result = builder.run(tauri::generate_context!()); let run_result = builder.run(context);
return match run_result { return match run_result {
std::result::Result::Ok(()) => std::result::Result::Ok(()), std::result::Result::Ok(()) => std::result::Result::Ok(()),
std::result::Result::Err(error) => std::result::Result::Err( std::result::Result::Err(error) => std::result::Result::Err(
@@ -26,6 +31,36 @@ pub fn run(arguments: &[std::ffi::OsString]) -> ksp_core_lib::Result<()> {
}; };
} }
fn configure_packaged_runtime(context: &tauri::Context<tauri::Wry>) -> ksp_core_lib::Result<()> {
if cfg!(debug_assertions) {
return std::result::Result::Ok(());
}
let resource_root = tauri::utils::platform::resource_dir(context.package_info(), &tauri::Env::default());
let resource_root = match resource_root {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
return std::result::Result::Err(
ksp_core_lib::Error::new(crate::ERROR_CODE_TAURI_RUNTIME_FAILED, "Cannot resolve packaged Tauri resource directory")
.with_context("tauri_error", error.to_string()),
);
},
};
let layout = ksp_config_lib::prepare_packaged_runtime(resource_root.as_path());
let layout = match layout {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let working_directory = std::env::set_current_dir(layout.runtime_root());
return match working_directory {
std::result::Result::Ok(()) => std::result::Result::Ok(()),
std::result::Result::Err(error) => std::result::Result::Err(
ksp_core_lib::Error::new(crate::ERROR_CODE_TAURI_RUNTIME_FAILED, "Cannot activate packaged KSP runtime directory")
.with_context("runtime_root", layout.runtime_root().to_string_lossy().into_owned())
.with_source(error),
),
};
}
fn configure_state(builder: tauri::Builder<tauri::Wry>, app_state: crate::AppState) -> tauri::Builder<tauri::Wry> { fn configure_state(builder: tauri::Builder<tauri::Wry>, app_state: crate::AppState) -> tauri::Builder<tauri::Wry> {
return builder.manage(app_state); return builder.manage(app_state);
} }

View File

@@ -50,6 +50,22 @@
"icon": [ "icon": [
"icons/favicon.png", "icons/favicon.png",
"icons/favicon.ico" "icons/favicon.ico"
] ],
"resources": {
"../../config/composite.ksp-app-backfill-desk.json": "config/composite.ksp-app-backfill-desk.json",
"../../config/composite.ksp-app-solprices-desk.json": "config/composite.ksp-app-solprices-desk.json",
"../../config/composite.ksp-app-wallet-desk.json": "config/composite.ksp-app-wallet-desk.json",
"../../config/std.logging.json": "config/std.logging.json",
"../../config/std.offchain_transport.json": "config/std.offchain_transport.json",
"../../config/std.store.json": "config/std.store.json",
"../../config/std.transport.json": "config/std.transport.json",
"../../config/std.wallet.json": "config/std.wallet.json",
"../../config/schemas/composite.schema.json": "config/schemas/composite.schema.json",
"../../config/schemas/std.logging.schema.json": "config/schemas/std.logging.schema.json",
"../../config/schemas/std.offchain_transport.schema.json": "config/schemas/std.offchain_transport.schema.json",
"../../config/schemas/std.store.schema.json": "config/schemas/std.store.schema.json",
"../../config/schemas/std.transport.schema.json": "config/schemas/std.transport.schema.json",
"../../config/schemas/std.wallet.schema.json": "config/schemas/std.wallet.schema.json"
}
} }
} }

View File

@@ -0,0 +1,88 @@
// file: crates/ksp-app-backfill-desk/tests/config_composition.rs
// version: 1
//! Config composite contracts for Backfill Desk pre.003.
#![forbid(unsafe_code)]
#![deny(unreachable_pub)]
#![warn(missing_docs)]
fn workspace_engine() -> ksp_core_lib::Result<ksp_config_lib::ConfigDocumentEngine> {
let workspace = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../..");
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();
return match registry {
std::result::Result::Ok(value) => std::result::Result::Ok(ksp_config_lib::ConfigDocumentEngine::new(bootstrap, value)),
std::result::Result::Err(error) => std::result::Result::Err(error),
};
}
fn assert_component(composite: &ksp_config_lib::ResolvedConfigComposite, component_id: &str, file_id: &str, profile_id: &str) {
let component = composite.component(component_id);
assert!(component.is_some(), "missing component {component_id}");
if let std::option::Option::Some(component) = component {
assert_eq!(component.resolved().file_id().as_str(), file_id);
assert_eq!(component.resolved().profile_id(), profile_id);
assert_eq!(component.resolved().selection_source(), ksp_config_lib::ConfigProfileSelectionSource::Composite);
}
}
#[test]
fn pre_003_default_composite_selects_trace_devnet_logging_transport_and_store() {
let engine = workspace_engine();
assert!(engine.is_ok(), "workspace Config engine should be constructible: {engine:?}");
let engine = match engine {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let file_id = ksp_config_lib::ConfigFileId::new(ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_BACKFILL_DESK);
assert!(file_id.is_ok(), "Backfill Desk composite file_id should be valid: {file_id:?}");
let file_id = match file_id {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let composite = engine.load_resolved_composite(&file_id, std::option::Option::None);
assert!(composite.is_ok(), "committed Backfill Desk composite should resolve: {composite:?}");
if let std::result::Result::Ok(composite) = composite {
assert_eq!(composite.profile_id(), "devnet");
assert_component(&composite, "logging", ksp_config_lib::FILE_ID_STD_LOGGING, "supertrace");
assert_component(&composite, "transport", ksp_config_lib::FILE_ID_STD_TRANSPORT, "devnet_public");
assert_component(&composite, "store", ksp_config_lib::FILE_ID_STD_STORE, "devnet");
let logging = composite.component("logging");
assert!(logging.is_some(), "Backfill Desk composite should expose Logging");
if let std::option::Option::Some(logging) = logging {
assert_eq!(logging.resolved().profile().get("default_filter").and_then(serde_json::Value::as_str), std::option::Option::Some("trace"));
}
}
}
#[test]
fn pre_003_named_profiles_keep_transport_and_store_network_selection_paired() {
let engine = workspace_engine();
assert!(engine.is_ok(), "workspace Config engine should be constructible: {engine:?}");
let engine = match engine {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
let file_id = ksp_config_lib::ConfigFileId::new(ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_BACKFILL_DESK);
let file_id = match file_id {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => return,
};
for (profile_id, logging_profile, transport_profile, store_profile) in
[("mainnet", "console_info", "mainnet_public", "mainnet"), ("testnet", "console_info", "publicnode_testnet", "testnet")]
{
let composite = engine.load_resolved_composite(&file_id, std::option::Option::Some(profile_id));
assert!(composite.is_ok(), "Backfill Desk composite profile {profile_id} should resolve: {composite:?}");
if let std::result::Result::Ok(composite) = composite {
assert_eq!(composite.profile_id(), profile_id);
assert_component(&composite, "logging", ksp_config_lib::FILE_ID_STD_LOGGING, logging_profile);
assert_component(&composite, "transport", ksp_config_lib::FILE_ID_STD_TRANSPORT, transport_profile);
assert_component(&composite, "store", ksp_config_lib::FILE_ID_STD_STORE, store_profile);
}
}
}

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-backfill-desk/tests/desktop_contract.rs // file: crates/ksp-app-backfill-desk/tests/desktop_contract.rs
// version: 1 // version: 2
//! Structural desktop contract checks for the Backfill Desk scaffold. //! Structural desktop contract checks for the Backfill Desk scaffold.
@@ -24,6 +24,16 @@ fn read_text(path: &std::path::Path) -> String {
}; };
} }
fn read_json(path: &std::path::Path) -> serde_json::Value {
let source = read_text(path);
let parsed = serde_json::from_str(source.as_str());
assert!(parsed.is_ok(), "unable to parse {}", path.display());
return match parsed {
std::result::Result::Ok(value) => value,
std::result::Result::Err(_) => serde_json::Value::Null,
};
}
fn read_bytes(path: &std::path::Path) -> std::vec::Vec<u8> { fn read_bytes(path: &std::path::Path) -> std::vec::Vec<u8> {
let source = std::fs::read(path); let source = std::fs::read(path);
assert!(source.is_ok(), "unable to read {}", path.display()); assert!(source.is_ok(), "unable to read {}", path.display());
@@ -119,3 +129,52 @@ fn pre_002_shell_and_splash_use_shared_frontend_tooling() {
assert!(splash.contains("Splash opacity animation started")); assert!(splash.contains("Splash opacity animation started"));
assert!(splash.contains("Backfill Desk splash frontend loaded")); assert!(splash.contains("Backfill Desk splash frontend loaded"));
} }
#[test]
fn pre_003_composite_packaging_follows_atomic_config_registry_contract() {
let root = app_root();
let config = read_json(root.join("tauri.conf.json").as_path());
let resources = config.get("bundle").and_then(|value| value.get("resources")).and_then(serde_json::Value::as_object);
assert!(resources.is_some());
let resources = match resources {
std::option::Option::Some(value) => value,
std::option::Option::None => return,
};
assert_eq!(resources.len(), 14);
for required in [
"../../config/composite.ksp-app-backfill-desk.json",
"../../config/composite.ksp-app-solprices-desk.json",
"../../config/composite.ksp-app-wallet-desk.json",
"../../config/std.logging.json",
"../../config/std.offchain_transport.json",
"../../config/std.store.json",
"../../config/std.transport.json",
"../../config/std.wallet.json",
"../../config/schemas/composite.schema.json",
"../../config/schemas/std.logging.schema.json",
"../../config/schemas/std.offchain_transport.schema.json",
"../../config/schemas/std.store.schema.json",
"../../config/schemas/std.transport.schema.json",
"../../config/schemas/std.wallet.schema.json",
] {
assert!(resources.contains_key(required), "missing packaged Config resource {required}");
}
let tauri = read_text(root.join("src/tauri.rs").as_path());
assert!(tauri.contains("prepare_packaged_runtime"));
assert!(tauri.contains("resource_dir"));
assert!(tauri.contains("set_current_dir"));
}
#[test]
fn pre_003_bootstrap_uses_composite_logging_without_opening_transport_or_store() {
let root = app_root();
let bootstrap = read_text(root.join("src/bootstrap.rs").as_path());
assert!(bootstrap.contains("FILE_ID_COMPOSITE_KSP_APP_BACKFILL_DESK"));
assert!(bootstrap.contains("COMPOSITE_COMPONENT_ID_LOGGING"));
assert!(bootstrap.contains("COMPOSITE_COMPONENT_ID_TRANSPORT"));
assert!(bootstrap.contains("COMPOSITE_COMPONENT_ID_STORE"));
assert!(bootstrap.contains("LogFilterLevel::Trace"));
for forbidden in ["HttpTransportPool", "Store::open", "BackfillJobRuntime", "BackfillRequest"] {
assert!(!bootstrap.contains(forbidden), "pre.003 opens later runtime surface {forbidden}");
}
}

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-backfill-desk/tests/desktop_security.rs // file: crates/ksp-app-backfill-desk/tests/desktop_security.rs
// version: 1 // version: 2
//! Security and dependency-boundary checks for the Backfill Desk scaffold. //! Security and dependency-boundary checks for the Backfill Desk scaffold.
@@ -113,3 +113,17 @@ fn pre_002_frontend_instrumentation_avoids_business_or_secret_payloads() {
assert!(!main.contains(forbidden)); assert!(!main.contains(forbidden));
} }
} }
#[test]
fn pre_003_keeps_config_only_composition_boundary() {
let root = app_root();
let manifest = read_text(root.join("Cargo.toml").as_path());
assert!(manifest.contains("ksp-config-lib.workspace = true"));
for forbidden in ["ksp-job-backfill-lib", "ksp-onchain-transport-lib", "ksp-store-lib", "ksp-store-api", "ksp-store-postgres-lib"] {
assert!(!manifest.contains(forbidden), "pre.003 opens a later-layer dependency: {forbidden}");
}
let bootstrap = read_text(root.join("src/bootstrap.rs").as_path());
assert!(bootstrap.contains("LogFilterLevel::Trace"));
assert!(!bootstrap.contains("HttpTransportPool"));
assert!(!bootstrap.contains("Store::open"));
}

View File

@@ -52,6 +52,7 @@
"icons/favicon.ico" "icons/favicon.ico"
], ],
"resources": { "resources": {
"../../config/composite.ksp-app-backfill-desk.json": "config/composite.ksp-app-backfill-desk.json",
"../../config/composite.ksp-app-solprices-desk.json": "config/composite.ksp-app-solprices-desk.json", "../../config/composite.ksp-app-solprices-desk.json": "config/composite.ksp-app-solprices-desk.json",
"../../config/composite.ksp-app-wallet-desk.json": "config/composite.ksp-app-wallet-desk.json", "../../config/composite.ksp-app-wallet-desk.json": "config/composite.ksp-app-wallet-desk.json",
"../../config/std.logging.json": "config/std.logging.json", "../../config/std.logging.json": "config/std.logging.json",

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-config-desk/tests/desktop_contract.rs // file: crates/ksp-app-config-desk/tests/desktop_contract.rs
// version: 11 // version: 12
//! Desktop build/shell contract audits for Config Desk. //! Desktop build/shell contract audits for Config Desk.
@@ -110,7 +110,11 @@ fn pre_018_packaged_runtime_bundles_config_resources_and_activates_shared_writab
let resources = tauri.pointer("/bundle/resources").and_then(serde_json::Value::as_object); let resources = tauri.pointer("/bundle/resources").and_then(serde_json::Value::as_object);
assert!(resources.is_some(), "packaged Config resources map must exist"); assert!(resources.is_some(), "packaged Config resources map must exist");
if let std::option::Option::Some(resources) = resources { if let std::option::Option::Some(resources) = resources {
assert_eq!(resources.len(), 13); assert_eq!(resources.len(), 14);
assert_eq!(
resources.get("../../config/composite.ksp-app-backfill-desk.json").and_then(serde_json::Value::as_str),
std::option::Option::Some("config/composite.ksp-app-backfill-desk.json"),
);
assert_eq!( assert_eq!(
resources.get("../../config/composite.ksp-app-solprices-desk.json").and_then(serde_json::Value::as_str), resources.get("../../config/composite.ksp-app-solprices-desk.json").and_then(serde_json::Value::as_str),
std::option::Option::Some("config/composite.ksp-app-solprices-desk.json"), std::option::Option::Some("config/composite.ksp-app-solprices-desk.json"),

View File

@@ -52,6 +52,7 @@
"icons/favicon.ico" "icons/favicon.ico"
], ],
"resources": { "resources": {
"../../config/composite.ksp-app-backfill-desk.json": "config/composite.ksp-app-backfill-desk.json",
"../../config/composite.ksp-app-solprices-desk.json": "config/composite.ksp-app-solprices-desk.json", "../../config/composite.ksp-app-solprices-desk.json": "config/composite.ksp-app-solprices-desk.json",
"../../config/composite.ksp-app-wallet-desk.json": "config/composite.ksp-app-wallet-desk.json", "../../config/composite.ksp-app-wallet-desk.json": "config/composite.ksp-app-wallet-desk.json",
"../../config/std.logging.json": "config/std.logging.json", "../../config/std.logging.json": "config/std.logging.json",

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-solprices-desk/tests/desktop_contract.rs // file: crates/ksp-app-solprices-desk/tests/desktop_contract.rs
// version: 10 // version: 11
//! Desktop scaffold, shared-template and Config packaging contract audits for SOL Prices Desk `0.2.12`. //! Desktop scaffold, shared-template and Config packaging contract audits for SOL Prices Desk `0.2.12`.
@@ -85,13 +85,17 @@ fn pre_002_package_is_mixed_lib_bin_and_frontend_is_scaffold_only() {
} }
#[test] #[test]
fn pre_004_packaging_contains_current_thirteen_config_resources() { fn pre_004_packaging_contains_current_fourteen_config_resources() {
let root = app_root(); let root = app_root();
let tauri = read_json(root.join("tauri.conf.json").as_path()); let tauri = read_json(root.join("tauri.conf.json").as_path());
let resources = tauri.pointer("/bundle/resources").and_then(serde_json::Value::as_object); let resources = tauri.pointer("/bundle/resources").and_then(serde_json::Value::as_object);
assert!(resources.is_some()); assert!(resources.is_some());
if let std::option::Option::Some(resources) = resources { if let std::option::Option::Some(resources) = resources {
assert_eq!(resources.len(), 13); assert_eq!(resources.len(), 14);
assert_eq!(
resources.get("../../config/composite.ksp-app-backfill-desk.json").and_then(serde_json::Value::as_str),
std::option::Option::Some("config/composite.ksp-app-backfill-desk.json"),
);
assert_eq!( assert_eq!(
resources.get("../../config/composite.ksp-app-solprices-desk.json").and_then(serde_json::Value::as_str), resources.get("../../config/composite.ksp-app-solprices-desk.json").and_then(serde_json::Value::as_str),
std::option::Option::Some("config/composite.ksp-app-solprices-desk.json"), std::option::Option::Some("config/composite.ksp-app-solprices-desk.json"),

View File

@@ -52,6 +52,7 @@
"icons/favicon.ico" "icons/favicon.ico"
], ],
"resources": { "resources": {
"../../config/composite.ksp-app-backfill-desk.json": "config/composite.ksp-app-backfill-desk.json",
"../../config/composite.ksp-app-solprices-desk.json": "config/composite.ksp-app-solprices-desk.json", "../../config/composite.ksp-app-solprices-desk.json": "config/composite.ksp-app-solprices-desk.json",
"../../config/composite.ksp-app-wallet-desk.json": "config/composite.ksp-app-wallet-desk.json", "../../config/composite.ksp-app-wallet-desk.json": "config/composite.ksp-app-wallet-desk.json",
"../../config/std.logging.json": "config/std.logging.json", "../../config/std.logging.json": "config/std.logging.json",

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-wallet-desk/tests/desktop_contract.rs // file: crates/ksp-app-wallet-desk/tests/desktop_contract.rs
// version: 31 // version: 32
//! Desktop build, shell and Config-status contract audits for Wallet Desk. //! Desktop build, shell and Config-status contract audits for Wallet Desk.
@@ -432,7 +432,11 @@ fn pre_018_packaged_runtime_bundles_config_resources_and_keeps_wallet_desk_versi
let resources = tauri.pointer("/bundle/resources").and_then(serde_json::Value::as_object); let resources = tauri.pointer("/bundle/resources").and_then(serde_json::Value::as_object);
assert!(resources.is_some(), "packaged Wallet Desk Config resources map must exist"); assert!(resources.is_some(), "packaged Wallet Desk Config resources map must exist");
if let std::option::Option::Some(resources) = resources { if let std::option::Option::Some(resources) = resources {
assert_eq!(resources.len(), 13); assert_eq!(resources.len(), 14);
assert_eq!(
resources.get("../../config/composite.ksp-app-backfill-desk.json").and_then(serde_json::Value::as_str),
std::option::Option::Some("config/composite.ksp-app-backfill-desk.json"),
);
assert_eq!( assert_eq!(
resources.get("../../config/composite.ksp-app-solprices-desk.json").and_then(serde_json::Value::as_str), resources.get("../../config/composite.ksp-app-solprices-desk.json").and_then(serde_json::Value::as_str),
std::option::Option::Some("config/composite.ksp-app-solprices-desk.json"), std::option::Option::Some("config/composite.ksp-app-solprices-desk.json"),

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-wallet-desk/tests/release_compliance.rs // file: crates/ksp-app-wallet-desk/tests/release_compliance.rs
// version: 10 // version: 11
//! Release-wide deterministic compliance canaries for Wallet Desk. //! Release-wide deterministic compliance canaries for Wallet Desk.
@@ -199,7 +199,7 @@ fn packaged_resources_include_only_registered_config_sources_and_schemas() {
std::option::Option::Some(value) => value, std::option::Option::Some(value) => value,
std::option::Option::None => return, std::option::Option::None => return,
}; };
assert_eq!(resources.len(), 13); assert_eq!(resources.len(), 14);
for (source, destination) in resources { for (source, destination) in resources {
let destination = destination.as_str(); let destination = destination.as_str();
assert!(destination.is_some(), "resource destination must be textual"); assert!(destination.is_some(), "resource destination must be textual");

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-config-lib/src/lib.rs // file: crates/ksp-config-lib/src/lib.rs
// version: 21 // version: 22
#![warn(missing_docs)] #![warn(missing_docs)]
#![deny(unreachable_pub)] #![deny(unreachable_pub)]
@@ -151,6 +151,8 @@ pub use self::registry::ConfigFileId;
pub use self::registry::ConfigFileKind; pub use self::registry::ConfigFileKind;
/// Registry of KSP-known logical Config files and their replaceable physical filenames. /// Registry of KSP-known logical Config files and their replaceable physical filenames.
pub use self::registry::ConfigFileRegistry; pub use self::registry::ConfigFileRegistry;
/// Default physical filename for the Backfill Desk composite configuration document.
pub use self::registry::DEFAULT_COMPOSITE_KSP_APP_BACKFILL_DESK_FILENAME;
/// Default physical filename for the SOL Prices Desk composite configuration document. /// Default physical filename for the SOL Prices Desk composite configuration document.
pub use self::registry::DEFAULT_COMPOSITE_KSP_APP_SOLPRICES_DESK_FILENAME; pub use self::registry::DEFAULT_COMPOSITE_KSP_APP_SOLPRICES_DESK_FILENAME;
/// Default physical filename for the Wallet Desk composite configuration document. /// Default physical filename for the Wallet Desk composite configuration document.
@@ -177,6 +179,8 @@ pub use self::registry::DEFAULT_STD_TRANSPORT_SCHEMA_FILENAME;
pub use self::registry::DEFAULT_STD_WALLET_FILENAME; pub use self::registry::DEFAULT_STD_WALLET_FILENAME;
/// Default physical filename for the standard Wallet JSON Schema document. /// Default physical filename for the standard Wallet JSON Schema document.
pub use self::registry::DEFAULT_STD_WALLET_SCHEMA_FILENAME; pub use self::registry::DEFAULT_STD_WALLET_SCHEMA_FILENAME;
/// Logical file identifier for the Backfill Desk composite configuration document.
pub use self::registry::FILE_ID_COMPOSITE_KSP_APP_BACKFILL_DESK;
/// Logical file identifier for the SOL Prices Desk composite configuration document. /// Logical file identifier for the SOL Prices Desk composite configuration document.
pub use self::registry::FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK; pub use self::registry::FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK;
/// Logical file identifier for the Wallet Desk composite configuration document. /// Logical file identifier for the Wallet Desk composite configuration document.

View File

@@ -1,8 +1,10 @@
// file: crates/ksp-config-lib/src/registry.rs // file: crates/ksp-config-lib/src/registry.rs
// version: 13 // version: 14
/// Bootstrap argument used to replace a known Config filename mapping. /// Bootstrap argument used to replace a known Config filename mapping.
pub const ARG_FILE_MAP: &str = "--filemap"; pub const ARG_FILE_MAP: &str = "--filemap";
/// Default physical filename for the Backfill Desk composite configuration document.
pub const DEFAULT_COMPOSITE_KSP_APP_BACKFILL_DESK_FILENAME: &str = "composite.ksp-app-backfill-desk.json";
/// Default physical filename for the SOL Prices Desk composite configuration document. /// Default physical filename for the SOL Prices Desk composite configuration document.
pub const DEFAULT_COMPOSITE_KSP_APP_SOLPRICES_DESK_FILENAME: &str = "composite.ksp-app-solprices-desk.json"; pub const DEFAULT_COMPOSITE_KSP_APP_SOLPRICES_DESK_FILENAME: &str = "composite.ksp-app-solprices-desk.json";
/// Default physical filename for the Wallet Desk composite configuration document. /// Default physical filename for the Wallet Desk composite configuration document.
@@ -29,6 +31,8 @@ pub const DEFAULT_STD_TRANSPORT_SCHEMA_FILENAME: &str = "std.transport.schema.js
pub const DEFAULT_STD_WALLET_FILENAME: &str = "std.wallet.json"; pub const DEFAULT_STD_WALLET_FILENAME: &str = "std.wallet.json";
/// Default physical filename for the standard Wallet JSON Schema document. /// Default physical filename for the standard Wallet JSON Schema document.
pub const DEFAULT_STD_WALLET_SCHEMA_FILENAME: &str = "std.wallet.schema.json"; pub const DEFAULT_STD_WALLET_SCHEMA_FILENAME: &str = "std.wallet.schema.json";
/// Logical file identifier for the Backfill Desk composite configuration document.
pub const FILE_ID_COMPOSITE_KSP_APP_BACKFILL_DESK: &str = "cfg.composite.ksp-app-backfill-desk";
/// Logical file identifier for the SOL Prices Desk composite configuration document. /// Logical file identifier for the SOL Prices Desk composite configuration document.
pub const FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK: &str = "cfg.composite.ksp-app-solprices-desk"; pub const FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK: &str = "cfg.composite.ksp-app-solprices-desk";
/// Logical file identifier for the Wallet Desk composite configuration document. /// Logical file identifier for the Wallet Desk composite configuration document.
@@ -160,6 +164,16 @@ pub struct ConfigFileRegistry {
impl ConfigFileRegistry { impl ConfigFileRegistry {
/// Creates the registry containing the KSP default file mappings known in the current release. /// Creates the registry containing the KSP default file mappings known in the current release.
pub fn defaults() -> ksp_core_lib::Result<Self> { pub fn defaults() -> ksp_core_lib::Result<Self> {
let backfill_composite = ConfigFileDescriptor::new(
FILE_ID_COMPOSITE_KSP_APP_BACKFILL_DESK,
ConfigFileKind::Config,
DEFAULT_COMPOSITE_KSP_APP_BACKFILL_DESK_FILENAME,
std::option::Option::Some(FILE_ID_SCHEMA_COMPOSITE),
);
let backfill_composite = match backfill_composite {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let solprices_composite = ConfigFileDescriptor::new( let solprices_composite = ConfigFileDescriptor::new(
FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK, FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK,
ConfigFileKind::Config, ConfigFileKind::Config,
@@ -271,6 +285,7 @@ impl ConfigFileRegistry {
std::result::Result::Err(error) => return std::result::Result::Err(error), std::result::Result::Err(error) => return std::result::Result::Err(error),
}; };
return crate::build_registry([ return crate::build_registry([
backfill_composite,
solprices_composite, solprices_composite,
wallet_composite, wallet_composite,
composite_schema, composite_schema,

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-config-lib/tests/public_api.rs // file: crates/ksp-config-lib/tests/public_api.rs
// version: 26 // version: 27
//! Integration tests for the public `ksp-config-lib` bootstrap, registry, JSON/profile/composite, environment-resolution, sensitivity, //! Integration tests for the public `ksp-config-lib` bootstrap, registry, JSON/profile/composite, environment-resolution, sensitivity,
//! Logging/Transport/Store adapters and management contracts. //! Logging/Transport/Store adapters and management contracts.
@@ -80,21 +80,22 @@ fn registry_descriptor_inventory_is_available_from_crate_root() {
assert!(registry.is_ok(), "public registry should remain constructible: {registry:?}"); assert!(registry.is_ok(), "public registry should remain constructible: {registry:?}");
if let std::result::Result::Ok(registry) = registry { if let std::result::Result::Ok(registry) = registry {
let descriptors: std::vec::Vec<&ksp_config_lib::ConfigFileDescriptor> = registry.descriptors().collect(); let descriptors: std::vec::Vec<&ksp_config_lib::ConfigFileDescriptor> = registry.descriptors().collect();
assert_eq!(descriptors.len(), 13); assert_eq!(descriptors.len(), 14);
assert_eq!(descriptors[0].file_id().as_str(), ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK); assert_eq!(descriptors[0].file_id().as_str(), ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_BACKFILL_DESK);
assert_eq!(descriptors[1].file_id().as_str(), ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK); assert_eq!(descriptors[1].file_id().as_str(), ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK);
assert_eq!(descriptors[2].file_id().as_str(), ksp_config_lib::FILE_ID_STD_LOGGING); assert_eq!(descriptors[2].file_id().as_str(), ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK);
assert_eq!(descriptors[3].file_id().as_str(), ksp_config_lib::FILE_ID_STD_OFFCHAIN_TRANSPORT); assert_eq!(descriptors[3].file_id().as_str(), ksp_config_lib::FILE_ID_STD_LOGGING);
assert_eq!(descriptors[4].file_id().as_str(), ksp_config_lib::FILE_ID_STD_STORE); assert_eq!(descriptors[4].file_id().as_str(), ksp_config_lib::FILE_ID_STD_OFFCHAIN_TRANSPORT);
assert_eq!(descriptors[5].file_id().as_str(), ksp_config_lib::FILE_ID_STD_TRANSPORT); assert_eq!(descriptors[5].file_id().as_str(), ksp_config_lib::FILE_ID_STD_STORE);
assert_eq!(descriptors[6].file_id().as_str(), ksp_config_lib::FILE_ID_STD_WALLET); assert_eq!(descriptors[6].file_id().as_str(), ksp_config_lib::FILE_ID_STD_TRANSPORT);
assert_eq!(descriptors[7].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_COMPOSITE); assert_eq!(descriptors[7].file_id().as_str(), ksp_config_lib::FILE_ID_STD_WALLET);
assert_eq!(descriptors[8].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_LOGGING); assert_eq!(descriptors[8].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_COMPOSITE);
assert_eq!(descriptors[9].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_OFFCHAIN_TRANSPORT); assert_eq!(descriptors[9].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_LOGGING);
assert_eq!(descriptors[10].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_STORE); assert_eq!(descriptors[10].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_OFFCHAIN_TRANSPORT);
assert_eq!(descriptors[11].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_TRANSPORT); assert_eq!(descriptors[11].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_STORE);
assert_eq!(descriptors[12].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_WALLET); assert_eq!(descriptors[12].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_TRANSPORT);
let schema_file_id = descriptors[6].schema_file_id(); assert_eq!(descriptors[13].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_WALLET);
let schema_file_id = descriptors[7].schema_file_id();
assert!(schema_file_id.is_some(), "public Wallet descriptor should preserve schema association"); assert!(schema_file_id.is_some(), "public Wallet descriptor should preserve schema association");
if let std::option::Option::Some(schema_file_id) = schema_file_id { if let std::option::Option::Some(schema_file_id) = schema_file_id {
assert_eq!(schema_file_id.as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_WALLET); assert_eq!(schema_file_id.as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_WALLET);
@@ -163,6 +164,8 @@ fn composite_schema_and_provenance_contracts_are_available_from_crate_root() {
assert_eq!(descriptor.kind(), ksp_config_lib::ConfigFileKind::Schema); assert_eq!(descriptor.kind(), ksp_config_lib::ConfigFileKind::Schema);
} }
} }
assert_eq!(ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_BACKFILL_DESK, "cfg.composite.ksp-app-backfill-desk");
assert_eq!(ksp_config_lib::DEFAULT_COMPOSITE_KSP_APP_BACKFILL_DESK_FILENAME, "composite.ksp-app-backfill-desk.json");
assert_eq!(ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK, "cfg.composite.ksp-app-solprices-desk"); assert_eq!(ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK, "cfg.composite.ksp-app-solprices-desk");
assert_eq!(ksp_config_lib::DEFAULT_COMPOSITE_KSP_APP_SOLPRICES_DESK_FILENAME, "composite.ksp-app-solprices-desk.json"); assert_eq!(ksp_config_lib::DEFAULT_COMPOSITE_KSP_APP_SOLPRICES_DESK_FILENAME, "composite.ksp-app-solprices-desk.json");
assert_ne!(ksp_config_lib::ConfigProfileSelectionSource::Composite, ksp_config_lib::ConfigProfileSelectionSource::Explicit); assert_ne!(ksp_config_lib::ConfigProfileSelectionSource::Composite, ksp_config_lib::ConfigProfileSelectionSource::Explicit);

View File

@@ -0,0 +1,66 @@
{
"format_version": 1,
"default_profile": "devnet",
"profiles": [
{
"profile_id": "devnet",
"documents": [
{
"component_id": "logging",
"file_id": "cfg.std.logging",
"profile_id": "supertrace"
},
{
"component_id": "transport",
"file_id": "cfg.std.transport",
"profile_id": "devnet_public"
},
{
"component_id": "store",
"file_id": "cfg.std.store",
"profile_id": "devnet"
}
]
},
{
"profile_id": "mainnet",
"documents": [
{
"component_id": "logging",
"file_id": "cfg.std.logging",
"profile_id": "console_info"
},
{
"component_id": "transport",
"file_id": "cfg.std.transport",
"profile_id": "mainnet_public"
},
{
"component_id": "store",
"file_id": "cfg.std.store",
"profile_id": "mainnet"
}
]
},
{
"profile_id": "testnet",
"documents": [
{
"component_id": "logging",
"file_id": "cfg.std.logging",
"profile_id": "console_info"
},
{
"component_id": "transport",
"file_id": "cfg.std.transport",
"profile_id": "publicnode_testnet"
},
{
"component_id": "store",
"file_id": "cfg.std.store",
"profile_id": "testnet"
}
]
}
]
}

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-config-lib/unit_tests/registry.rs // file: crates/ksp-config-lib/unit_tests/registry.rs
// version: 11 // version: 12
#[test] #[test]
fn descriptors_expose_complete_registry_in_deterministic_file_id_order() { fn descriptors_expose_complete_registry_in_deterministic_file_id_order() {
@@ -7,27 +7,27 @@ fn descriptors_expose_complete_registry_in_deterministic_file_id_order() {
assert!(registry.is_ok(), "default registry should be valid: {registry:?}"); assert!(registry.is_ok(), "default registry should be valid: {registry:?}");
if let std::result::Result::Ok(registry) = registry { if let std::result::Result::Ok(registry) = registry {
let descriptors: std::vec::Vec<&crate::ConfigFileDescriptor> = registry.descriptors().collect(); let descriptors: std::vec::Vec<&crate::ConfigFileDescriptor> = registry.descriptors().collect();
assert_eq!(descriptors.len(), 13); assert_eq!(descriptors.len(), 14);
assert_eq!(descriptors[0].file_id().as_str(), crate::FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK); assert_eq!(descriptors[0].file_id().as_str(), crate::FILE_ID_COMPOSITE_KSP_APP_BACKFILL_DESK);
assert_eq!(descriptors[0].filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_KSP_APP_SOLPRICES_DESK_FILENAME)); assert_eq!(descriptors[0].filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_KSP_APP_BACKFILL_DESK_FILENAME));
assert_eq!(descriptors[0].schema_file_id().map(crate::ConfigFileId::as_str), std::option::Option::Some(crate::FILE_ID_SCHEMA_COMPOSITE)); assert_eq!(descriptors[0].schema_file_id().map(crate::ConfigFileId::as_str), std::option::Option::Some(crate::FILE_ID_SCHEMA_COMPOSITE));
assert_eq!(descriptors[1].file_id().as_str(), crate::FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK); assert_eq!(descriptors[1].file_id().as_str(), crate::FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK);
assert_eq!(descriptors[1].filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_KSP_APP_WALLET_DESK_FILENAME)); assert_eq!(descriptors[2].file_id().as_str(), crate::FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK);
assert_eq!(descriptors[2].file_id().as_str(), crate::FILE_ID_STD_LOGGING); assert_eq!(descriptors[3].file_id().as_str(), crate::FILE_ID_STD_LOGGING);
assert_eq!(descriptors[3].file_id().as_str(), crate::FILE_ID_STD_OFFCHAIN_TRANSPORT); assert_eq!(descriptors[4].file_id().as_str(), crate::FILE_ID_STD_OFFCHAIN_TRANSPORT);
assert_eq!(descriptors[4].file_id().as_str(), crate::FILE_ID_STD_STORE); assert_eq!(descriptors[5].file_id().as_str(), crate::FILE_ID_STD_STORE);
assert_eq!(descriptors[5].file_id().as_str(), crate::FILE_ID_STD_TRANSPORT); assert_eq!(descriptors[6].file_id().as_str(), crate::FILE_ID_STD_TRANSPORT);
assert_eq!(descriptors[6].file_id().as_str(), crate::FILE_ID_STD_WALLET); assert_eq!(descriptors[7].file_id().as_str(), crate::FILE_ID_STD_WALLET);
assert_eq!(descriptors[6].filename(), std::path::Path::new(crate::DEFAULT_STD_WALLET_FILENAME)); assert_eq!(descriptors[7].filename(), std::path::Path::new(crate::DEFAULT_STD_WALLET_FILENAME));
assert_eq!(descriptors[6].schema_file_id().map(crate::ConfigFileId::as_str), std::option::Option::Some(crate::FILE_ID_SCHEMA_STD_WALLET)); assert_eq!(descriptors[7].schema_file_id().map(crate::ConfigFileId::as_str), std::option::Option::Some(crate::FILE_ID_SCHEMA_STD_WALLET));
assert_eq!(descriptors[7].file_id().as_str(), crate::FILE_ID_SCHEMA_COMPOSITE); assert_eq!(descriptors[8].file_id().as_str(), crate::FILE_ID_SCHEMA_COMPOSITE);
assert_eq!(descriptors[8].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_LOGGING); assert_eq!(descriptors[9].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_LOGGING);
assert_eq!(descriptors[9].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_OFFCHAIN_TRANSPORT); assert_eq!(descriptors[10].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_OFFCHAIN_TRANSPORT);
assert_eq!(descriptors[10].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_STORE); assert_eq!(descriptors[11].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_STORE);
assert_eq!(descriptors[11].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_TRANSPORT); assert_eq!(descriptors[12].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_TRANSPORT);
assert_eq!(descriptors[12].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_WALLET); assert_eq!(descriptors[13].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_WALLET);
assert!(descriptors[0..7].iter().all(|descriptor| return descriptor.kind() == crate::ConfigFileKind::Config)); assert!(descriptors[0..8].iter().all(|descriptor| return descriptor.kind() == crate::ConfigFileKind::Config));
assert!(descriptors[7..13].iter().all(|descriptor| return descriptor.kind() == crate::ConfigFileKind::Schema)); assert!(descriptors[8..14].iter().all(|descriptor| return descriptor.kind() == crate::ConfigFileKind::Schema));
} }
} }
@@ -362,27 +362,41 @@ fn absolute_fixture_path() -> std::path::PathBuf {
} }
#[test] #[test]
fn defaults_register_generic_composite_schema_and_both_runtime_composites() { fn defaults_register_generic_composite_schema_and_three_runtime_composites() {
let registry = crate::ConfigFileRegistry::defaults(); let registry = crate::ConfigFileRegistry::defaults();
let schema_id = crate::ConfigFileId::new(crate::FILE_ID_SCHEMA_COMPOSITE); let schema_id = crate::ConfigFileId::new(crate::FILE_ID_SCHEMA_COMPOSITE);
let backfill_id = crate::ConfigFileId::new(crate::FILE_ID_COMPOSITE_KSP_APP_BACKFILL_DESK);
let solprices_id = crate::ConfigFileId::new(crate::FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK); let solprices_id = crate::ConfigFileId::new(crate::FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK);
let wallet_id = crate::ConfigFileId::new(crate::FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK); let wallet_id = crate::ConfigFileId::new(crate::FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK);
assert!(registry.is_ok(), "default registry should be valid: {registry:?}"); assert!(registry.is_ok(), "default registry should be valid: {registry:?}");
assert!(schema_id.is_ok(), "composite schema file_id should be valid: {schema_id:?}"); assert!(schema_id.is_ok(), "composite schema file_id should be valid: {schema_id:?}");
assert!(backfill_id.is_ok(), "Backfill Desk composite runtime file_id should be valid: {backfill_id:?}");
assert!(solprices_id.is_ok(), "SOL Prices Desk composite runtime file_id should be valid: {solprices_id:?}"); assert!(solprices_id.is_ok(), "SOL Prices Desk composite runtime file_id should be valid: {solprices_id:?}");
assert!(wallet_id.is_ok(), "Wallet Desk composite runtime file_id should be valid: {wallet_id:?}"); assert!(wallet_id.is_ok(), "Wallet Desk composite runtime file_id should be valid: {wallet_id:?}");
if let (std::result::Result::Ok(registry), std::result::Result::Ok(schema_id), std::result::Result::Ok(solprices_id), std::result::Result::Ok(wallet_id)) = if let (
(registry, schema_id, solprices_id, wallet_id) std::result::Result::Ok(registry),
std::result::Result::Ok(schema_id),
std::result::Result::Ok(backfill_id),
std::result::Result::Ok(solprices_id),
std::result::Result::Ok(wallet_id),
) = (registry, schema_id, backfill_id, solprices_id, wallet_id)
{ {
let schema = registry.descriptor(&schema_id); let schema = registry.descriptor(&schema_id);
let backfill = registry.descriptor(&backfill_id);
let solprices = registry.descriptor(&solprices_id); let solprices = registry.descriptor(&solprices_id);
let wallet = registry.descriptor(&wallet_id); let wallet = registry.descriptor(&wallet_id);
assert!(schema.is_ok(), "generic composite schema should be registered: {schema:?}"); assert!(schema.is_ok(), "generic composite schema should be registered: {schema:?}");
assert!(backfill.is_ok(), "Backfill Desk runtime composite should be registered: {backfill:?}");
assert!(solprices.is_ok(), "SOL Prices Desk runtime composite should be registered: {solprices:?}"); assert!(solprices.is_ok(), "SOL Prices Desk runtime composite should be registered: {solprices:?}");
assert!(wallet.is_ok(), "Wallet Desk runtime composite should be registered: {wallet:?}"); assert!(wallet.is_ok(), "Wallet Desk runtime composite should be registered: {wallet:?}");
if let (std::result::Result::Ok(schema), std::result::Result::Ok(solprices), std::result::Result::Ok(wallet)) = (schema, solprices, wallet) { if let (std::result::Result::Ok(schema), std::result::Result::Ok(backfill), std::result::Result::Ok(solprices), std::result::Result::Ok(wallet)) =
(schema, backfill, solprices, wallet)
{
assert_eq!(schema.kind(), crate::ConfigFileKind::Schema); assert_eq!(schema.kind(), crate::ConfigFileKind::Schema);
assert_eq!(schema.filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_SCHEMA_FILENAME)); assert_eq!(schema.filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_SCHEMA_FILENAME));
assert_eq!(backfill.kind(), crate::ConfigFileKind::Config);
assert_eq!(backfill.filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_KSP_APP_BACKFILL_DESK_FILENAME));
assert_eq!(backfill.schema_file_id(), std::option::Option::Some(&schema_id));
assert_eq!(solprices.kind(), crate::ConfigFileKind::Config); assert_eq!(solprices.kind(), crate::ConfigFileKind::Config);
assert_eq!(solprices.filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_KSP_APP_SOLPRICES_DESK_FILENAME)); assert_eq!(solprices.filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_KSP_APP_SOLPRICES_DESK_FILENAME));
assert_eq!(solprices.schema_file_id(), std::option::Option::Some(&schema_id)); assert_eq!(solprices.schema_file_id(), std::option::Option::Some(&schema_id));

83
deltas/0.3.7/pre.003.md Normal file
View File

@@ -0,0 +1,83 @@
<!-- file: deltas/0.3.7/pre.003.md -->
<!-- version: 1 -->
# Delta 0.3.7-pre.003 — Config composite et packaging Backfill Desk
## Base
`0.3.7-pre.002` validée par le gate opérateur fourni : audits Rust/Markdown, `cargo check --workspace`, Clippy et tests `ksp-app-backfill-desk` propres.
## Objectif
Introduire le composite Config de Backfill Desk, brancher son bootstrap Config/Logging et le packaging release, tout en conservant Transport, Store et Backfill runtime fermés. Pendant le développement du Desk, rendre son tracing volontairement verbeux via `supertrace` sur le profil `devnet` et `trace` pour le fallback local.
## Fichiers ajoutés
- `config/composite.ksp-app-backfill-desk.json` ;
- `crates/ksp-config-lib/unit_tests/fixtures/composite.ksp-app-backfill-desk.json` ;
- `crates/ksp-app-backfill-desk/tests/config_composition.rs` ;
- `deltas/0.3.7/pre.003.md`.
## Fichiers modifiés
- `Cargo.toml` ;
- `crates/ksp-config-lib/src/lib.rs` ;
- `crates/ksp-config-lib/src/registry.rs` ;
- `crates/ksp-config-lib/tests/public_api.rs` ;
- `crates/ksp-config-lib/unit_tests/registry.rs` ;
- `crates/ksp-app-backfill-desk/src/bootstrap.rs` ;
- `crates/ksp-app-backfill-desk/src/constants.rs` ;
- `crates/ksp-app-backfill-desk/src/errors.rs` ;
- `crates/ksp-app-backfill-desk/src/lib.rs` ;
- `crates/ksp-app-backfill-desk/src/tauri.rs` ;
- `crates/ksp-app-backfill-desk/tauri.conf.json` ;
- `crates/ksp-app-backfill-desk/tests/desktop_contract.rs` ;
- `crates/ksp-app-backfill-desk/tests/desktop_security.rs` ;
- `crates/ksp-app-config-desk/tauri.conf.json` ;
- `crates/ksp-app-config-desk/tests/desktop_contract.rs` ;
- `crates/ksp-app-solprices-desk/tauri.conf.json` ;
- `crates/ksp-app-solprices-desk/tests/desktop_contract.rs` ;
- `crates/ksp-app-wallet-desk/tauri.conf.json` ;
- `crates/ksp-app-wallet-desk/tests/desktop_contract.rs` ;
- `crates/ksp-app-wallet-desk/tests/release_compliance.rs` ;
- `docs/plans/028-V0_3_7_BACKFILL_DESK_PLAN.md` ;
- `docs/validation/024-V0_3_7_BACKFILL_DESK.md`.
## Fichiers supprimés
Aucun.
## Décisions
- Le composite Backfill Desk possède `devnet`, `mainnet` et `testnet`, avec `devnet` par défaut.
- `devnet` sélectionne Logging `supertrace`; le fallback local de Backfill Desk utilise `LogFilterLevel::Trace` pendant le développement. Aucun niveau des autres Desk n'est modifié.
- Le bootstrap valide les composants Logging/Transport/Store mais ne résout que Logging en `pre.003`; Transport et Store restent fermés jusqu'aux tranches prévues.
- `prepare_packaged_runtime()` traverse tout le registre Config. L'ajout du composite porte ce registre à 14 descriptors : les quatre Desk embarquent donc atomiquement les 14 resources Config/schema.
- La présence de documents Wallet/offchain dans le bundle Backfill satisfait uniquement le contrat de packaging partagé ; elle ne crée ni dépendance Rust ni capability frontend correspondante.
## Validations exécutées
- `python3 scripts/audit_rust_workspace_rules.py` : propre, zéro candidat d'export ;
- `python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.3.7` : propre, 270 tableaux / 150 fichiers ;
- parsing JSON : 7 manifests/resources contrôlés ;
- parsing TOML : `Cargo.toml` racine et manifeste Backfill Desk contrôlés ;
- validation JSON Schema : composite source et fixture conformes à `composite.schema.json` ;
- profils composite : `devnet/mainnet/testnet` et sélections Logging/Transport/Store exacts ;
- packaging : 14/14 resources Config/schema identiques dans les quatre Desk ;
- frontend : dépendances minimales et `devDependencies` du gabarit préservées ;
- tracing développement : `supertrace` via le composite `devnet`, `Trace` en fallback ;
- frontière `pre.003` : aucune dépendance/runtime Transport, Store ou Backfill ouverte.
- diff `pre.002 -> pre.003` : 4 fichiers ajoutés, 22 fichiers modifiés, aucune suppression.
## Validations non exécutées
- `cargo fmt --all` ;
- `cargo check --workspace` ;
- `cargo clippy --workspace --all-targets` ;
- suites Cargo de `ksp-config-lib` et des quatre Desk.
L'exécutable `cargo`/`rustfmt` n'est pas disponible dans le sandbox d'assemblage.
## Questions ouvertes
Aucune question bloquante. Le niveau de tracing verbeux est explicitement temporaire pour la phase de développement et devra être réévalué avant la publication stable.

View File

@@ -1,5 +1,5 @@
<!-- file: docs/plans/028-V0_3_7_BACKFILL_DESK_PLAN.md --> <!-- file: docs/plans/028-V0_3_7_BACKFILL_DESK_PLAN.md -->
<!-- version: 2 --> <!-- version: 3 -->
# Plan v0.3.7 — Backfill Desk # Plan v0.3.7 — Backfill Desk
@@ -148,7 +148,7 @@ Au bootstrap, l'application charge le composite, résout Logging/Transport/Store
Les rôles présentés à l'UI sont dérivés des snapshots/settings Transport, dédupliqués, puis validés côté Rust comme capables de sélectionner à la fois `getSignaturesForAddress` et `getTransaction`. Le rôle `default` est actuellement le seul rôle des profils standard, mais il n'est pas codé en dur comme contrat du Desk. Les rôles présentés à l'UI sont dérivés des snapshots/settings Transport, dédupliqués, puis validés côté Rust comme capables de sélectionner à la fois `getSignaturesForAddress` et `getTransaction`. Le rôle `default` est actuellement le seul rôle des profils standard, mais il n'est pas codé en dur comme contrat du Desk.
Les resources bundle minimales sont le composite Backfill Desk, `std.logging.json`, `std.transport.json`, `std.store.json` et leurs schemas, plus `composite.schema.json`. Les documents Wallet/offchain ne sont pas embarqués sans besoin démontré. Le packaging Config suit le contrat atomique déjà détenu par `ksp-config-lib::prepare_packaged_runtime()` : il traverse l'intégralité de `ConfigFileRegistry::defaults()`. L'ajout du composite Backfill Desk fait donc passer le registre de 13 à 14 descriptors et impose que les quatre applications Desk qui utilisent ce packaging embarquent les 14 resources Config/schema du registre. Backfill Desk embarque ainsi également les documents Wallet/offchain sans les consommer au runtime ; leur présence satisfait le contrat de packaging partagé et n'ouvre aucune dépendance, permission frontend ou responsabilité métier supplémentaire.
## 8. Dependency map ## 8. Dependency map
@@ -235,7 +235,7 @@ Créer package lib+bin, shell/splash/tracing/capability, frontend minimal, ports
### pre.003 — Config composite et packaging ### pre.003 — Config composite et packaging
Ajouter composite Backfill Desk, resources minimales, bootstrap Config/Logging et canaries packaging/composition sans encore ouvrir réseau/Store réel. Ajouter le composite Backfill Desk et l'enregistrer dans Config, mettre à jour atomiquement les quatre bundles Desk vers les 14 resources du registre, puis brancher le bootstrap Config/Logging et ses canaries sans encore ouvrir Transport/Store réel. Pendant le développement de l'application, `devnet` sélectionne le profil Logging `supertrace` et le fallback local Backfill Desk reste au niveau `trace`; ce choix est local au Desk et devra être resserré avant publication stable.
### pre.004 — Transport readiness ### pre.004 — Transport readiness

View File

@@ -1,5 +1,5 @@
<!-- file: docs/validation/024-V0_3_7_BACKFILL_DESK.md --> <!-- file: docs/validation/024-V0_3_7_BACKFILL_DESK.md -->
<!-- version: 2 --> <!-- version: 3 -->
# Validation v0.3.7 — Backfill Desk # Validation v0.3.7 — Backfill Desk
@@ -95,7 +95,7 @@ Le journal opérateur fourni rapporte `cargo clean`, `cargo fmt`, audits Rust/Ma
- [ ] Package Rust lib + bin conforme. - [ ] Package Rust lib + bin conforme.
- [ ] Ports Vite/HMR 1436/1437 stricts. - [ ] Ports Vite/HMR 1436/1437 stricts.
- [ ] Splash/main + tracing conformes. - [ ] Splash/main + tracing conformes.
- [ ] Composite Backfill Desk packagé et valide. - [X] Composite Backfill Desk packagé et valide.
- [ ] Transport readiness et role inventory sûrs. - [ ] Transport readiness et role inventory sûrs.
- [ ] Store readiness et cohérence réseau. - [ ] Store readiness et cohérence réseau.
- [ ] Quatre scopes + commitments + bornes mappés. - [ ] Quatre scopes + commitments + bornes mappés.
@@ -135,3 +135,33 @@ Contraintes de gabarit vérifiées statiquement : mêmes assets splash/logo/DOS
- [ ] typecheck npm complet / build Tauri : non exécutés dans le sandbox. - [ ] typecheck npm complet / build Tauri : non exécutés dans le sandbox.
Le contrôle TypeScript local est syntaxique avec le compilateur global disponible ; il ne remplace pas le typecheck complet avec dépendances npm et bindings TS-RS générés. Toute correction révélée par le gate opérateur reste dans la lane `pre.002-fix.NNN`. Le contrôle TypeScript local est syntaxique avec le compilateur global disponible ; il ne remplace pas le typecheck complet avec dépendances npm et bindings TS-RS générés. Toute correction révélée par le gate opérateur reste dans la lane `pre.002-fix.NNN`.
## 10. pre.003 — composite Config et packaging
Le composite `cfg.composite.ksp-app-backfill-desk` est enregistré dans `ksp-config-lib` avec `devnet` par défaut. Il sélectionne `supertrace + devnet_public + devnet`, tandis que `mainnet` et `testnet` conservent des couples Transport/Store cohérents. Le bootstrap Backfill Desk valide les trois composants requis mais ne résout encore que Logging : aucun `HttpTransportPool`, `Store::open`, `BackfillRequest` ou `BackfillJobRuntime` n'est ouvert dans cette tranche.
Le niveau de développement est volontairement verbeux pour cette application : `devnet` utilise `supertrace`, et le fallback Logging propre à Backfill Desk utilise `LogFilterLevel::Trace`. Les autres applications Desk ne changent pas de profil Logging.
La découverte du contrat réel de `prepare_packaged_runtime()` a réconcilié le plan : la fonction traverse tout `ConfigFileRegistry::defaults()`. Le registre compte désormais 14 descriptors, de sorte que Config Desk, Wallet Desk, SOL Prices Desk et Backfill Desk embarquent toutes les 14 resources Config/schema. Les documents Wallet/offchain présents dans le bundle Backfill ne sont pas consommés par son runtime et n'élargissent ni ses capabilities ni ses dépendances Rust.
### Gate pre.002 opérateur acquis
- [X] audits Rust et Markdown propres ;
- [X] `cargo check --workspace` propre ;
- [X] `cargo clippy --workspace --all-targets` propre ;
- [X] `cargo test -p ksp-app-backfill-desk` : 12 unitaires + 5 desktop contract + 4 desktop security + 1 public API, aucun échec.
### Gate statique local pre.003
- [X] composite Backfill Desk ajouté au source Config et aux fixtures Config ;
- [X] registre Config porté à 14 descriptors avec exports publics associés ;
- [X] profils `devnet/mainnet/testnet` et références Logging/Transport/Store couplés conformément au plan ;
- [X] les quatre `tauri.conf.json` Desk embarquent le registre Config complet de 14 resources ;
- [X] release packaging Backfill Desk appelle `prepare_packaged_runtime()` avant l'initialisation applicative ;
- [X] bootstrap Backfill valide Logging/Transport/Store puis ne résout que Logging ;
- [X] niveau de développement Backfill Desk verrouillé à `supertrace` via Config et `trace` en fallback ;
- [X] aucune dépendance `ksp-job-backfill-lib`, `ksp-onchain-transport-lib`, `ksp-store-lib` ou backend Store ajoutée au manifeste Backfill Desk ;
- [X] audit Rust workspace propre, zéro candidat d'export ;
- [X] audit Markdown propre : 270 tableaux / 150 fichiers ;
- [X] parsing JSON/TOML, validation JSON Schema et audit structurel Config/package propres ;
- [ ] `cargo fmt/check/clippy/test` pre.003 : à exécuter par l'opérateur, `cargo`/`rustfmt` absents du sandbox.