v0.1.4-pre.011

This commit is contained in:
2026-08-16 15:14:37 +02:00
parent f0f2954236
commit 00361f22f4
15 changed files with 523 additions and 20 deletions

View File

@@ -0,0 +1,119 @@
// file: crates/ksp-app-config-desk/src/environment.rs
// version: 1
//! Safe Config environment report projections for Config Desk.
use ts_rs::TS; // rust-rules: derive-import
/// Safe desired/effective environment view exposed to the ordinary Config Desk frontend.
#[derive(Clone, Debug, serde::Serialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export, export_to = "../frontend/ts/bindings/ksp_app_config_desk/environment/ConfigEnvironmentReportDto.ts")]
pub(crate) struct ConfigEnvironmentReportDto {
/// Supported KSP/KSPB variable name.
pub(crate) variable_name: String,
/// Namespace family derived from the variable name without inspecting its value.
pub(crate) namespace: String,
/// `public`, `internal` or `secret`.
pub(crate) sensitivity: String,
/// Persisted `.env` value using Config's safe/redacted representation.
pub(crate) desired_safe_value: std::option::Option<String>,
/// Currently effective process-or-`.env` value using Config's safe/redacted representation.
pub(crate) effective_safe_value: std::option::Option<String>,
/// Winning external source: `process`, `dotenv`, or `none`.
pub(crate) effective_source: String,
/// Whether the persisted `.env` value is shadowed by the inherited process environment.
pub(crate) shadowed_by_process_environment: bool,
}
/// Returns the safe environment report owned by Config.
pub(crate) fn report(state: &crate::AppState) -> ksp_core_lib::Result<std::vec::Vec<ConfigEnvironmentReportDto>> {
return report_from_management(state.config_management());
}
fn report_from_management(management: &ksp_config_lib::ConfigManagement) -> ksp_core_lib::Result<std::vec::Vec<ConfigEnvironmentReportDto>> {
let reports = management.environment_report();
let reports = match reports {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let mut result = std::vec::Vec::<ConfigEnvironmentReportDto>::with_capacity(reports.len());
let mut process_count = 0usize;
let mut dotenv_count = 0usize;
let mut shadowed_count = 0usize;
let mut secret_count = 0usize;
for report in reports {
let source = report.effective_source();
match source {
std::option::Option::Some(ksp_config_lib::ConfigEnvironmentSource::Process) => process_count += 1,
std::option::Option::Some(ksp_config_lib::ConfigEnvironmentSource::DotEnv) => dotenv_count += 1,
std::option::Option::Some(ksp_config_lib::ConfigEnvironmentSource::Fallback) | std::option::Option::None => {},
}
if report.shadowed_by_process_environment() {
shadowed_count += 1;
}
if report.sensitivity() == ksp_config_lib::ConfigSensitivity::Secret {
secret_count += 1;
}
result.push(ConfigEnvironmentReportDto {
variable_name: report.variable_name().to_owned(),
namespace: namespace_label(report.variable_name()).to_owned(),
sensitivity: sensitivity_label(report.sensitivity()).to_owned(),
desired_safe_value: report.desired_safe_value().map(str::to_owned),
effective_safe_value: report.effective_safe_value().map(str::to_owned),
effective_source: environment_source_label(source).to_owned(),
shadowed_by_process_environment: report.shadowed_by_process_environment(),
});
}
ksp_logging_lib::debug!(
target: crate::TRACING_TARGET,
domain = crate::TRACING_DOMAIN_ENVIRONMENT,
variable_count = result.len(),
process_count,
dotenv_count,
shadowed_count,
secret_count,
"Config environment report evaluated"
);
return std::result::Result::Ok(result);
}
const fn environment_source_label(source: std::option::Option<ksp_config_lib::ConfigEnvironmentSource>) -> &'static str {
return match source {
std::option::Option::Some(ksp_config_lib::ConfigEnvironmentSource::Process) => "process",
std::option::Option::Some(ksp_config_lib::ConfigEnvironmentSource::DotEnv) => "dotenv",
std::option::Option::Some(ksp_config_lib::ConfigEnvironmentSource::Fallback) => "fallback",
std::option::Option::None => "none",
};
}
const fn sensitivity_label(sensitivity: ksp_config_lib::ConfigSensitivity) -> &'static str {
return match sensitivity {
ksp_config_lib::ConfigSensitivity::Public => "public",
ksp_config_lib::ConfigSensitivity::Internal => "internal",
ksp_config_lib::ConfigSensitivity::Secret => "secret",
};
}
fn namespace_label(variable_name: &str) -> &'static str {
if variable_name.starts_with("KSPB_SECRET_") {
return "KSPB_SECRET";
}
if variable_name.starts_with("KSPB_PUBLIC_") {
return "KSPB_PUBLIC";
}
if variable_name.starts_with("KSPB_") {
return "KSPB";
}
if variable_name.starts_with("KSP_SECRET_") {
return "KSP_SECRET";
}
if variable_name.starts_with("KSP_PUBLIC_") {
return "KSP_PUBLIC";
}
return "KSP";
}
#[cfg(test)]
#[path = "../unit_tests/environment.rs"]
mod tests;