use crate::chaos_utilities::ChaosConfig;
use crate::contract_drift::DriftBudgetConfig;
use crate::reality::RealityLevel;
use crate::workspace::{MockEnvironmentName, Workspace};
use serde_json::Value;
#[derive(Debug, Clone)]
pub struct TemplateEnvironmentConfig {
pub environment: MockEnvironmentName,
pub reality_level: Option<RealityLevel>,
pub reality_config: Option<crate::reality::RealityConfig>,
pub chaos_config: Option<ChaosConfig>,
pub drift_budget_config: Option<DriftBudgetConfig>,
}
#[derive(Debug, Clone)]
pub struct TemplateApplicationResult {
pub environments_configured: usize,
pub personas_created: usize,
pub scenarios_created: usize,
pub security_policies_applied: usize,
}
pub fn apply_template_to_workspace(
workspace: &mut Workspace,
blueprint_config: &Value,
security_baseline: &Value,
) -> Result<TemplateApplicationResult, String> {
let mut result = TemplateApplicationResult {
environments_configured: 0,
personas_created: 0,
scenarios_created: 0,
security_policies_applied: 0,
};
if let Some(env_configs) = blueprint_config.get("environments").and_then(|v| v.as_object()) {
for (env_name_str, env_config) in env_configs {
if let Some(env_name) = parse_environment_name(env_name_str) {
apply_environment_config(workspace, env_name, env_config)?;
result.environments_configured += 1;
}
}
}
if let Some(reality_level) = blueprint_config
.get("default_reality_level")
.and_then(|v| v.as_str())
.and_then(parse_reality_level)
{
workspace.config.reality_level = Some(reality_level);
}
if let Some(_validation_mode) =
security_baseline.get("default_validation_mode").and_then(|v| v.as_str())
{
result.security_policies_applied += 1;
}
if let Some(rbac_defaults) = security_baseline.get("rbac_defaults").and_then(|v| v.as_object())
{
result.security_policies_applied += rbac_defaults.len();
}
if let Some(personas) = blueprint_config.get("personas").and_then(|v| v.as_array()) {
result.personas_created = personas.len();
}
if let Some(scenarios) = blueprint_config.get("scenarios").and_then(|v| v.as_array()) {
result.scenarios_created = scenarios.len();
}
Ok(result)
}
fn apply_environment_config(
workspace: &mut Workspace,
env_name: MockEnvironmentName,
env_config: &Value,
) -> Result<(), String> {
let reality_config = env_config
.get("reality_config")
.and_then(|v| serde_json::from_value(v.clone()).ok());
let chaos_config = env_config
.get("chaos_config")
.and_then(|v| serde_json::from_value(v.clone()).ok());
let drift_budget_config = env_config
.get("drift_budget_config")
.and_then(|v| serde_json::from_value(v.clone()).ok());
workspace
.set_mock_environment_config(env_name, reality_config, chaos_config, drift_budget_config)
.map_err(|e| format!("Failed to set mock environment config: {}", e))?;
Ok(())
}
fn parse_environment_name(s: &str) -> Option<MockEnvironmentName> {
MockEnvironmentName::from_str(s)
}
fn parse_reality_level(s: &str) -> Option<RealityLevel> {
match s.to_lowercase().as_str() {
"1" | "static_stubs" | "static" => Some(RealityLevel::StaticStubs),
"2" | "light_simulation" | "light" => Some(RealityLevel::LightSimulation),
"3" | "moderate_realism" | "moderate" => Some(RealityLevel::ModerateRealism),
"4" | "high_realism" | "high" => Some(RealityLevel::HighRealism),
"5" | "production_chaos" | "production" | "prod" => Some(RealityLevel::ProductionChaos),
_ => None,
}
}
pub fn get_default_template_structure() -> Value {
serde_json::json!({
"environments": {
"dev": {
"reality_level": "light_simulation",
"chaos_config": {
"enabled": true,
"error_rate": 0.1,
"delay_rate": 0.2
},
"drift_budget_config": {
"enabled": true,
"default_budget": {
"max_breaking_changes": 5,
"max_non_breaking_changes": 10
}
}
},
"test": {
"reality_level": "moderate_realism",
"chaos_config": {
"enabled": true,
"error_rate": 0.05,
"delay_rate": 0.1
},
"drift_budget_config": {
"enabled": true,
"default_budget": {
"max_breaking_changes": 2,
"max_non_breaking_changes": 5
}
}
},
"prod": {
"reality_level": "high_realism",
"chaos_config": {
"enabled": false,
"error_rate": 0.0,
"delay_rate": 0.0
},
"drift_budget_config": {
"enabled": true,
"default_budget": {
"max_breaking_changes": 0,
"max_non_breaking_changes": 2
}
}
}
},
"default_reality_level": "moderate_realism",
"personas": [],
"scenarios": [],
"recommended_blueprints": []
})
}
pub fn get_default_security_baseline() -> Value {
serde_json::json!({
"default_validation_mode": "warn",
"rbac_defaults": {
"admin": ["*"],
"editor": ["MockCreate", "MockUpdate", "MockRead"],
"viewer": ["MockRead"]
},
"environment_permissions": {
"prod": {
"ManageSettings": ["admin", "platform"],
"ScenarioModifyRealityDefaults": ["platform"],
"ScenarioModifyChaosRules": ["qa"]
},
"test": {
"ScenarioModifyChaosRules": ["qa", "editor"]
}
}
})
}