v0.2.12-pre.003
This commit is contained in:
@@ -1,12 +1,12 @@
|
|||||||
# file: Cargo.toml
|
# file: Cargo.toml
|
||||||
# version: 288
|
# version: 289
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
members = ["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-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-wallet-lib"]
|
members = ["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-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-wallet-lib"]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.2.12-pre.2.fix.1"
|
version = "0.2.12-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"
|
||||||
|
|||||||
51
config/composite.ksp-app-solprices-desk.json
Normal file
51
config/composite.ksp-app-solprices-desk.json
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"format_version": 1,
|
||||||
|
"default_profile": "public_keyless",
|
||||||
|
"profiles": [
|
||||||
|
{
|
||||||
|
"profile_id": "public_keyless",
|
||||||
|
"documents": [
|
||||||
|
{
|
||||||
|
"component_id": "logging",
|
||||||
|
"file_id": "cfg.std.logging",
|
||||||
|
"profile_id": "console_info"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"component_id": "offchain_transport",
|
||||||
|
"file_id": "cfg.std.offchain_transport",
|
||||||
|
"profile_id": "public_keyless"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"profile_id": "all_free",
|
||||||
|
"documents": [
|
||||||
|
{
|
||||||
|
"component_id": "logging",
|
||||||
|
"file_id": "cfg.std.logging",
|
||||||
|
"profile_id": "console_info"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"component_id": "offchain_transport",
|
||||||
|
"file_id": "cfg.std.offchain_transport",
|
||||||
|
"profile_id": "all_free"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"profile_id": "tests",
|
||||||
|
"documents": [
|
||||||
|
{
|
||||||
|
"component_id": "logging",
|
||||||
|
"file_id": "cfg.std.logging",
|
||||||
|
"profile_id": "console_info"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"component_id": "offchain_transport",
|
||||||
|
"file_id": "cfg.std.offchain_transport",
|
||||||
|
"profile_id": "public_keyless"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -53,6 +53,7 @@
|
|||||||
"icons/favicon.ico"
|
"icons/favicon.ico"
|
||||||
],
|
],
|
||||||
"resources": {
|
"resources": {
|
||||||
|
"../../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",
|
||||||
"../../config/std.offchain_transport.json": "config/std.offchain_transport.json",
|
"../../config/std.offchain_transport.json": "config/std.offchain_transport.json",
|
||||||
|
|||||||
@@ -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: 8
|
// version: 9
|
||||||
|
|
||||||
//! Desktop build/shell contract audits for Config Desk.
|
//! Desktop build/shell contract audits for Config Desk.
|
||||||
|
|
||||||
@@ -150,7 +150,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(), 10);
|
assert_eq!(resources.len(), 11);
|
||||||
|
assert_eq!(
|
||||||
|
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"),
|
||||||
|
);
|
||||||
assert_eq!(resources.get("../../config/std.logging.json").and_then(serde_json::Value::as_str), std::option::Option::Some("config/std.logging.json"));
|
assert_eq!(resources.get("../../config/std.logging.json").and_then(serde_json::Value::as_str), std::option::Option::Some("config/std.logging.json"));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resources.get("../../config/std.offchain_transport.json").and_then(serde_json::Value::as_str),
|
resources.get("../../config/std.offchain_transport.json").and_then(serde_json::Value::as_str),
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: crates/ksp-app-solprices-desk/frontend/main.html -->
|
<!-- file: crates/ksp-app-solprices-desk/frontend/main.html -->
|
||||||
<!-- version: 3 -->
|
<!-- version: 4 -->
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="fr">
|
<html lang="fr">
|
||||||
|
|
||||||
@@ -47,14 +47,14 @@
|
|||||||
<div class="d-flex align-items-center justify-content-between mb-4">
|
<div class="d-flex align-items-center justify-content-between mb-4">
|
||||||
<div>
|
<div>
|
||||||
<h1 class="h3 mb-1">Prices</h1>
|
<h1 class="h3 mb-1">Prices</h1>
|
||||||
<p class="text-body-secondary mb-0">Scaffold desktop actif. Le runtime Off-chain et la table SOL/USD arrivent dans les tranches suivantes.</p>
|
<p class="text-body-secondary mb-0">Composition Config/Off-chain active. La projection provider-neutral du registry arrive dans la tranche suivante.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="app-placeholder">
|
<div class="app-placeholder">
|
||||||
<div>
|
<div>
|
||||||
<i class="fa-solid fa-chart-line fa-3x text-body-secondary mb-3" aria-hidden="true"></i>
|
<i class="fa-solid fa-chart-line fa-3x text-body-secondary mb-3" aria-hidden="true"></i>
|
||||||
<h2 class="h5">Surface prix volontairement inactive</h2>
|
<h2 class="h5">Surface prix volontairement inactive</h2>
|
||||||
<p class="text-body-secondary mb-0">`pre.002` ne crée ni `MarketPriceService`, ni table provider, ni refresh réseau.</p>
|
<p class="text-body-secondary mb-0">`pre.003` initialise le service via Config, mais ne crée encore ni lignes provider, ni observation affichée, ni refresh réseau déclenché par l’UI.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
<div class="d-flex align-items-center justify-content-between mb-4">
|
<div class="d-flex align-items-center justify-content-between mb-4">
|
||||||
<div>
|
<div>
|
||||||
<h1 class="h3 mb-1">Diagnostics</h1>
|
<h1 class="h3 mb-1">Diagnostics</h1>
|
||||||
<p class="text-body-secondary mb-0">État sûr du scaffold uniquement.</p>
|
<p class="text-body-secondary mb-0">État sûr du bootstrap Config, Logging et Off-chain Transport.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card shadow-sm">
|
<div class="card shadow-sm">
|
||||||
@@ -75,6 +75,10 @@
|
|||||||
<dd id="runtimeShellPhase" class="col-sm-7">—</dd>
|
<dd id="runtimeShellPhase" class="col-sm-7">—</dd>
|
||||||
<dt class="col-sm-5">Documents Config</dt>
|
<dt class="col-sm-5">Documents Config</dt>
|
||||||
<dd id="runtimeConfigDocuments" class="col-sm-7">—</dd>
|
<dd id="runtimeConfigDocuments" class="col-sm-7">—</dd>
|
||||||
|
<dt class="col-sm-5">Profil composite</dt>
|
||||||
|
<dd id="runtimeCompositeProfile" class="col-sm-7">—</dd>
|
||||||
|
<dt class="col-sm-5">Profil Off-chain</dt>
|
||||||
|
<dd id="runtimeOffchainProfile" class="col-sm-7">—</dd>
|
||||||
<dt class="col-sm-5">Profil Logging</dt>
|
<dt class="col-sm-5">Profil Logging</dt>
|
||||||
<dd id="runtimeLoggingProfile" class="col-sm-7">—</dd>
|
<dd id="runtimeLoggingProfile" class="col-sm-7">—</dd>
|
||||||
<dt class="col-sm-5">Fallback Logging</dt>
|
<dt class="col-sm-5">Fallback Logging</dt>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: crates/ksp-app-solprices-desk/frontend/ts/main.ts
|
// file: crates/ksp-app-solprices-desk/frontend/ts/main.ts
|
||||||
// version: 2
|
// version: 3
|
||||||
|
|
||||||
import "bootstrap";
|
import "bootstrap";
|
||||||
import ResizeObserver from "resize-observer-polyfill";
|
import ResizeObserver from "resize-observer-polyfill";
|
||||||
@@ -44,6 +44,7 @@ function bindNavigation(): void {
|
|||||||
document.querySelectorAll<HTMLButtonElement>("[data-view]").forEach(button => {
|
document.querySelectorAll<HTMLButtonElement>("[data-view]").forEach(button => {
|
||||||
button.addEventListener("click", () => {
|
button.addEventListener("click", () => {
|
||||||
const viewId = button.dataset.view;
|
const viewId = button.dataset.view;
|
||||||
|
frontendDebug("main", "SOL Prices Desk navigation control clicked", { viewId: viewId ?? "unknown" });
|
||||||
if (isViewId(viewId)) {
|
if (isViewId(viewId)) {
|
||||||
activateView(viewId, "user");
|
activateView(viewId, "user");
|
||||||
}
|
}
|
||||||
@@ -54,6 +55,8 @@ function bindNavigation(): void {
|
|||||||
|
|
||||||
function renderRuntimeStatus(status: RuntimeStatusDto): void {
|
function renderRuntimeStatus(status: RuntimeStatusDto): void {
|
||||||
const values: Record<string, string> = {
|
const values: Record<string, string> = {
|
||||||
|
runtimeCompositeProfile: status.activeCompositeProfile,
|
||||||
|
runtimeOffchainProfile: status.activeOffchainProfile,
|
||||||
runtimeVersion: status.applicationVersion,
|
runtimeVersion: status.applicationVersion,
|
||||||
runtimeShellPhase: status.shellPhase,
|
runtimeShellPhase: status.shellPhase,
|
||||||
runtimeConfigDocuments: status.configDocumentCount.toString(),
|
runtimeConfigDocuments: status.configDocumentCount.toString(),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "ksp-app-solprices-desk",
|
"name": "ksp-app-solprices-desk",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.2.12-pre.2.fix.1",
|
"version": "0.2.12-pre.3",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: crates/ksp-app-solprices-desk/src/app_state.rs
|
// file: crates/ksp-app-solprices-desk/src/app_state.rs
|
||||||
// version: 1
|
// version: 2
|
||||||
|
|
||||||
//! Shared backend state owned by the SOL Prices Desk Tauri application.
|
//! Shared backend state owned by the SOL Prices Desk Tauri application.
|
||||||
|
|
||||||
@@ -7,12 +7,13 @@
|
|||||||
pub(crate) struct AppState {
|
pub(crate) struct AppState {
|
||||||
config_management: ksp_config_lib::ConfigManagement,
|
config_management: ksp_config_lib::ConfigManagement,
|
||||||
logging_runtime: std::sync::Mutex<LoggingRuntimeState>,
|
logging_runtime: std::sync::Mutex<LoggingRuntimeState>,
|
||||||
|
offchain_transport_startup: crate::OffchainTransportStartup,
|
||||||
splash_settings: crate::SplashSettings,
|
splash_settings: crate::SplashSettings,
|
||||||
splash_sequence_started: std::sync::atomic::AtomicBool,
|
splash_sequence_started: std::sync::atomic::AtomicBool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppState {
|
impl crate::AppState {
|
||||||
/// Initializes Config ownership, Logging and the common desktop splash state without creating the Off-chain runtime reserved for `pre.003`.
|
/// Initializes Config ownership, composite-managed Logging and the Config-selected Off-chain Transport runtime.
|
||||||
pub(crate) fn initialize(arguments: &[std::ffi::OsString]) -> ksp_core_lib::Result<Self> {
|
pub(crate) fn initialize(arguments: &[std::ffi::OsString]) -> ksp_core_lib::Result<Self> {
|
||||||
let config_management = crate::config_management(arguments);
|
let config_management = crate::config_management(arguments);
|
||||||
let config_management = match config_management {
|
let config_management = match config_management {
|
||||||
@@ -29,6 +30,11 @@ impl AppState {
|
|||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
};
|
};
|
||||||
|
let offchain_transport_startup = crate::initialize_offchain_transport(&config_management);
|
||||||
|
let offchain_transport_startup = match offchain_transport_startup {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
|
};
|
||||||
let splash_settings = crate::SplashSettings::load();
|
let splash_settings = crate::SplashSettings::load();
|
||||||
let splash_settings = match splash_settings {
|
let splash_settings = match splash_settings {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
@@ -46,12 +52,13 @@ impl AppState {
|
|||||||
fallback_active: logging_startup.fallback_active,
|
fallback_active: logging_startup.fallback_active,
|
||||||
startup_diagnostic: logging_startup.startup_diagnostic,
|
startup_diagnostic: logging_startup.startup_diagnostic,
|
||||||
}),
|
}),
|
||||||
|
offchain_transport_startup,
|
||||||
splash_settings,
|
splash_settings,
|
||||||
splash_sequence_started: std::sync::atomic::AtomicBool::new(false),
|
splash_sequence_started: std::sync::atomic::AtomicBool::new(false),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds the safe scaffold runtime status exposed before market-price composition is introduced.
|
/// Builds the safe runtime status exposed before provider rows and refresh commands are introduced.
|
||||||
pub(crate) fn runtime_status(&self) -> ksp_core_lib::Result<crate::RuntimeStatusDto> {
|
pub(crate) fn runtime_status(&self) -> ksp_core_lib::Result<crate::RuntimeStatusDto> {
|
||||||
let document_count = self.config_management.engine().registry().descriptors().count();
|
let document_count = self.config_management.engine().registry().descriptors().count();
|
||||||
let document_count = u32::try_from(document_count);
|
let document_count = u32::try_from(document_count);
|
||||||
@@ -61,7 +68,7 @@ impl AppState {
|
|||||||
return std::result::Result::Err(
|
return std::result::Result::Err(
|
||||||
ksp_core_lib::Error::new(
|
ksp_core_lib::Error::new(
|
||||||
crate::ERROR_CODE_APP_STATE_INVALID,
|
crate::ERROR_CODE_APP_STATE_INVALID,
|
||||||
"Config registry contains too many descriptors for the SOL Prices Desk scaffold DTO",
|
"Config registry contains too many descriptors for the SOL Prices Desk runtime DTO",
|
||||||
)
|
)
|
||||||
.with_source(error),
|
.with_source(error),
|
||||||
);
|
);
|
||||||
@@ -78,12 +85,15 @@ impl AppState {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
let _keep_guard_alive = &runtime.guard;
|
let _keep_guard_alive = &runtime.guard;
|
||||||
|
let offchain = self.offchain_transport_startup.resolved();
|
||||||
return std::result::Result::Ok(crate::RuntimeStatusDto {
|
return std::result::Result::Ok(crate::RuntimeStatusDto {
|
||||||
application_version: env!("CARGO_PKG_VERSION").to_owned(),
|
active_composite_profile: self.offchain_transport_startup.composite_profile_id().to_owned(),
|
||||||
active_logging_profile: runtime.active_profile_id.clone(),
|
active_logging_profile: runtime.active_profile_id.clone(),
|
||||||
|
active_offchain_profile: offchain.profile_id().to_owned(),
|
||||||
|
application_version: env!("CARGO_PKG_VERSION").to_owned(),
|
||||||
config_document_count: document_count,
|
config_document_count: document_count,
|
||||||
fallback_logging_active: runtime.fallback_active,
|
fallback_logging_active: runtime.fallback_active,
|
||||||
shell_phase: "pre.002-scaffold".to_owned(),
|
shell_phase: "pre.003-offchain-bootstrap".to_owned(),
|
||||||
startup_diagnostic: runtime.startup_diagnostic.clone(),
|
startup_diagnostic: runtime.startup_diagnostic.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// file: crates/ksp-app-solprices-desk/src/bootstrap.rs
|
// file: crates/ksp-app-solprices-desk/src/bootstrap.rs
|
||||||
// version: 1
|
// version: 2
|
||||||
|
|
||||||
//! Config and Logging bootstrap for the SOL Prices Desk scaffold.
|
//! Config composite and Logging bootstrap for SOL Prices 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,51 @@ 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 Config document until the SOL Prices composite is introduced by `pre.003`.
|
/// Loads the concrete SOL Prices Desk Config composite using its registered logical `file_id` and autonomous default profile.
|
||||||
|
pub(crate) fn load_solprices_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_SOLPRICES_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 SOL Prices 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, "SOL Prices 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,
|
||||||
|
"SOL Prices 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 SOL Prices Desk composite, with the same bounded fallback policy as the other KSP desks.
|
||||||
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,
|
||||||
@@ -54,7 +98,7 @@ pub(crate) fn initialize_logging(
|
|||||||
let guard = ksp_logging_lib::initialize_with_identity(&settings, runtime_identity);
|
let guard = ksp_logging_lib::initialize_with_identity(&settings, runtime_identity);
|
||||||
match guard {
|
match guard {
|
||||||
std::result::Result::Ok(guard) => {
|
std::result::Result::Ok(guard) => {
|
||||||
ksp_logging_lib::info!(target: crate::TRACING_TARGET, domain = crate::TRACING_DOMAIN_BOOTSTRAP, active_profile = active_profile_id.as_str(), "initialized SOL Prices Desk scaffold logging from managed configuration");
|
ksp_logging_lib::info!(target: crate::TRACING_TARGET, domain = crate::TRACING_DOMAIN_BOOTSTRAP, active_profile = active_profile_id.as_str(), "initialized SOL Prices Desk logging from composite-managed configuration");
|
||||||
std::result::Result::Ok(LoggingStartup {
|
std::result::Result::Ok(LoggingStartup {
|
||||||
guard,
|
guard,
|
||||||
active_profile_id: std::option::Option::Some(active_profile_id),
|
active_profile_id: std::option::Option::Some(active_profile_id),
|
||||||
@@ -86,7 +130,25 @@ 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_solprices_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 offchain_profile = crate::required_composite_component_profile(
|
||||||
|
&composite,
|
||||||
|
crate::COMPOSITE_COMPONENT_ID_OFFCHAIN_TRANSPORT,
|
||||||
|
ksp_config_lib::FILE_ID_STD_OFFCHAIN_TRANSPORT,
|
||||||
|
);
|
||||||
|
if let std::result::Result::Err(error) = offchain_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),
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
// file: crates/ksp-app-solprices-desk/src/constants.rs
|
// file: crates/ksp-app-solprices-desk/src/constants.rs
|
||||||
// version: 1
|
// version: 2
|
||||||
|
|
||||||
//! Application-owned tracing targets and domains.
|
//! Application-owned composition identifiers, tracing targets and domains.
|
||||||
|
|
||||||
|
/// Composite-local identifier for the standard Logging component.
|
||||||
|
pub(crate) const COMPOSITE_COMPONENT_ID_LOGGING: &str = "logging";
|
||||||
|
/// Composite-local identifier for the standard Off-chain Transport component.
|
||||||
|
pub(crate) const COMPOSITE_COMPONENT_ID_OFFCHAIN_TRANSPORT: &str = "offchain_transport";
|
||||||
/// Structured domain used while bootstrapping Config and Logging.
|
/// Structured domain used while bootstrapping Config and Logging.
|
||||||
pub(crate) const TRACING_DOMAIN_BOOTSTRAP: &str = "solprices.bootstrap";
|
pub(crate) const TRACING_DOMAIN_BOOTSTRAP: &str = "solprices.bootstrap";
|
||||||
/// Structured domain used by technical frontend events.
|
/// Structured domain used by technical frontend events.
|
||||||
pub(crate) const TRACING_DOMAIN_FRONTEND: &str = "frontend";
|
pub(crate) const TRACING_DOMAIN_FRONTEND: &str = "frontend";
|
||||||
|
/// Structured domain used by the Config-selected Off-chain Transport runtime.
|
||||||
|
pub(crate) const TRACING_DOMAIN_OFFCHAIN_TRANSPORT: &str = "solprices.offchain_transport";
|
||||||
/// Structured domain used by the SOL Prices Desk shell.
|
/// Structured domain used by the SOL Prices Desk shell.
|
||||||
pub(crate) const TRACING_DOMAIN_SHELL: &str = "solprices.shell";
|
pub(crate) const TRACING_DOMAIN_SHELL: &str = "solprices.shell";
|
||||||
/// Structured domain used by Tauri window lifecycle operations.
|
/// Structured domain used by Tauri window lifecycle operations.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// file: crates/ksp-app-solprices-desk/src/dto_common.rs
|
// file: crates/ksp-app-solprices-desk/src/dto_common.rs
|
||||||
// version: 1
|
// version: 2
|
||||||
|
|
||||||
//! Common Tauri DTOs shared by the SOL Prices Desk scaffold.
|
//! Common Tauri DTOs shared by the SOL Prices Desk bootstrap shell.
|
||||||
|
|
||||||
use ts_rs::TS; // rust-rules: trait-import
|
use ts_rs::TS; // rust-rules: trait-import
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ pub(crate) struct CommandErrorDto {
|
|||||||
pub(crate) message: String,
|
pub(crate) message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommandErrorDto {
|
impl crate::CommandErrorDto {
|
||||||
/// Builds a bounded safe projection from a KSP error.
|
/// Builds a bounded safe projection from a KSP error.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub(crate) fn from_error(error: &ksp_core_lib::Error) -> Self {
|
pub(crate) fn from_error(error: &ksp_core_lib::Error) -> Self {
|
||||||
@@ -30,20 +30,24 @@ impl CommandErrorDto {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Safe scaffold/runtime snapshot exposed to the SOL Prices Desk shell before Off-chain bootstrap exists.
|
/// Safe Config/bootstrap snapshot exposed before market-price provider rows exist.
|
||||||
#[derive(Clone, Debug, serde::Serialize, TS)]
|
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_solprices_desk/dto_common/RuntimeStatusDto.ts")]
|
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_solprices_desk/dto_common/RuntimeStatusDto.ts")]
|
||||||
pub(crate) struct RuntimeStatusDto {
|
pub(crate) struct RuntimeStatusDto {
|
||||||
/// Cargo application version.
|
/// SOL Prices Desk composite profile selected for this launch.
|
||||||
pub(crate) application_version: String,
|
pub(crate) active_composite_profile: String,
|
||||||
/// Active configured Logging profile, or `None` while transient fallback Logging is active.
|
/// Active configured Logging profile, or `None` while transient fallback Logging is active.
|
||||||
pub(crate) active_logging_profile: std::option::Option<String>,
|
pub(crate) active_logging_profile: std::option::Option<String>,
|
||||||
/// Number of logical Config resources registered by the current scaffold runtime.
|
/// Standard Off-chain Transport profile selected by the active composite.
|
||||||
|
pub(crate) active_offchain_profile: String,
|
||||||
|
/// Cargo application version.
|
||||||
|
pub(crate) application_version: String,
|
||||||
|
/// Number of logical Config resources registered by the current runtime.
|
||||||
pub(crate) config_document_count: u32,
|
pub(crate) config_document_count: u32,
|
||||||
/// Whether SOL Prices Desk had to install its transient in-memory Logging fallback.
|
/// Whether SOL Prices Desk had to install its transient in-memory Logging fallback.
|
||||||
pub(crate) fallback_logging_active: bool,
|
pub(crate) fallback_logging_active: bool,
|
||||||
/// Current implementation phase exposed by the scaffold shell.
|
/// Current implementation phase exposed by the bootstrap shell.
|
||||||
pub(crate) shell_phase: String,
|
pub(crate) shell_phase: String,
|
||||||
/// Safe startup diagnostic that caused fallback Logging, when applicable.
|
/// Safe startup diagnostic that caused fallback Logging, when applicable.
|
||||||
pub(crate) startup_diagnostic: std::option::Option<CommandErrorDto>,
|
pub(crate) startup_diagnostic: std::option::Option<CommandErrorDto>,
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
// file: crates/ksp-app-solprices-desk/src/errors.rs
|
// file: crates/ksp-app-solprices-desk/src/errors.rs
|
||||||
// version: 1
|
// version: 2
|
||||||
|
|
||||||
//! Application-local error codes for SOL Prices Desk scaffold and desktop runtime surfaces.
|
//! Application-local error codes for SOL Prices Desk composition and desktop runtime surfaces.
|
||||||
|
|
||||||
/// Shared SOL Prices Desk application state is internally inconsistent.
|
/// Shared SOL Prices Desk application state is internally inconsistent.
|
||||||
pub(crate) const ERROR_CODE_APP_STATE_INVALID: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("solprices_desk", "app_state_invalid");
|
pub(crate) const ERROR_CODE_APP_STATE_INVALID: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("solprices_desk", "app_state_invalid");
|
||||||
/// Shared SOL Prices Desk runtime state cannot be locked safely.
|
/// Shared SOL Prices Desk runtime state cannot be locked safely.
|
||||||
pub(crate) const ERROR_CODE_APP_STATE_LOCK_FAILED: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("solprices_desk", "app_state_lock_failed");
|
pub(crate) const ERROR_CODE_APP_STATE_LOCK_FAILED: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("solprices_desk", "app_state_lock_failed");
|
||||||
|
/// The SOL Prices Desk Config composite is missing or misroutes one required standard component.
|
||||||
|
pub(crate) const ERROR_CODE_CONFIG_COMPOSITE_INVALID: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("solprices_desk", "config_composite_invalid");
|
||||||
/// Frontend logging requested an unsupported level.
|
/// Frontend logging requested an unsupported level.
|
||||||
pub(crate) const ERROR_CODE_FRONTEND_LOG_LEVEL_INVALID: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("solprices_desk", "frontend_log_level_invalid");
|
pub(crate) const ERROR_CODE_FRONTEND_LOG_LEVEL_INVALID: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("solprices_desk", "frontend_log_level_invalid");
|
||||||
/// Frontend logging requested a target outside the application whitelist.
|
/// Frontend logging requested a target outside the application whitelist.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: crates/ksp-app-solprices-desk/src/lib.rs
|
// file: crates/ksp-app-solprices-desk/src/lib.rs
|
||||||
// version: 1
|
// version: 2
|
||||||
|
|
||||||
//! Tauri desktop application scaffold for provider-neutral SOL/USD price visualization.
|
//! Tauri desktop application scaffold for provider-neutral SOL/USD price visualization.
|
||||||
|
|
||||||
@@ -14,6 +14,7 @@ mod dto_common;
|
|||||||
mod errors;
|
mod errors;
|
||||||
mod frontend_logging;
|
mod frontend_logging;
|
||||||
mod logging_runtime;
|
mod logging_runtime;
|
||||||
|
mod offchain_runtime;
|
||||||
mod splash;
|
mod splash;
|
||||||
mod tauri;
|
mod tauri;
|
||||||
mod tw_main;
|
mod tw_main;
|
||||||
@@ -30,10 +31,20 @@ pub(crate) use self::bootstrap::LoggingStartup;
|
|||||||
pub(crate) use self::bootstrap::config_management;
|
pub(crate) use self::bootstrap::config_management;
|
||||||
/// Initializes the scaffold Logging runtime from Config, with a bounded in-memory fallback.
|
/// Initializes the scaffold Logging runtime from Config, with a bounded in-memory fallback.
|
||||||
pub(crate) use self::bootstrap::initialize_logging;
|
pub(crate) use self::bootstrap::initialize_logging;
|
||||||
|
/// Loads the SOL Prices Desk composite selected by its registered logical file identifier.
|
||||||
|
pub(crate) use self::bootstrap::load_solprices_desk_composite;
|
||||||
|
/// Resolves one required standard Config profile from the SOL Prices Desk composite.
|
||||||
|
pub(crate) use self::bootstrap::required_composite_component_profile;
|
||||||
|
/// Composite-local identifier for the standard Logging component.
|
||||||
|
pub(crate) use self::constants::COMPOSITE_COMPONENT_ID_LOGGING;
|
||||||
|
/// Composite-local identifier for the standard Off-chain Transport component.
|
||||||
|
pub(crate) use self::constants::COMPOSITE_COMPONENT_ID_OFFCHAIN_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.
|
||||||
pub(crate) use self::constants::TRACING_DOMAIN_FRONTEND;
|
pub(crate) use self::constants::TRACING_DOMAIN_FRONTEND;
|
||||||
|
/// Structured domain used by the Config-selected Off-chain Transport runtime.
|
||||||
|
pub(crate) use self::constants::TRACING_DOMAIN_OFFCHAIN_TRANSPORT;
|
||||||
/// Structured domain used by the SOL Prices Desk shell.
|
/// Structured domain used by the SOL Prices Desk shell.
|
||||||
pub(crate) use self::constants::TRACING_DOMAIN_SHELL;
|
pub(crate) use self::constants::TRACING_DOMAIN_SHELL;
|
||||||
/// Structured domain used by Tauri window lifecycle operations.
|
/// Structured domain used by Tauri window lifecycle operations.
|
||||||
@@ -54,6 +65,8 @@ pub(crate) use self::dto_common::RuntimeStatusDto;
|
|||||||
pub(crate) use self::errors::ERROR_CODE_APP_STATE_INVALID;
|
pub(crate) use self::errors::ERROR_CODE_APP_STATE_INVALID;
|
||||||
/// Shared SOL Prices Desk runtime state cannot be locked safely.
|
/// Shared SOL Prices 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;
|
||||||
|
/// The SOL Prices Desk Config composite is missing or misroutes a required component.
|
||||||
|
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.
|
||||||
@@ -76,6 +89,10 @@ pub(crate) use self::frontend_logging::FrontendLogPayloadDto;
|
|||||||
pub(crate) use self::frontend_logging::emit_frontend_log_event;
|
pub(crate) use self::frontend_logging::emit_frontend_log_event;
|
||||||
/// Creates the stable runtime identity for this SOL Prices Desk process launch.
|
/// Creates the stable runtime identity for this SOL Prices Desk process launch.
|
||||||
pub(crate) use self::logging_runtime::launch_identity;
|
pub(crate) use self::logging_runtime::launch_identity;
|
||||||
|
/// Resolved composite and Off-chain Transport configuration retained by SOL Prices Desk.
|
||||||
|
pub(crate) use self::offchain_runtime::OffchainTransportStartup;
|
||||||
|
/// Resolves the composite-selected Off-chain Transport profile and constructs the Config-owned service.
|
||||||
|
pub(crate) use self::offchain_runtime::initialize_offchain_transport;
|
||||||
/// Command emitted by Rust to the splash frontend.
|
/// Command emitted by Rust to the splash frontend.
|
||||||
pub(crate) use self::splash::SplashOrderDto;
|
pub(crate) use self::splash::SplashOrderDto;
|
||||||
/// Runtime timings used by the common desk splash lifecycle.
|
/// Runtime timings used by the common desk splash lifecycle.
|
||||||
|
|||||||
59
crates/ksp-app-solprices-desk/src/offchain_runtime.rs
Normal file
59
crates/ksp-app-solprices-desk/src/offchain_runtime.rs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
// file: crates/ksp-app-solprices-desk/src/offchain_runtime.rs
|
||||||
|
// version: 1
|
||||||
|
|
||||||
|
//! Config-owned Off-chain Transport bootstrap for SOL Prices Desk.
|
||||||
|
|
||||||
|
/// Resolved SOL Prices Desk composite and Off-chain Transport configuration retained by application state.
|
||||||
|
pub(crate) struct OffchainTransportStartup {
|
||||||
|
composite_profile_id: String,
|
||||||
|
resolved: ksp_config_lib::ResolvedOffchainTransportConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl crate::OffchainTransportStartup {
|
||||||
|
/// Returns the composite profile selected for this application launch.
|
||||||
|
#[must_use]
|
||||||
|
pub(crate) fn composite_profile_id(&self) -> &str {
|
||||||
|
return self.composite_profile_id.as_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the Config-resolved Off-chain Transport runtime configuration.
|
||||||
|
#[must_use]
|
||||||
|
pub(crate) const fn resolved(&self) -> &ksp_config_lib::ResolvedOffchainTransportConfig {
|
||||||
|
return &self.resolved;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resolves the composite-selected Off-chain Transport profile and constructs the provider-neutral service owned by Config.
|
||||||
|
pub(crate) fn initialize_offchain_transport(management: &ksp_config_lib::ConfigManagement) -> ksp_core_lib::Result<crate::OffchainTransportStartup> {
|
||||||
|
let environment = ksp_config_lib::ConfigEnvironment::load();
|
||||||
|
let environment = match environment {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
|
};
|
||||||
|
let composite = crate::load_solprices_desk_composite(management);
|
||||||
|
let composite = match composite {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
|
};
|
||||||
|
let logging_profile = crate::required_composite_component_profile(&composite, crate::COMPOSITE_COMPONENT_ID_LOGGING, ksp_config_lib::FILE_ID_STD_LOGGING);
|
||||||
|
if let std::result::Result::Err(error) = logging_profile {
|
||||||
|
return std::result::Result::Err(error);
|
||||||
|
}
|
||||||
|
let offchain_profile = crate::required_composite_component_profile(
|
||||||
|
&composite,
|
||||||
|
crate::COMPOSITE_COMPONENT_ID_OFFCHAIN_TRANSPORT,
|
||||||
|
ksp_config_lib::FILE_ID_STD_OFFCHAIN_TRANSPORT,
|
||||||
|
);
|
||||||
|
let offchain_profile = match offchain_profile {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
|
};
|
||||||
|
let resolved = management.engine().resolve_offchain_transport_config_profile(&offchain_profile, &environment);
|
||||||
|
let resolved = match resolved {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
|
};
|
||||||
|
let provider_count = resolved.service().registry().len();
|
||||||
|
ksp_logging_lib::info!(target: crate::TRACING_TARGET, domain = crate::TRACING_DOMAIN_OFFCHAIN_TRANSPORT, composite_profile = composite.profile_id(), offchain_profile = resolved.profile_id(), provider_count, "initialized SOL Prices Desk Off-chain Transport from composite-managed configuration");
|
||||||
|
return std::result::Result::Ok(crate::OffchainTransportStartup { composite_profile_id: composite.profile_id().to_owned(), resolved });
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "KSP SOL Prices Desk",
|
"productName": "KSP SOL Prices Desk",
|
||||||
"version": "0.2.12-pre.2.fix.1",
|
"version": "0.2.12-pre.3",
|
||||||
"identifier": "com.sasedev.ksp-app-solprices-desk",
|
"identifier": "com.sasedev.ksp-app-solprices-desk",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": {
|
"beforeDevCommand": {
|
||||||
@@ -53,6 +53,7 @@
|
|||||||
"icons/favicon.ico"
|
"icons/favicon.ico"
|
||||||
],
|
],
|
||||||
"resources": {
|
"resources": {
|
||||||
|
"../../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",
|
||||||
"../../config/std.offchain_transport.json": "config/std.offchain_transport.json",
|
"../../config/std.offchain_transport.json": "config/std.offchain_transport.json",
|
||||||
|
|||||||
94
crates/ksp-app-solprices-desk/tests/config_composition.rs
Normal file
94
crates/ksp-app-solprices-desk/tests/config_composition.rs
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
// file: crates/ksp-app-solprices-desk/tests/config_composition.rs
|
||||||
|
// version: 1
|
||||||
|
|
||||||
|
//! Config composition contracts for SOL Prices Desk `0.2.12-pre.003`.
|
||||||
|
|
||||||
|
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 solprices_desk_composite_profiles_select_logging_and_offchain_transport_by_file_id() {
|
||||||
|
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_SOLPRICES_DESK);
|
||||||
|
assert!(file_id.is_ok(), "SOL Prices 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,
|
||||||
|
};
|
||||||
|
for (selection, expected_composite_profile, expected_offchain_profile) in [
|
||||||
|
(std::option::Option::None, "public_keyless", "public_keyless"),
|
||||||
|
(std::option::Option::Some("all_free"), "all_free", "all_free"),
|
||||||
|
(std::option::Option::Some("tests"), "tests", "public_keyless"),
|
||||||
|
] {
|
||||||
|
let composite = engine.load_resolved_composite(&file_id, selection);
|
||||||
|
assert!(composite.is_ok(), "committed SOL Prices Desk composite profile should resolve: {composite:?}");
|
||||||
|
if let std::result::Result::Ok(composite) = composite {
|
||||||
|
assert_eq!(composite.profile_id(), expected_composite_profile);
|
||||||
|
assert_component(&composite, "logging", ksp_config_lib::FILE_ID_STD_LOGGING, "console_info");
|
||||||
|
assert_component(&composite, "offchain_transport", ksp_config_lib::FILE_ID_STD_OFFCHAIN_TRANSPORT, expected_offchain_profile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn solprices_desk_default_composite_builds_provider_neutral_offchain_service() {
|
||||||
|
let engine = workspace_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_SOLPRICES_DESK);
|
||||||
|
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);
|
||||||
|
let composite = match composite {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(_) => return,
|
||||||
|
};
|
||||||
|
let component = composite.component("offchain_transport");
|
||||||
|
let component = match component {
|
||||||
|
std::option::Option::Some(value) => value,
|
||||||
|
std::option::Option::None => return,
|
||||||
|
};
|
||||||
|
let environment = ksp_config_lib::ConfigEnvironment::load();
|
||||||
|
assert!(environment.is_ok(), "Config environment should load for the public_keyless profile: {environment:?}");
|
||||||
|
let environment = match environment {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(_) => return,
|
||||||
|
};
|
||||||
|
let resolved = engine.resolve_offchain_transport_config_profile(component.resolved(), &environment);
|
||||||
|
assert!(resolved.is_ok(), "public_keyless composite-selected Off-chain Transport should map: {resolved:?}");
|
||||||
|
if let std::result::Result::Ok(resolved) = resolved {
|
||||||
|
assert_eq!(resolved.profile_id(), "public_keyless");
|
||||||
|
assert_eq!(resolved.selection_source(), ksp_config_lib::ConfigProfileSelectionSource::Composite);
|
||||||
|
assert_eq!(resolved.service().registry().len(), 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
// file: crates/ksp-app-solprices-desk/tests/desktop_contract.rs
|
// file: crates/ksp-app-solprices-desk/tests/desktop_contract.rs
|
||||||
// version: 2
|
// version: 3
|
||||||
|
|
||||||
//! Desktop scaffold and shared-template contract audits for SOL Prices Desk `0.2.12-pre.002` and its fixes.
|
//! Desktop scaffold, shared-template and Config packaging contract audits for SOL Prices Desk `0.2.12`.
|
||||||
|
|
||||||
fn app_root() -> std::path::PathBuf {
|
fn app_root() -> std::path::PathBuf {
|
||||||
return std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
return std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||||
@@ -37,9 +37,9 @@ fn pre_002_shell_uses_reserved_ports_windows_and_owned_backend_paths() {
|
|||||||
let tauri = read_json(root.join("tauri.conf.json").as_path());
|
let tauri = read_json(root.join("tauri.conf.json").as_path());
|
||||||
assert_eq!(tauri.pointer("/productName").and_then(serde_json::Value::as_str), std::option::Option::Some("KSP SOL Prices Desk"));
|
assert_eq!(tauri.pointer("/productName").and_then(serde_json::Value::as_str), std::option::Option::Some("KSP SOL Prices Desk"));
|
||||||
assert_eq!(tauri.pointer("/identifier").and_then(serde_json::Value::as_str), std::option::Option::Some("com.sasedev.ksp-app-solprices-desk"));
|
assert_eq!(tauri.pointer("/identifier").and_then(serde_json::Value::as_str), std::option::Option::Some("com.sasedev.ksp-app-solprices-desk"));
|
||||||
assert_eq!(tauri.pointer("/version").and_then(serde_json::Value::as_str), std::option::Option::Some("0.2.12-pre.2.fix.1"));
|
assert_eq!(tauri.pointer("/version").and_then(serde_json::Value::as_str), std::option::Option::Some("0.2.12-pre.3"));
|
||||||
let package = read_json(root.join("package.json").as_path());
|
let package = read_json(root.join("package.json").as_path());
|
||||||
assert_eq!(package.pointer("/version").and_then(serde_json::Value::as_str), std::option::Option::Some("0.2.12-pre.2.fix.1"));
|
assert_eq!(package.pointer("/version").and_then(serde_json::Value::as_str), std::option::Option::Some("0.2.12-pre.3"));
|
||||||
assert_eq!(tauri.pointer("/build/devUrl").and_then(serde_json::Value::as_str), std::option::Option::Some("http://localhost:1434"));
|
assert_eq!(tauri.pointer("/build/devUrl").and_then(serde_json::Value::as_str), std::option::Option::Some("http://localhost:1434"));
|
||||||
assert_eq!(tauri.pointer("/build/beforeDevCommand/script").and_then(serde_json::Value::as_str), std::option::Option::Some("npm run dev"));
|
assert_eq!(tauri.pointer("/build/beforeDevCommand/script").and_then(serde_json::Value::as_str), std::option::Option::Some("npm run dev"));
|
||||||
assert_eq!(tauri.pointer("/build/beforeDevCommand/cwd").and_then(serde_json::Value::as_str), std::option::Option::Some("."));
|
assert_eq!(tauri.pointer("/build/beforeDevCommand/cwd").and_then(serde_json::Value::as_str), std::option::Option::Some("."));
|
||||||
@@ -86,14 +86,17 @@ fn pre_002_package_is_mixed_lib_bin_and_frontend_is_scaffold_only() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pre_002_packaging_contains_current_ten_config_resources_only() {
|
fn pre_003_packaging_contains_current_eleven_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(), 10);
|
assert_eq!(resources.len(), 11);
|
||||||
assert!(!resources.contains_key("../../config/composite.ksp-app-solprices-desk.json"));
|
assert_eq!(
|
||||||
|
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"),
|
||||||
|
);
|
||||||
assert!(resources.contains_key("../../config/std.offchain_transport.json"));
|
assert!(resources.contains_key("../../config/std.offchain_transport.json"));
|
||||||
assert!(resources.contains_key("../../config/schemas/std.offchain_transport.schema.json"));
|
assert!(resources.contains_key("../../config/schemas/std.offchain_transport.schema.json"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// file: crates/ksp-app-solprices-desk/tests/desktop_security.rs
|
// file: crates/ksp-app-solprices-desk/tests/desktop_security.rs
|
||||||
// version: 1
|
// version: 2
|
||||||
|
|
||||||
//! Security and ownership canaries for the non-functional SOL Prices Desk scaffold.
|
//! Security, ownership and frontend instrumentation canaries for SOL Prices Desk.
|
||||||
|
|
||||||
fn app_root() -> std::path::PathBuf {
|
fn app_root() -> std::path::PathBuf {
|
||||||
return std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
return std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||||
@@ -69,7 +69,7 @@ fn pre_002_frontend_has_no_network_persistence_or_native_dialog_surface() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pre_002_tauri_commands_remain_centralized_and_price_runtime_is_absent() {
|
fn pre_003_tauri_commands_remain_centralized_and_refresh_runtime_is_absent() {
|
||||||
let root = app_root();
|
let root = app_root();
|
||||||
let mut rust_files = std::vec::Vec::new();
|
let mut rust_files = std::vec::Vec::new();
|
||||||
collect_files(root.join("src").as_path(), "rs", &mut rust_files);
|
collect_files(root.join("src").as_path(), "rs", &mut rust_files);
|
||||||
@@ -82,8 +82,25 @@ fn pre_002_tauri_commands_remain_centralized_and_price_runtime_is_absent() {
|
|||||||
} else {
|
} else {
|
||||||
assert_eq!(count, 0, "{} declares a Tauri command outside tauri.rs", path.display());
|
assert_eq!(count, 0, "{} declares a Tauri command outside tauri.rs", path.display());
|
||||||
}
|
}
|
||||||
assert!(!source.contains("MarketPriceService"), "{} advances market-price runtime before pre.003", path.display());
|
assert!(!source.contains("MarketPriceRuntime"), "{} advances application price-state runtime before pre.004", path.display());
|
||||||
assert!(!source.contains("refresh_market_price"), "{} advances refresh commands before their planned tranche", path.display());
|
assert!(!source.contains("refresh_market_price"), "{} advances refresh commands before their planned tranche", path.display());
|
||||||
}
|
}
|
||||||
assert_eq!(command_count, 3);
|
assert_eq!(command_count, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pre_003_frontend_control_interactions_are_logged_without_business_values() {
|
||||||
|
let root = app_root();
|
||||||
|
let main = read_text(root.join("frontend/ts/main.ts").as_path());
|
||||||
|
let invoke = read_text(root.join("frontend/ts/invoke.ts").as_path());
|
||||||
|
assert!(main.contains(r#"button.addEventListener("click""#));
|
||||||
|
assert!(main.contains("SOL Prices Desk navigation control clicked"));
|
||||||
|
assert!(main.contains("frontendDebug"));
|
||||||
|
assert!(main.contains("SOL Prices Desk view activated"));
|
||||||
|
assert!(invoke.contains("Frontend IPC command requested"));
|
||||||
|
assert!(invoke.contains("Frontend IPC command completed"));
|
||||||
|
assert!(invoke.contains("frontendTrace"));
|
||||||
|
for forbidden in ["JSON.stringify(status)", "JSON.stringify(payload)", "apiKey", "authorization"] {
|
||||||
|
assert!(!main.contains(forbidden), "main frontend logging must not serialize business/secret values: {forbidden}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -53,6 +53,7 @@
|
|||||||
"icons/favicon.ico"
|
"icons/favicon.ico"
|
||||||
],
|
],
|
||||||
"resources": {
|
"resources": {
|
||||||
|
"../../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",
|
||||||
"../../config/std.offchain_transport.json": "config/std.offchain_transport.json",
|
"../../config/std.offchain_transport.json": "config/std.offchain_transport.json",
|
||||||
|
|||||||
@@ -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: 23
|
// version: 24
|
||||||
|
|
||||||
//! Desktop build, shell and Config-status contract audits for Wallet Desk.
|
//! Desktop build, shell and Config-status contract audits for Wallet Desk.
|
||||||
|
|
||||||
@@ -472,7 +472,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(), 10);
|
assert_eq!(resources.len(), 11);
|
||||||
|
assert_eq!(
|
||||||
|
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"),
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resources.get("../../config/composite.ksp-app-wallet-desk.json").and_then(serde_json::Value::as_str),
|
resources.get("../../config/composite.ksp-app-wallet-desk.json").and_then(serde_json::Value::as_str),
|
||||||
std::option::Option::Some("config/composite.ksp-app-wallet-desk.json"),
|
std::option::Option::Some("config/composite.ksp-app-wallet-desk.json"),
|
||||||
|
|||||||
@@ -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: 6
|
// version: 7
|
||||||
|
|
||||||
//! Release-wide deterministic compliance canaries for Wallet Desk.
|
//! Release-wide deterministic compliance canaries for Wallet Desk.
|
||||||
|
|
||||||
@@ -198,7 +198,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(), 10);
|
assert_eq!(resources.len(), 11);
|
||||||
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");
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: crates/ksp-config-lib/src/lib.rs
|
// file: crates/ksp-config-lib/src/lib.rs
|
||||||
// version: 19
|
// version: 20
|
||||||
|
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
#![deny(unreachable_pub)]
|
#![deny(unreachable_pub)]
|
||||||
@@ -150,6 +150,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 SOL Prices Desk composite configuration document.
|
||||||
|
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.
|
||||||
pub use self::registry::DEFAULT_COMPOSITE_KSP_APP_WALLET_DESK_FILENAME;
|
pub use self::registry::DEFAULT_COMPOSITE_KSP_APP_WALLET_DESK_FILENAME;
|
||||||
/// Default physical filename for the generic composite JSON Schema document.
|
/// Default physical filename for the generic composite JSON Schema document.
|
||||||
@@ -170,6 +172,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 SOL Prices Desk composite configuration document.
|
||||||
|
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.
|
||||||
pub use self::registry::FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK;
|
pub use self::registry::FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK;
|
||||||
/// Logical file identifier for the generic composite JSON Schema document.
|
/// Logical file identifier for the generic composite JSON Schema document.
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
// file: crates/ksp-config-lib/src/registry.rs
|
// file: crates/ksp-config-lib/src/registry.rs
|
||||||
// version: 11
|
// version: 12
|
||||||
|
|
||||||
/// 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 SOL Prices Desk composite configuration document.
|
||||||
|
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.
|
||||||
pub const DEFAULT_COMPOSITE_KSP_APP_WALLET_DESK_FILENAME: &str = "composite.ksp-app-wallet-desk.json";
|
pub const DEFAULT_COMPOSITE_KSP_APP_WALLET_DESK_FILENAME: &str = "composite.ksp-app-wallet-desk.json";
|
||||||
/// Default physical filename for the generic composite JSON Schema document.
|
/// Default physical filename for the generic composite JSON Schema document.
|
||||||
@@ -23,6 +25,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 SOL Prices Desk composite configuration document.
|
||||||
|
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.
|
||||||
pub const FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK: &str = "cfg.composite.ksp-app-wallet-desk";
|
pub const FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK: &str = "cfg.composite.ksp-app-wallet-desk";
|
||||||
/// Logical file identifier for the generic composite JSON Schema document.
|
/// Logical file identifier for the generic composite JSON Schema document.
|
||||||
@@ -148,13 +152,23 @@ 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 composite = ConfigFileDescriptor::new(
|
let solprices_composite = ConfigFileDescriptor::new(
|
||||||
|
FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK,
|
||||||
|
ConfigFileKind::Config,
|
||||||
|
DEFAULT_COMPOSITE_KSP_APP_SOLPRICES_DESK_FILENAME,
|
||||||
|
std::option::Option::Some(FILE_ID_SCHEMA_COMPOSITE),
|
||||||
|
);
|
||||||
|
let solprices_composite = match solprices_composite {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
|
};
|
||||||
|
let wallet_composite = ConfigFileDescriptor::new(
|
||||||
FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK,
|
FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK,
|
||||||
ConfigFileKind::Config,
|
ConfigFileKind::Config,
|
||||||
DEFAULT_COMPOSITE_KSP_APP_WALLET_DESK_FILENAME,
|
DEFAULT_COMPOSITE_KSP_APP_WALLET_DESK_FILENAME,
|
||||||
std::option::Option::Some(FILE_ID_SCHEMA_COMPOSITE),
|
std::option::Option::Some(FILE_ID_SCHEMA_COMPOSITE),
|
||||||
);
|
);
|
||||||
let composite = match composite {
|
let wallet_composite = match wallet_composite {
|
||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
};
|
};
|
||||||
@@ -233,7 +247,8 @@ 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([
|
||||||
composite,
|
solprices_composite,
|
||||||
|
wallet_composite,
|
||||||
composite_schema,
|
composite_schema,
|
||||||
logging,
|
logging,
|
||||||
logging_schema,
|
logging_schema,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: crates/ksp-config-lib/tests/ownership.rs
|
// file: crates/ksp-config-lib/tests/ownership.rs
|
||||||
// version: 7
|
// version: 8
|
||||||
|
|
||||||
//! Workspace ownership audits for KSP application configuration boundaries.
|
//! Workspace ownership audits for KSP application configuration boundaries.
|
||||||
|
|
||||||
@@ -262,6 +262,7 @@ fn workspace_crates_do_not_hardcode_config_managed_physical_files() {
|
|||||||
};
|
};
|
||||||
for token in [
|
for token in [
|
||||||
"\".env\"",
|
"\".env\"",
|
||||||
|
"\"composite.ksp-app-solprices-desk.json\"",
|
||||||
"\"composite.ksp-app-wallet-desk.json\"",
|
"\"composite.ksp-app-wallet-desk.json\"",
|
||||||
"\"composite.schema.json\"",
|
"\"composite.schema.json\"",
|
||||||
"\"std.logging.json\"",
|
"\"std.logging.json\"",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: crates/ksp-config-lib/tests/public_api.rs
|
// file: crates/ksp-config-lib/tests/public_api.rs
|
||||||
// version: 24
|
// version: 25
|
||||||
|
|
||||||
//! 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 adapters and management contracts.
|
//! Logging/Transport adapters and management contracts.
|
||||||
@@ -80,18 +80,19 @@ 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(), 10);
|
assert_eq!(descriptors.len(), 11);
|
||||||
assert_eq!(descriptors[0].file_id().as_str(), ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK);
|
assert_eq!(descriptors[0].file_id().as_str(), ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK);
|
||||||
assert_eq!(descriptors[1].file_id().as_str(), ksp_config_lib::FILE_ID_STD_LOGGING);
|
assert_eq!(descriptors[1].file_id().as_str(), ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK);
|
||||||
assert_eq!(descriptors[2].file_id().as_str(), ksp_config_lib::FILE_ID_STD_OFFCHAIN_TRANSPORT);
|
assert_eq!(descriptors[2].file_id().as_str(), ksp_config_lib::FILE_ID_STD_LOGGING);
|
||||||
assert_eq!(descriptors[3].file_id().as_str(), ksp_config_lib::FILE_ID_STD_TRANSPORT);
|
assert_eq!(descriptors[3].file_id().as_str(), ksp_config_lib::FILE_ID_STD_OFFCHAIN_TRANSPORT);
|
||||||
assert_eq!(descriptors[4].file_id().as_str(), ksp_config_lib::FILE_ID_STD_WALLET);
|
assert_eq!(descriptors[4].file_id().as_str(), ksp_config_lib::FILE_ID_STD_TRANSPORT);
|
||||||
assert_eq!(descriptors[5].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_COMPOSITE);
|
assert_eq!(descriptors[5].file_id().as_str(), ksp_config_lib::FILE_ID_STD_WALLET);
|
||||||
assert_eq!(descriptors[6].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_LOGGING);
|
assert_eq!(descriptors[6].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_COMPOSITE);
|
||||||
assert_eq!(descriptors[7].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_OFFCHAIN_TRANSPORT);
|
assert_eq!(descriptors[7].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_STD_TRANSPORT);
|
assert_eq!(descriptors[8].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_WALLET);
|
assert_eq!(descriptors[9].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_TRANSPORT);
|
||||||
let schema_file_id = descriptors[4].schema_file_id();
|
assert_eq!(descriptors[10].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_WALLET);
|
||||||
|
let schema_file_id = descriptors[5].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);
|
||||||
@@ -160,6 +161,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_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_ne!(ksp_config_lib::ConfigProfileSelectionSource::Composite, ksp_config_lib::ConfigProfileSelectionSource::Explicit);
|
assert_ne!(ksp_config_lib::ConfigProfileSelectionSource::Composite, ksp_config_lib::ConfigProfileSelectionSource::Explicit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: crates/ksp-config-lib/unit_tests/offchain_transport.rs
|
// file: crates/ksp-config-lib/unit_tests/offchain_transport.rs
|
||||||
// version: 2
|
// version: 3
|
||||||
|
|
||||||
const TEST_PAIR: &str = "Czfq3xZZDmsdGdUyrNLtRhGc47cXcZtLG4crryfu44zE";
|
const TEST_PAIR: &str = "Czfq3xZZDmsdGdUyrNLtRhGc47cXcZtLG4crryfu44zE";
|
||||||
|
|
||||||
@@ -31,6 +31,45 @@ fn committed_public_keyless_profile_maps_all_eight_providers_without_secret_envi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn committed_solprices_composite_preserves_offchain_profile_and_composite_provenance() {
|
||||||
|
let engine = committed_engine();
|
||||||
|
let engine = match engine {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(_) => return,
|
||||||
|
};
|
||||||
|
let file_id = crate::ConfigFileId::new(crate::FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK);
|
||||||
|
assert!(file_id.is_ok(), "SOL Prices 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 SOL Prices Desk composite should resolve: {composite:?}");
|
||||||
|
let composite = match composite {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(_) => return,
|
||||||
|
};
|
||||||
|
assert_eq!(composite.profile_id(), "public_keyless");
|
||||||
|
let component = composite.component("offchain_transport");
|
||||||
|
assert!(component.is_some(), "SOL Prices Desk composite should expose offchain_transport");
|
||||||
|
let component = match component {
|
||||||
|
std::option::Option::Some(value) => value,
|
||||||
|
std::option::Option::None => return,
|
||||||
|
};
|
||||||
|
assert_eq!(component.resolved().file_id().as_str(), crate::FILE_ID_STD_OFFCHAIN_TRANSPORT);
|
||||||
|
assert_eq!(component.resolved().profile_id(), "public_keyless");
|
||||||
|
assert_eq!(component.resolved().selection_source(), crate::ConfigProfileSelectionSource::Composite);
|
||||||
|
let environment = crate::ConfigEnvironment::from_maps(std::collections::BTreeMap::new(), std::collections::BTreeMap::new());
|
||||||
|
let resolved = engine.resolve_offchain_transport_config_profile(component.resolved(), &environment);
|
||||||
|
assert!(resolved.is_ok(), "composite-selected Off-chain Transport should map: {resolved:?}");
|
||||||
|
if let std::result::Result::Ok(resolved) = resolved {
|
||||||
|
assert_eq!(resolved.profile_id(), "public_keyless");
|
||||||
|
assert_eq!(resolved.selection_source(), crate::ConfigProfileSelectionSource::Composite);
|
||||||
|
assert_eq!(resolved.service().registry().len(), 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn committed_all_free_profile_requires_config_owned_secrets_and_public_pair_provenance() {
|
fn committed_all_free_profile_requires_config_owned_secrets_and_public_pair_provenance() {
|
||||||
let engine = committed_engine();
|
let engine = committed_engine();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: crates/ksp-config-lib/unit_tests/registry.rs
|
// file: crates/ksp-config-lib/unit_tests/registry.rs
|
||||||
// version: 9
|
// version: 10
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn descriptors_expose_complete_registry_in_deterministic_file_id_order() {
|
fn descriptors_expose_complete_registry_in_deterministic_file_id_order() {
|
||||||
@@ -7,23 +7,25 @@ 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(), 10);
|
assert_eq!(descriptors.len(), 11);
|
||||||
assert_eq!(descriptors[0].file_id().as_str(), crate::FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK);
|
assert_eq!(descriptors[0].file_id().as_str(), crate::FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK);
|
||||||
assert_eq!(descriptors[0].filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_KSP_APP_WALLET_DESK_FILENAME));
|
assert_eq!(descriptors[0].filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_KSP_APP_SOLPRICES_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_STD_LOGGING);
|
assert_eq!(descriptors[1].file_id().as_str(), crate::FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK);
|
||||||
assert_eq!(descriptors[2].file_id().as_str(), crate::FILE_ID_STD_OFFCHAIN_TRANSPORT);
|
assert_eq!(descriptors[1].filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_KSP_APP_WALLET_DESK_FILENAME));
|
||||||
assert_eq!(descriptors[3].file_id().as_str(), crate::FILE_ID_STD_TRANSPORT);
|
assert_eq!(descriptors[2].file_id().as_str(), crate::FILE_ID_STD_LOGGING);
|
||||||
assert_eq!(descriptors[4].file_id().as_str(), crate::FILE_ID_STD_WALLET);
|
assert_eq!(descriptors[3].file_id().as_str(), crate::FILE_ID_STD_OFFCHAIN_TRANSPORT);
|
||||||
assert_eq!(descriptors[4].filename(), std::path::Path::new(crate::DEFAULT_STD_WALLET_FILENAME));
|
assert_eq!(descriptors[4].file_id().as_str(), crate::FILE_ID_STD_TRANSPORT);
|
||||||
assert_eq!(descriptors[4].schema_file_id().map(crate::ConfigFileId::as_str), std::option::Option::Some(crate::FILE_ID_SCHEMA_STD_WALLET));
|
assert_eq!(descriptors[5].file_id().as_str(), crate::FILE_ID_STD_WALLET);
|
||||||
assert_eq!(descriptors[5].file_id().as_str(), crate::FILE_ID_SCHEMA_COMPOSITE);
|
assert_eq!(descriptors[5].filename(), std::path::Path::new(crate::DEFAULT_STD_WALLET_FILENAME));
|
||||||
assert_eq!(descriptors[6].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_LOGGING);
|
assert_eq!(descriptors[5].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_STD_OFFCHAIN_TRANSPORT);
|
assert_eq!(descriptors[6].file_id().as_str(), crate::FILE_ID_SCHEMA_COMPOSITE);
|
||||||
assert_eq!(descriptors[8].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_TRANSPORT);
|
assert_eq!(descriptors[7].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_LOGGING);
|
||||||
assert_eq!(descriptors[9].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_WALLET);
|
assert_eq!(descriptors[8].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_OFFCHAIN_TRANSPORT);
|
||||||
assert!(descriptors[0..5].iter().all(|descriptor| return descriptor.kind() == crate::ConfigFileKind::Config));
|
assert_eq!(descriptors[9].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_TRANSPORT);
|
||||||
assert!(descriptors[5..10].iter().all(|descriptor| return descriptor.kind() == crate::ConfigFileKind::Schema));
|
assert_eq!(descriptors[10].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_WALLET);
|
||||||
|
assert!(descriptors[0..6].iter().all(|descriptor| return descriptor.kind() == crate::ConfigFileKind::Config));
|
||||||
|
assert!(descriptors[6..11].iter().all(|descriptor| return descriptor.kind() == crate::ConfigFileKind::Schema));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,24 +339,33 @@ fn absolute_fixture_path() -> std::path::PathBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn defaults_register_generic_composite_schema_and_wallet_desk_runtime_composite() {
|
fn defaults_register_generic_composite_schema_and_both_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 runtime_id = crate::ConfigFileId::new(crate::FILE_ID_COMPOSITE_KSP_APP_WALLET_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);
|
||||||
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!(runtime_id.is_ok(), "Wallet Desk composite runtime file_id should be valid: {runtime_id:?}");
|
assert!(solprices_id.is_ok(), "SOL Prices Desk composite runtime file_id should be valid: {solprices_id:?}");
|
||||||
if let (std::result::Result::Ok(registry), std::result::Result::Ok(schema_id), std::result::Result::Ok(runtime_id)) = (registry, schema_id, runtime_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)) =
|
||||||
|
(registry, schema_id, solprices_id, wallet_id)
|
||||||
|
{
|
||||||
let schema = registry.descriptor(&schema_id);
|
let schema = registry.descriptor(&schema_id);
|
||||||
let runtime = registry.descriptor(&runtime_id);
|
let solprices = registry.descriptor(&solprices_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!(runtime.is_ok(), "Wallet Desk runtime composite should be registered: {runtime:?}");
|
assert!(solprices.is_ok(), "SOL Prices Desk runtime composite should be registered: {solprices:?}");
|
||||||
if let (std::result::Result::Ok(schema), std::result::Result::Ok(runtime)) = (schema, runtime) {
|
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) {
|
||||||
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!(runtime.kind(), crate::ConfigFileKind::Config);
|
assert_eq!(solprices.kind(), crate::ConfigFileKind::Config);
|
||||||
assert_eq!(runtime.filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_KSP_APP_WALLET_DESK_FILENAME));
|
assert_eq!(solprices.filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_KSP_APP_SOLPRICES_DESK_FILENAME));
|
||||||
assert_eq!(runtime.schema_file_id(), std::option::Option::Some(&schema_id));
|
assert_eq!(solprices.schema_file_id(), std::option::Option::Some(&schema_id));
|
||||||
|
assert_eq!(wallet.kind(), crate::ConfigFileKind::Config);
|
||||||
|
assert_eq!(wallet.filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_KSP_APP_WALLET_DESK_FILENAME));
|
||||||
|
assert_eq!(wallet.schema_file_id(), std::option::Option::Some(&schema_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
250
deltas/0.2.12/pre.003.md
Normal file
250
deltas/0.2.12/pre.003.md
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
<!-- file: deltas/0.2.12/pre.003.md -->
|
||||||
|
<!-- version: 1 -->
|
||||||
|
|
||||||
|
# Delta `0.2.12-pre.003` — composite Config et bootstrap Off-chain
|
||||||
|
|
||||||
|
## 1. Base requise
|
||||||
|
|
||||||
|
Cette tranche s'applique exclusivement après :
|
||||||
|
|
||||||
|
```text
|
||||||
|
v0.2.11
|
||||||
|
+ 0.2.12-pre.001
|
||||||
|
+ 0.2.12-pre.001-fix.001
|
||||||
|
+ 0.2.12-pre.002
|
||||||
|
+ 0.2.12-pre.002-fix.001
|
||||||
|
```
|
||||||
|
|
||||||
|
Le retour opérateur du `27 août 2026` clôt proprement `pre.002-fix.001` : `cargo fmt`, installation npm, audits Rust/Markdown, `cargo check --workspace`, Clippy workspace, `cargo test -p ksp-app-solprices-desk` et `cargo tauri dev` passent sans warning Rust. `cargo test --workspace` n'a pas été rejoué dans ce retour précis et n'est pas revendiqué comme tel.
|
||||||
|
|
||||||
|
La version workspace passe à :
|
||||||
|
|
||||||
|
```text
|
||||||
|
0.2.12-pre.3
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. Responsabilité de la tranche
|
||||||
|
|
||||||
|
`pre.003` matérialise uniquement la composition Config du nouveau Desk et son bootstrap Off-chain provider-neutral :
|
||||||
|
|
||||||
|
```text
|
||||||
|
nouveau composite SOL Prices Desk
|
||||||
|
nouveau descriptor Config
|
||||||
|
registry Config 10 -> 11 descriptors
|
||||||
|
resources Config packagées 10 -> 11 dans les trois Desks
|
||||||
|
Logging du SOL Prices Desk sélectionné par composite
|
||||||
|
ResolvedOffchainTransportConfig construit au bootstrap
|
||||||
|
MarketPriceService détenu indirectement par Config
|
||||||
|
provenance Composite conservée
|
||||||
|
Diagnostics bootstrap sûrs
|
||||||
|
instrumentation frontend durable pour les contrôles existants
|
||||||
|
```
|
||||||
|
|
||||||
|
La tranche n'introduit encore aucun `MarketPriceRuntime`, row provider, observation affichée ni commande de refresh.
|
||||||
|
|
||||||
|
## 3. Composite SOL Prices Desk
|
||||||
|
|
||||||
|
Le document ajouté est :
|
||||||
|
|
||||||
|
```text
|
||||||
|
config/composite.ksp-app-solprices-desk.json
|
||||||
|
file_id = cfg.composite.ksp-app-solprices-desk
|
||||||
|
schema = schema.composite
|
||||||
|
```
|
||||||
|
|
||||||
|
Il contient exactement les profils prévus :
|
||||||
|
|
||||||
|
```text
|
||||||
|
public_keyless (default)
|
||||||
|
logging -> cfg.std.logging / console_info
|
||||||
|
offchain_transport -> cfg.std.offchain_transport / public_keyless
|
||||||
|
|
||||||
|
all_free
|
||||||
|
logging -> cfg.std.logging / console_info
|
||||||
|
offchain_transport -> cfg.std.offchain_transport / all_free
|
||||||
|
|
||||||
|
tests
|
||||||
|
logging -> cfg.std.logging / console_info
|
||||||
|
offchain_transport -> cfg.std.offchain_transport / public_keyless
|
||||||
|
```
|
||||||
|
|
||||||
|
Les composants sont résolus par `file_id`; aucun filename physique n'est connu du code applicatif.
|
||||||
|
|
||||||
|
## 4. Registry et packaging atomiques
|
||||||
|
|
||||||
|
`ksp-config-lib` enregistre le nouveau descriptor avec le schema composite existant. L'inventaire passe à **11 descriptors** : 6 documents Config et 5 schemas.
|
||||||
|
|
||||||
|
Comme `prepare_packaged_runtime` travaille sur le registry logique complet, la même tranche ajoute le nouveau resource mapping aux trois applications packagées :
|
||||||
|
|
||||||
|
```text
|
||||||
|
ksp-app-config-desk 11 resources
|
||||||
|
ksp-app-wallet-desk 11 resources
|
||||||
|
ksp-app-solprices-desk 11 resources
|
||||||
|
```
|
||||||
|
|
||||||
|
Les canaris historiques de Config Desk et Wallet Desk sont mis à jour pour rendre cette atomicité durable.
|
||||||
|
|
||||||
|
## 5. Bootstrap Config -> Off-chain
|
||||||
|
|
||||||
|
SOL Prices Desk charge son composite via `FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK` puis vérifie explicitement les composants obligatoires :
|
||||||
|
|
||||||
|
```text
|
||||||
|
logging -> FILE_ID_STD_LOGGING
|
||||||
|
offchain_transport -> FILE_ID_STD_OFFCHAIN_TRANSPORT
|
||||||
|
```
|
||||||
|
|
||||||
|
Le profil Logging du composite alimente le runtime Logging existant. Le profil Off-chain sélectionné est ensuite transmis à :
|
||||||
|
|
||||||
|
```text
|
||||||
|
ConfigDocumentEngine::resolve_offchain_transport_config_profile
|
||||||
|
```
|
||||||
|
|
||||||
|
Le résultat `ResolvedOffchainTransportConfig` reste détenu par l'état backend. Pour le profil default `public_keyless`, le service construit par Config expose les huit entrées provider-neutral déjà définies par `0.2.11`.
|
||||||
|
|
||||||
|
Aucune dépendance provider, URL, API key, rate limit ou logique HTTP n'est recréée dans la crate applicative.
|
||||||
|
|
||||||
|
## 6. État runtime exposé
|
||||||
|
|
||||||
|
`get_runtime_status` reste une commande de diagnostic et expose uniquement des projections sûres supplémentaires :
|
||||||
|
|
||||||
|
```text
|
||||||
|
active_composite_profile
|
||||||
|
active_logging_profile
|
||||||
|
active_offchain_profile
|
||||||
|
config_document_count
|
||||||
|
application_version
|
||||||
|
fallback_logging_active
|
||||||
|
shell_phase
|
||||||
|
startup_diagnostic sûr
|
||||||
|
```
|
||||||
|
|
||||||
|
Aucun provider individuel, prix, credential, endpoint ou payload Off-chain n'est projeté dans cette tranche.
|
||||||
|
|
||||||
|
## 7. Logging frontend durable
|
||||||
|
|
||||||
|
Conformément à `KSP-APP-027`, les contrôles frontend existants sont instrumentés via le bridge commun :
|
||||||
|
|
||||||
|
```text
|
||||||
|
clic / action utilisateur debug
|
||||||
|
transition de vue debug
|
||||||
|
demande IPC debug
|
||||||
|
fin technique IPC trace
|
||||||
|
échec contrôlé error/warn selon le chemin existant
|
||||||
|
```
|
||||||
|
|
||||||
|
Les logs ne sérialisent pas de valeurs métier ou secrètes. Le canari ajouté impose ce comportement avant l'arrivée des boutons prix : les futurs refresh row/many/all devront journaliser l'action, l'ID opaque/count/code sûr lorsque nécessaire, jamais prix brut, API key, header ou payload provider.
|
||||||
|
|
||||||
|
## 8. Tests et canaris ajoutés/étendus
|
||||||
|
|
||||||
|
`ksp-config-lib` couvre désormais :
|
||||||
|
|
||||||
|
```text
|
||||||
|
inventaire exact des 11 descriptors
|
||||||
|
public constants du nouveau composite
|
||||||
|
provenance Composite du profil Off-chain
|
||||||
|
construction du service public_keyless depuis le composite
|
||||||
|
interdiction de hardcoder le nouveau filename hors Config
|
||||||
|
```
|
||||||
|
|
||||||
|
SOL Prices Desk couvre :
|
||||||
|
|
||||||
|
```text
|
||||||
|
profils composite public_keyless / all_free / tests
|
||||||
|
mapping logging + offchain_transport exact
|
||||||
|
provenance Composite
|
||||||
|
service provider-neutral à huit entrées pour public_keyless
|
||||||
|
11 resources packagées
|
||||||
|
absence de MarketPriceRuntime avant pre.004
|
||||||
|
absence de refresh avant pre.005
|
||||||
|
logging debug des contrôles/navigation
|
||||||
|
logging debug/trace du wrapper IPC
|
||||||
|
```
|
||||||
|
|
||||||
|
## 9. Fichiers ajoutés
|
||||||
|
|
||||||
|
```text
|
||||||
|
config/composite.ksp-app-solprices-desk.json
|
||||||
|
crates/ksp-app-solprices-desk/src/offchain_runtime.rs
|
||||||
|
crates/ksp-app-solprices-desk/tests/config_composition.rs
|
||||||
|
deltas/0.2.12/pre.003.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## 10. Fichiers modifiés
|
||||||
|
|
||||||
|
```text
|
||||||
|
Cargo.toml
|
||||||
|
crates/ksp-app-config-desk/tauri.conf.json
|
||||||
|
crates/ksp-app-config-desk/tests/desktop_contract.rs
|
||||||
|
crates/ksp-app-solprices-desk/package.json
|
||||||
|
crates/ksp-app-solprices-desk/tauri.conf.json
|
||||||
|
crates/ksp-app-solprices-desk/frontend/main.html
|
||||||
|
crates/ksp-app-solprices-desk/frontend/ts/main.ts
|
||||||
|
crates/ksp-app-solprices-desk/src/app_state.rs
|
||||||
|
crates/ksp-app-solprices-desk/src/bootstrap.rs
|
||||||
|
crates/ksp-app-solprices-desk/src/constants.rs
|
||||||
|
crates/ksp-app-solprices-desk/src/dto_common.rs
|
||||||
|
crates/ksp-app-solprices-desk/src/errors.rs
|
||||||
|
crates/ksp-app-solprices-desk/src/lib.rs
|
||||||
|
crates/ksp-app-solprices-desk/tests/desktop_contract.rs
|
||||||
|
crates/ksp-app-solprices-desk/tests/desktop_security.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
|
||||||
|
crates/ksp-config-lib/src/lib.rs
|
||||||
|
crates/ksp-config-lib/src/registry.rs
|
||||||
|
crates/ksp-config-lib/tests/ownership.rs
|
||||||
|
crates/ksp-config-lib/tests/public_api.rs
|
||||||
|
crates/ksp-config-lib/unit_tests/offchain_transport.rs
|
||||||
|
crates/ksp-config-lib/unit_tests/registry.rs
|
||||||
|
docs/plans/019-V0_2_12_SOL_PRICES_DESK_PLAN.md
|
||||||
|
docs/validation/015-V0_2_12_SOL_PRICES_DESK.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## 11. Fichiers volontairement inchangés
|
||||||
|
|
||||||
|
```text
|
||||||
|
crates/ksp-offchain-transport-lib/**
|
||||||
|
crates/ksp-app-wallet-desk/src/**
|
||||||
|
crates/ksp-app-wallet-desk/frontend/**
|
||||||
|
crates/ksp-app-config-desk/src/**
|
||||||
|
crates/ksp-app-config-desk/frontend/**
|
||||||
|
README.md
|
||||||
|
ROADMAP.md
|
||||||
|
CHANGELOG.md
|
||||||
|
prompts/017-V0_2_12_START_PROMPT.md
|
||||||
|
```
|
||||||
|
|
||||||
|
L'intégration Off-chain de Wallet Desk reste propriétaire des tranches ultérieures. Le présent changement Wallet/Config Desk est strictement limité à la cohérence des resources packagées et de leurs canaris.
|
||||||
|
|
||||||
|
## 12. Validations exécutées dans le sandbox
|
||||||
|
|
||||||
|
Après matérialisation de la tranche et du delta :
|
||||||
|
|
||||||
|
```text
|
||||||
|
python3 scripts/audit_rust_workspace_rules.py PASS
|
||||||
|
General Rust rule audit clean
|
||||||
|
Rust export completeness audit 0 candidate
|
||||||
|
KSP workspace Rust rule audit clean
|
||||||
|
|
||||||
|
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.2.12
|
||||||
|
PASS
|
||||||
|
JSON parse composite/package/tauri.conf modifiés PASS
|
||||||
|
```
|
||||||
|
|
||||||
|
Le sandbox ne possède pas `cargo`; les commandes Cargo ne sont donc pas déclarées PASS localement.
|
||||||
|
|
||||||
|
## 13. Gate opérateur attendu
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo fmt --all
|
||||||
|
python3 scripts/audit_rust_workspace_rules.py
|
||||||
|
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas/0.2.12
|
||||||
|
cargo check --workspace
|
||||||
|
cargo clippy --workspace --all-targets
|
||||||
|
cargo test -p ksp-config-lib
|
||||||
|
cargo test -p ksp-app-solprices-desk
|
||||||
|
cargo test --workspace
|
||||||
|
(cd crates/ksp-app-solprices-desk && cargo tauri dev)
|
||||||
|
```
|
||||||
|
|
||||||
|
Le `cargo tauri dev` doit confirmer que le Desk démarre avec le composite default `public_keyless`, que Diagnostics affiche les profils composite/Off-chain et `11` documents Config, et qu'aucune table prix ni requête de refresh n'est encore présente.
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: docs/plans/019-V0_2_12_SOL_PRICES_DESK_PLAN.md -->
|
<!-- file: docs/plans/019-V0_2_12_SOL_PRICES_DESK_PLAN.md -->
|
||||||
<!-- version: 4 -->
|
<!-- version: 5 -->
|
||||||
|
|
||||||
# Plan `0.2.12` — SOL Prices Desk + intégration prix Wallet Desk
|
# Plan `0.2.12` — SOL Prices Desk + intégration prix Wallet Desk
|
||||||
|
|
||||||
@@ -472,19 +472,19 @@ Remplacement du forecast tabulaire par des sous-sections éditables avec statut
|
|||||||
|
|
||||||
### `pre.002` — Scaffold `ksp-app-solprices-desk`
|
### `pre.002` — Scaffold `ksp-app-solprices-desk`
|
||||||
|
|
||||||
**Statut : implémenté ; gate opérateur à confirmer.**
|
**Statut : réalisé ; gate opérateur de tranche PASS.**
|
||||||
|
|
||||||
Création du scaffold strict de `ksp-app-solprices-desk` : crate lib/bin, shell Tauri, frontend de base, splash, logging et paire de ports réservée `1434/1435`. La tranche n'implémente encore ni table prix, ni `MarketPriceService`, ni refresh réseau.
|
Création du scaffold strict de `ksp-app-solprices-desk` : crate lib/bin, shell Tauri, frontend de base, splash, logging et paire de ports réservée `1434/1435`. La tranche n'implémente encore ni table prix, ni `MarketPriceService`, ni refresh réseau.
|
||||||
|
|
||||||
#### `pre.002-fix.001` — Alignement strict du gabarit desktop commun
|
#### `pre.002-fix.001` — Alignement strict du gabarit desktop commun
|
||||||
|
|
||||||
**Statut : implémenté ; gate opérateur à confirmer.**
|
**Statut : réalisé ; gate opérateur de tranche PASS.**
|
||||||
|
|
||||||
Correction du scaffold pour reprendre réellement les conventions communes Config/Wallet Desk : dépendances frontend de gabarit, `ResizeObserver`, identité de fenêtre, footer, police/provenance splash, vocabulaire SCSS partagé, commande `get_runtime_status`, instrumentation shell et canaris anti-dérive. Aucun runtime Off-chain, composite ni table prix n'est avancé.
|
Correction du scaffold pour reprendre réellement les conventions communes Config/Wallet Desk : dépendances frontend de gabarit, `ResizeObserver`, identité de fenêtre, footer, police/provenance splash, vocabulaire SCSS partagé, commande `get_runtime_status`, instrumentation shell et canaris anti-dérive. Aucun runtime Off-chain, composite ni table prix n'est avancé.
|
||||||
|
|
||||||
### `pre.003` — Composite Config et bootstrap Off-chain
|
### `pre.003` — Composite Config et bootstrap Off-chain
|
||||||
|
|
||||||
**Statut : planifié.**
|
**Statut : implémenté ; gate opérateur à confirmer.**
|
||||||
|
|
||||||
Ajout atomique du composite `cfg.composite.ksp-app-solprices-desk`, de son descriptor registry et des resources packagées nécessaires aux trois Desks concernés, puis bootstrap Config -> Off-chain Transport du nouveau Desk. Le gate exige que le packaging Config reste cohérent ; aucune UI prix n'est ajoutée ici.
|
Ajout atomique du composite `cfg.composite.ksp-app-solprices-desk`, de son descriptor registry et des resources packagées nécessaires aux trois Desks concernés, puis bootstrap Config -> Off-chain Transport du nouveau Desk. Le gate exige que le packaging Config reste cohérent ; aucune UI prix n'est ajoutée ici.
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: docs/validation/015-V0_2_12_SOL_PRICES_DESK.md -->
|
<!-- file: docs/validation/015-V0_2_12_SOL_PRICES_DESK.md -->
|
||||||
<!-- version: 3 -->
|
<!-- version: 4 -->
|
||||||
|
|
||||||
# Validation `0.2.12` — SOL Prices Desk + intégration Wallet Desk
|
# Validation `0.2.12` — SOL Prices Desk + intégration Wallet Desk
|
||||||
|
|
||||||
@@ -79,16 +79,16 @@ NOT RUN commande non exécutée dans le contexte indiqué
|
|||||||
|
|
||||||
| Contrat | Valeur attendue | Statut |
|
| Contrat | Valeur attendue | Statut |
|
||||||
|---------------------------------------|--------------------------------------------------------------|---------|
|
|---------------------------------------|--------------------------------------------------------------|---------|
|
||||||
| Price Desk composite file | `config/composite.ksp-app-solprices-desk.json` | PENDING |
|
| Price Desk composite file | `config/composite.ksp-app-solprices-desk.json` | PASS |
|
||||||
| Price Desk file_id | `cfg.composite.ksp-app-solprices-desk` | PENDING |
|
| Price Desk file_id | `cfg.composite.ksp-app-solprices-desk` | PASS |
|
||||||
| schema | `schema.composite` existant | PENDING |
|
| schema | `schema.composite` existant | PASS |
|
||||||
| components | `logging`, `offchain_transport` | PENDING |
|
| components | `logging`, `offchain_transport` | PENDING |
|
||||||
| default profile | `public_keyless` | PENDING |
|
| default profile | `public_keyless` | PENDING |
|
||||||
| optional profile | `all_free` | PENDING |
|
| optional profile | `all_free` | PENDING |
|
||||||
| test profile | `tests` -> offchain `public_keyless` | PENDING |
|
| test profile | `tests` -> offchain `public_keyless` | PENDING |
|
||||||
| Wallet composite | ajoute offchain `public_keyless` à devnet/temporary/tests | PENDING |
|
| Wallet composite | ajoute offchain `public_keyless` à devnet/temporary/tests | PENDING |
|
||||||
| registry/resource count | 11 après nouveau composite | PENDING |
|
| registry/resource count | 11 après nouveau composite | PASS |
|
||||||
| registry + resources atomiques | Config + Config Desk + Wallet Desk + Price Desk même tranche | PENDING |
|
| registry + resources atomiques | Config + Config Desk + Wallet Desk + Price Desk même tranche | PASS |
|
||||||
| nouveau schema Config | inutile | OUT |
|
| nouveau schema Config | inutile | OUT |
|
||||||
| modification `std.offchain_transport` | pas de lacune identifiée | OUT |
|
| modification `std.offchain_transport` | pas de lacune identifiée | OUT |
|
||||||
|
|
||||||
@@ -149,7 +149,7 @@ NOT RUN commande non exécutée dans le contexte indiqué
|
|||||||
| frontendDist | hors source, path Price Desk dédié | PASS |
|
| frontendDist | hors source, path Price Desk dédié | PASS |
|
||||||
| hooks | npm dev/build cwd crate | PASS |
|
| hooks | npm dev/build cwd crate | PASS |
|
||||||
| backend cross-app | aucune référence Wallet par erreur | PASS |
|
| backend cross-app | aucune référence Wallet par erreur | PASS |
|
||||||
| resources | registry complet packagé | PENDING |
|
| resources | registry complet packagé | PASS |
|
||||||
| bundle | targets/icons cohérents | PASS |
|
| bundle | targets/icons cohérents | PASS |
|
||||||
| Tauri production build Price Desk | crate-local PASS attendu | PENDING |
|
| Tauri production build Price Desk | crate-local PASS attendu | PENDING |
|
||||||
| Tauri production build Wallet Desk | crate-local PASS attendu | PENDING |
|
| Tauri production build Wallet Desk | crate-local PASS attendu | PENDING |
|
||||||
@@ -220,7 +220,7 @@ python3 scripts/audit_markdown_tables.py README.md ... deltas PASS
|
|||||||
cargo fmt/check/clippy/test NOT RUN — cargo indisponible dans le sandbox
|
cargo fmt/check/clippy/test NOT RUN — cargo indisponible dans le sandbox
|
||||||
```
|
```
|
||||||
|
|
||||||
Le statut de `pre.002` reste donc « implémenté ; gate opérateur à confirmer » jusqu'au retour du gate Cargo de l'opérateur.
|
Le retour opérateur du `27 août 2026` clôt le gate de tranche : `cargo fmt --all`, installation npm, audits Rust/Markdown, `cargo check --workspace`, Clippy workspace, `cargo test -p ksp-app-solprices-desk` et `cargo tauri dev` passent. Le test applicatif exécute 12 unit tests, 4 canaris `desktop_contract`, 3 canaris `desktop_security` et 1 canari `public_api`, tous PASS.
|
||||||
|
|
||||||
## 14. Gate `0.2.12-pre.002-fix.001`
|
## 14. Gate `0.2.12-pre.002-fix.001`
|
||||||
|
|
||||||
@@ -239,4 +239,33 @@ TRACING_DOMAIN_SHELL réellement consommé PAS
|
|||||||
MarketPriceService / composite / refresh / table prix absent par contrat
|
MarketPriceService / composite / refresh / table prix absent par contrat
|
||||||
```
|
```
|
||||||
|
|
||||||
Le gate Cargo du checkout opérateur précédent a confirmé que `pre.002` compile et que ses tests passent, mais il signalait deux warnings `TRACING_DOMAIN_SHELL` unused. Le fix consomme désormais ce domaine dans `configure_setup`; le gate complet doit être rejoué sur `0.2.12-pre.2.fix.1` avant passage à `pre.003`.
|
Le gate opérateur du `27 août 2026` sur `0.2.12-pre.2.fix.1` est propre : audits Rust/Markdown, `cargo check --workspace`, `cargo clippy --workspace --all-targets` et `cargo test -p ksp-app-solprices-desk` passent sans les deux warnings précédents. `cargo tauri dev` démarre Vite sur `1434` puis le backend Rust sans warning. `cargo test --workspace` n'a pas été rejoué dans ce retour précis et n'est donc pas revendiqué ici.
|
||||||
|
|
||||||
|
## 15. Gate `0.2.12-pre.003`
|
||||||
|
|
||||||
|
La tranche matérialise uniquement la composition Config et le bootstrap Off-chain provider-neutral :
|
||||||
|
|
||||||
|
```text
|
||||||
|
composite cfg.composite.ksp-app-solprices-desk PASS structurel
|
||||||
|
profils public_keyless / all_free / tests PASS structurel
|
||||||
|
composants logging + offchain_transport par file_id PASS structurel
|
||||||
|
registry Config 11 descriptors
|
||||||
|
resources Config Desk / Wallet Desk / SOL Prices Desk 11/11 chacune
|
||||||
|
Logging SOL Prices Desk résolu depuis le composite PASS structurel
|
||||||
|
ResolvedOffchainTransportConfig construit au bootstrap PASS structurel
|
||||||
|
service provider-neutral public_keyless 8 entrées attendues par canari
|
||||||
|
MarketPriceRuntime / rows / observations / refresh commands absent par contrat pre.003
|
||||||
|
navigation et contrôles frontend existants journalisés en debug PASS structurel/canari
|
||||||
|
IPC frontend request/completion debug / trace
|
||||||
|
```
|
||||||
|
|
||||||
|
Le contrat de logging frontend est volontairement durable : action utilisateur et transition de vue en `debug`, étapes techniques fréquentes/fin d'IPC en `trace`, sans sérialiser prix, credentials, headers ni payloads métier. Les futurs boutons de refresh devront reprendre le même bridge et le même niveau de discipline.
|
||||||
|
|
||||||
|
Validations sandbox après matérialisation :
|
||||||
|
|
||||||
|
```text
|
||||||
|
python3 scripts/audit_rust_workspace_rules.py PASS
|
||||||
|
python3 scripts/audit_markdown_tables.py README.md ... deltas PASS
|
||||||
|
validation syntaxique des JSON modifiés PASS
|
||||||
|
cargo fmt/check/clippy/test NOT RUN — cargo indisponible dans le sandbox
|
||||||
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user