v0.1.4-pre.017

This commit is contained in:
2026-08-16 19:49:21 +02:00
parent fd200f5335
commit 4216b6b783
18 changed files with 858 additions and 32 deletions

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-config-desk/src/constants.rs
// version: 8
// version: 9
//! Application-owned tracing targets and domains.
@@ -11,6 +11,8 @@ pub(crate) const TRACING_TARGET_FRONTEND: &str = "ksp-app-config-desk.frontend";
pub(crate) const TRACING_TARGET_FRONTEND_MAIN: &str = "ksp-app-config-desk.frontend.main";
/// Owning target for splash-window frontend events.
pub(crate) const TRACING_TARGET_FRONTEND_SPLASH: &str = "ksp-app-config-desk.frontend.splash";
/// Dedicated target used by the controlled Logging test panel.
pub(crate) const TRACING_TARGET_LOGGING_TEST: &str = "ksp-app-config-desk.logging-test";
/// Structured domain used while bootstrapping Config and Logging.
pub(crate) const TRACING_DOMAIN_BOOTSTRAP: &str = "config.bootstrap";
/// Structured domain used by technical frontend events.
@@ -29,3 +31,5 @@ pub(crate) const TRACING_DOMAIN_SECRETS: &str = "config.secrets";
pub(crate) const TRACING_DOMAIN_LOGGING_EDITOR: &str = "config.logging_editor";
/// Structured domain for active Logging runtime metadata and explicit profile application.
pub(crate) const TRACING_DOMAIN_LOGGING_RUNTIME: &str = "config.logging_runtime";
/// Structured domain used by controlled Logging test events.
pub(crate) const TRACING_DOMAIN_LOGGING_TEST: &str = "config.logging_test";

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-config-desk/src/errors.rs
// version: 8
// version: 9
//! Application-local error codes for the configuration desktop shell.
@@ -18,6 +18,8 @@ pub(crate) const ERROR_CODE_APP_STATE_LOCK_FAILED: ksp_core_lib::ErrorCode = ksp
pub(crate) const ERROR_CODE_FRONTEND_LOG_LEVEL_INVALID: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("config_desk", "frontend_log_level_invalid");
/// Frontend logging requested a target outside the application whitelist.
pub(crate) const ERROR_CODE_FRONTEND_LOG_TARGET_INVALID: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("config_desk", "frontend_log_target_invalid");
/// Controlled Logging test request contains an unsupported or invalid selector.
pub(crate) const ERROR_CODE_LOGGING_TEST_REQUEST_INVALID: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("config_desk", "logging_test_request_invalid");
/// A validated Config document does not expose the standard profile contract expected by the Profiles panel.
pub(crate) const ERROR_CODE_PROFILE_CONTRACT_MISSING: ksp_core_lib::ErrorCode = ksp_core_lib::ErrorCode::new("config_desk", "profile_contract_missing");

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-config-desk/src/lib.rs
// version: 13
// version: 14
//! Tauri desktop application for managing and validating KSP configuration.
@@ -17,6 +17,7 @@ mod errors;
mod frontend_logging;
mod logging_editor;
mod logging_runtime;
mod logging_test;
mod profiles;
mod secrets;
mod splash;
@@ -36,6 +37,7 @@ pub(crate) use self::constants::TRACING_DOMAIN_ENVIRONMENT;
pub(crate) use self::constants::TRACING_DOMAIN_FRONTEND;
pub(crate) use self::constants::TRACING_DOMAIN_LOGGING_EDITOR;
pub(crate) use self::constants::TRACING_DOMAIN_LOGGING_RUNTIME;
pub(crate) use self::constants::TRACING_DOMAIN_LOGGING_TEST;
pub(crate) use self::constants::TRACING_DOMAIN_PROFILES;
pub(crate) use self::constants::TRACING_DOMAIN_SECRETS;
pub(crate) use self::constants::TRACING_DOMAIN_WINDOWS;
@@ -43,6 +45,7 @@ pub(crate) use self::constants::TRACING_TARGET;
pub(crate) use self::constants::TRACING_TARGET_FRONTEND;
pub(crate) use self::constants::TRACING_TARGET_FRONTEND_MAIN;
pub(crate) use self::constants::TRACING_TARGET_FRONTEND_SPLASH;
pub(crate) use self::constants::TRACING_TARGET_LOGGING_TEST;
pub(crate) use self::documents::ConfigDocumentDetailDto;
pub(crate) use self::documents::ConfigDocumentErrorDto;
pub(crate) use self::documents::ConfigDocumentSaveResultDto;
@@ -58,6 +61,7 @@ pub(crate) use self::errors::ERROR_CODE_FRONTEND_LOG_LEVEL_INVALID;
pub(crate) use self::errors::ERROR_CODE_FRONTEND_LOG_TARGET_INVALID;
pub(crate) use self::errors::ERROR_CODE_LOGGING_BOOTSTRAP_FAILED;
pub(crate) use self::errors::ERROR_CODE_LOGGING_SOURCE_ROLLBACK_FAILED;
pub(crate) use self::errors::ERROR_CODE_LOGGING_TEST_REQUEST_INVALID;
pub(crate) use self::errors::ERROR_CODE_PROFILE_CONTRACT_MISSING;
pub(crate) use self::errors::ERROR_CODE_PROFILE_PROJECTION_FAILED;
pub(crate) use self::errors::ERROR_CODE_SECRET_REVEAL_REQUIRES_SECRET;
@@ -73,6 +77,7 @@ pub(crate) use self::logging_editor::LoggingDocumentCandidateDto;
pub(crate) use self::logging_editor::LoggingDocumentDto;
pub(crate) use self::logging_editor::LoggingDocumentSaveResultDto;
pub(crate) use self::logging_runtime::{LoggingRuntimeFileDto, LoggingRuntimeStatusDto};
pub(crate) use self::logging_test::{LoggingTestRequestDto, LoggingTestResultDto};
pub(crate) use self::profiles::ConfigProfileDetailDto;
pub(crate) use self::profiles::ConfigProfileDocumentDto;
pub(crate) use self::secrets::SecretRevealRequestDto;

View File

@@ -0,0 +1,428 @@
// file: crates/ksp-app-config-desk/src/logging_test.rs
// version: 1
//! Controlled Logging test events for validating KSP runtime routing from Config Desk.
use ts_rs::TS; // rust-rules: derive-import
/// Controlled request emitted through the backend KSP Logging facade.
#[derive(Clone, Debug, serde::Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_config_desk/logging_test/LoggingTestRequestDto.ts")]
pub(crate) struct LoggingTestRequestDto {
/// Requested level: trace/debug/info/warn/error/all.
pub(crate) level: String,
/// Controlled backend target identifier.
pub(crate) target_id: String,
/// Domain selection mode: absent/known/custom.
pub(crate) domain_mode: String,
/// Selected known domain or custom domain token.
pub(crate) domain: String,
/// Human test message emitted as the event body.
pub(crate) message: String,
}
/// Safe result metadata for one controlled backend Logging test request.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_config_desk/logging_test/LoggingTestResultDto.ts")]
pub(crate) struct LoggingTestResultDto {
/// Number of Logging events emitted by the request.
pub(crate) emitted_event_count: u32,
/// Requested level selector.
pub(crate) requested_level: String,
/// Effective static KSP target used by the emitted events.
pub(crate) target: String,
/// Effective domain, or `None` when domain routing is intentionally absent.
pub(crate) domain: std::option::Option<String>,
/// Logging runtime generation active while the events were emitted.
pub(crate) logging_generation: u32,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum LoggingTestLevel {
Trace,
Debug,
Info,
Warn,
Error,
All,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum LoggingTestTarget {
App,
Dedicated,
}
/// Emits one controlled backend test request through `ksp-logging-lib` only.
pub(crate) fn emit(state: &crate::AppState, request: LoggingTestRequestDto) -> ksp_core_lib::Result<LoggingTestResultDto> {
let level = parse_level(request.level.as_str());
let level = match level {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let target = parse_target(request.target_id.as_str());
let target = match target {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let domain = resolve_domain(request.domain_mode.as_str(), request.domain.as_str());
let domain = match domain {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let message = validate_message(request.message.as_str());
let message = match message {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let runtime_status = state.logging_runtime_status();
let runtime_status = match runtime_status {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let emitted_event_count = emit_levels(level, target, domain.as_deref(), message);
return std::result::Result::Ok(LoggingTestResultDto {
emitted_event_count,
requested_level: request.level.trim().to_ascii_lowercase(),
target: target_value(target).to_owned(),
domain,
logging_generation: runtime_status.generation,
});
}
fn parse_level(level: &str) -> ksp_core_lib::Result<LoggingTestLevel> {
return match level.trim().to_ascii_lowercase().as_str() {
"trace" => std::result::Result::Ok(LoggingTestLevel::Trace),
"debug" => std::result::Result::Ok(LoggingTestLevel::Debug),
"info" => std::result::Result::Ok(LoggingTestLevel::Info),
"warn" => std::result::Result::Ok(LoggingTestLevel::Warn),
"error" => std::result::Result::Ok(LoggingTestLevel::Error),
"all" => std::result::Result::Ok(LoggingTestLevel::All),
_ => invalid_request("Logging test level is not supported"),
};
}
fn parse_target(target_id: &str) -> ksp_core_lib::Result<LoggingTestTarget> {
return match target_id.trim().to_ascii_lowercase().as_str() {
"app" => std::result::Result::Ok(LoggingTestTarget::App),
"logging_test" => std::result::Result::Ok(LoggingTestTarget::Dedicated),
_ => invalid_request("Logging test target is not supported"),
};
}
fn resolve_domain(domain_mode: &str, domain: &str) -> ksp_core_lib::Result<std::option::Option<String>> {
return match domain_mode.trim().to_ascii_lowercase().as_str() {
"absent" => std::result::Result::Ok(std::option::Option::None),
"known" => resolve_known_domain(domain),
"custom" => resolve_custom_domain(domain),
_ => invalid_request("Logging test domain mode is not supported"),
};
}
fn resolve_known_domain(domain: &str) -> ksp_core_lib::Result<std::option::Option<String>> {
return match domain.trim() {
crate::TRACING_DOMAIN_LOGGING_TEST | crate::TRACING_DOMAIN_LOGGING_RUNTIME | crate::TRACING_DOMAIN_FRONTEND => {
std::result::Result::Ok(std::option::Option::Some(domain.trim().to_owned()))
},
_ => invalid_request("Logging test known domain is not supported"),
};
}
fn resolve_custom_domain(domain: &str) -> ksp_core_lib::Result<std::option::Option<String>> {
let domain = domain.trim();
if domain.is_empty() || domain.len() > 80 || !domain.chars().all(is_domain_character) {
return invalid_request("Logging test custom domain is invalid");
}
return std::result::Result::Ok(std::option::Option::Some(domain.to_owned()));
}
fn is_domain_character(character: char) -> bool {
return character.is_ascii_alphanumeric() || character == '.' || character == '_' || character == '-';
}
fn validate_message(message: &str) -> ksp_core_lib::Result<&str> {
let message = message.trim();
if message.is_empty() || message.len() > 500 {
return invalid_request("Logging test message must contain between 1 and 500 bytes");
}
return std::result::Result::Ok(message);
}
fn invalid_request<T>(message: &str) -> ksp_core_lib::Result<T> {
return std::result::Result::Err(ksp_core_lib::Error::new(crate::ERROR_CODE_LOGGING_TEST_REQUEST_INVALID, message));
}
const fn target_value(target: LoggingTestTarget) -> &'static str {
return match target {
LoggingTestTarget::App => crate::TRACING_TARGET,
LoggingTestTarget::Dedicated => crate::TRACING_TARGET_LOGGING_TEST,
};
}
fn emit_levels(level: LoggingTestLevel, target: LoggingTestTarget, domain: std::option::Option<&str>, message: &str) -> u32 {
return match level {
LoggingTestLevel::Trace => {
emit_one(LoggingTestLevel::Trace, target, domain, message);
1
},
LoggingTestLevel::Debug => {
emit_one(LoggingTestLevel::Debug, target, domain, message);
1
},
LoggingTestLevel::Info => {
emit_one(LoggingTestLevel::Info, target, domain, message);
1
},
LoggingTestLevel::Warn => {
emit_one(LoggingTestLevel::Warn, target, domain, message);
1
},
LoggingTestLevel::Error => {
emit_one(LoggingTestLevel::Error, target, domain, message);
1
},
LoggingTestLevel::All => {
emit_one(LoggingTestLevel::Trace, target, domain, message);
emit_one(LoggingTestLevel::Debug, target, domain, message);
emit_one(LoggingTestLevel::Info, target, domain, message);
emit_one(LoggingTestLevel::Warn, target, domain, message);
emit_one(LoggingTestLevel::Error, target, domain, message);
5
},
};
}
fn emit_one(level: LoggingTestLevel, target: LoggingTestTarget, domain: std::option::Option<&str>, message: &str) {
return match target {
LoggingTestTarget::App => emit_app_target(level, domain, message),
LoggingTestTarget::Dedicated => emit_dedicated_target(level, domain, message),
};
}
fn emit_app_target(level: LoggingTestLevel, domain: std::option::Option<&str>, message: &str) {
return match level {
LoggingTestLevel::Trace => emit_app_trace(domain, message),
LoggingTestLevel::Debug => emit_app_debug(domain, message),
LoggingTestLevel::Info => emit_app_info(domain, message),
LoggingTestLevel::Warn => emit_app_warn(domain, message),
LoggingTestLevel::Error => emit_app_error(domain, message),
LoggingTestLevel::All => (),
};
}
fn emit_dedicated_target(level: LoggingTestLevel, domain: std::option::Option<&str>, message: &str) {
return match level {
LoggingTestLevel::Trace => emit_dedicated_trace(domain, message),
LoggingTestLevel::Debug => emit_dedicated_debug(domain, message),
LoggingTestLevel::Info => emit_dedicated_info(domain, message),
LoggingTestLevel::Warn => emit_dedicated_warn(domain, message),
LoggingTestLevel::Error => emit_dedicated_error(domain, message),
LoggingTestLevel::All => (),
};
}
fn emit_app_trace(domain: std::option::Option<&str>, message: &str) {
return match domain {
std::option::Option::Some(domain) => ksp_logging_lib::trace!(
target: crate::TRACING_TARGET,
domain = domain,
action = "logging_test",
test_source = "backend",
test_level = "trace",
"{message}"
),
std::option::Option::None => ksp_logging_lib::trace!(
target: crate::TRACING_TARGET,
action = "logging_test",
test_source = "backend",
test_level = "trace",
"{message}"
),
};
}
fn emit_app_debug(domain: std::option::Option<&str>, message: &str) {
return match domain {
std::option::Option::Some(domain) => ksp_logging_lib::debug!(
target: crate::TRACING_TARGET,
domain = domain,
action = "logging_test",
test_source = "backend",
test_level = "debug",
"{message}"
),
std::option::Option::None => ksp_logging_lib::debug!(
target: crate::TRACING_TARGET,
action = "logging_test",
test_source = "backend",
test_level = "debug",
"{message}"
),
};
}
fn emit_app_info(domain: std::option::Option<&str>, message: &str) {
return match domain {
std::option::Option::Some(domain) => ksp_logging_lib::info!(
target: crate::TRACING_TARGET,
domain = domain,
action = "logging_test",
test_source = "backend",
test_level = "info",
"{message}"
),
std::option::Option::None => ksp_logging_lib::info!(
target: crate::TRACING_TARGET,
action = "logging_test",
test_source = "backend",
test_level = "info",
"{message}"
),
};
}
fn emit_app_warn(domain: std::option::Option<&str>, message: &str) {
return match domain {
std::option::Option::Some(domain) => ksp_logging_lib::warn!(
target: crate::TRACING_TARGET,
domain = domain,
action = "logging_test",
test_source = "backend",
test_level = "warn",
"{message}"
),
std::option::Option::None => ksp_logging_lib::warn!(
target: crate::TRACING_TARGET,
action = "logging_test",
test_source = "backend",
test_level = "warn",
"{message}"
),
};
}
fn emit_app_error(domain: std::option::Option<&str>, message: &str) {
return match domain {
std::option::Option::Some(domain) => ksp_logging_lib::error!(
target: crate::TRACING_TARGET,
domain = domain,
action = "logging_test",
test_source = "backend",
test_level = "error",
"{message}"
),
std::option::Option::None => ksp_logging_lib::error!(
target: crate::TRACING_TARGET,
action = "logging_test",
test_source = "backend",
test_level = "error",
"{message}"
),
};
}
fn emit_dedicated_trace(domain: std::option::Option<&str>, message: &str) {
return match domain {
std::option::Option::Some(domain) => ksp_logging_lib::trace!(
target: crate::TRACING_TARGET_LOGGING_TEST,
domain = domain,
action = "logging_test",
test_source = "backend",
test_level = "trace",
"{message}"
),
std::option::Option::None => ksp_logging_lib::trace!(
target: crate::TRACING_TARGET_LOGGING_TEST,
action = "logging_test",
test_source = "backend",
test_level = "trace",
"{message}"
),
};
}
fn emit_dedicated_debug(domain: std::option::Option<&str>, message: &str) {
return match domain {
std::option::Option::Some(domain) => ksp_logging_lib::debug!(
target: crate::TRACING_TARGET_LOGGING_TEST,
domain = domain,
action = "logging_test",
test_source = "backend",
test_level = "debug",
"{message}"
),
std::option::Option::None => ksp_logging_lib::debug!(
target: crate::TRACING_TARGET_LOGGING_TEST,
action = "logging_test",
test_source = "backend",
test_level = "debug",
"{message}"
),
};
}
fn emit_dedicated_info(domain: std::option::Option<&str>, message: &str) {
return match domain {
std::option::Option::Some(domain) => ksp_logging_lib::info!(
target: crate::TRACING_TARGET_LOGGING_TEST,
domain = domain,
action = "logging_test",
test_source = "backend",
test_level = "info",
"{message}"
),
std::option::Option::None => ksp_logging_lib::info!(
target: crate::TRACING_TARGET_LOGGING_TEST,
action = "logging_test",
test_source = "backend",
test_level = "info",
"{message}"
),
};
}
fn emit_dedicated_warn(domain: std::option::Option<&str>, message: &str) {
return match domain {
std::option::Option::Some(domain) => ksp_logging_lib::warn!(
target: crate::TRACING_TARGET_LOGGING_TEST,
domain = domain,
action = "logging_test",
test_source = "backend",
test_level = "warn",
"{message}"
),
std::option::Option::None => ksp_logging_lib::warn!(
target: crate::TRACING_TARGET_LOGGING_TEST,
action = "logging_test",
test_source = "backend",
test_level = "warn",
"{message}"
),
};
}
fn emit_dedicated_error(domain: std::option::Option<&str>, message: &str) {
return match domain {
std::option::Option::Some(domain) => ksp_logging_lib::error!(
target: crate::TRACING_TARGET_LOGGING_TEST,
domain = domain,
action = "logging_test",
test_source = "backend",
test_level = "error",
"{message}"
),
std::option::Option::None => ksp_logging_lib::error!(
target: crate::TRACING_TARGET_LOGGING_TEST,
action = "logging_test",
test_source = "backend",
test_level = "error",
"{message}"
),
};
}
#[cfg(test)]
#[path = "../unit_tests/logging_test.rs"]
mod tests;

View File

@@ -1,5 +1,5 @@
// file: crates/ksp-app-config-desk/src/tauri.rs
// version: 14
// version: 15
//! Tauri runtime assembly for the KSP configuration desktop application.
@@ -52,6 +52,7 @@ fn configure_commands(builder: tauri::Builder<tauri::Wry>) -> tauri::Builder<tau
get_logging_runtime_status,
apply_logging_profile,
save_logging_document,
emit_logging_test,
emit_frontend_log,
splash_frontend_ready
]);
@@ -216,6 +217,18 @@ fn save_logging_document(
};
}
#[tauri::command]
fn emit_logging_test(
request: crate::LoggingTestRequestDto,
state: tauri::State<'_, crate::AppState>,
) -> std::result::Result<crate::LoggingTestResultDto, crate::CommandErrorDto> {
let result = crate::logging_test::emit(&state, request);
return match result {
std::result::Result::Ok(value) => std::result::Result::Ok(value),
std::result::Result::Err(error) => std::result::Result::Err(crate::CommandErrorDto::from_error(&error)),
};
}
#[tauri::command]
fn emit_frontend_log(payload: crate::FrontendLogPayloadDto) -> std::result::Result<(), crate::CommandErrorDto> {
let result = crate::emit_frontend_log_event(payload);