Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/cdavid817_vanehub-ai.json
T

1 line
152 KiB
JSON

{"repo": "cdavid817/vanehub-ai", "files": {"src-tauri/src/contexts/tooling/cli_config/api.rs": {"cd7cca79453d578d189adda2e37c923a6c954ba5": {"t": 1785746254.3165758, "n": 74890, "h": "5625cc3a76311599", "c": "use super::application::{\n CliConfigCredentialPort, CliConfigRepository, CliGlobalConfigPort, ProjectionOutcome,\n};\nuse super::domain::{\n validate_profile_input, validate_supported_agent, AppliedStateRecord,\n ApplyCliConfigProfileInput, CliConfigAppliedState, CliConfigApplyResult,\n CliConfigDiscoveryCandidate, CliConfigDiscoveryResult, CliConfigDiscoveryState,\n CliConfigDriftResolution, CliConfigDriftState, CliConfigError, CliConfigPayload,\n CliConfigProfile, CliConfigStartupSyncResult, CliConfigStartupSyncState, CliConfigStatus,\n CliConfigValidationState, DeleteCliConfigProfileInput, ImportCliConfigProfileInput,\n ImportDiscoveredCliConfigInput, ImportDiscoveredCliConfigResult, ProfileRecord,\n SaveCliConfigProfileInput, SkippedCliConfigDiscoveryCandidate, PAYLOAD_VERSION,\n SUPPORTED_AGENT_IDS,\n};\nuse crate::contexts::operations::api::{DiagnosticLog, DiagnosticLogPort, LogSeverity};\nuse chrono::Utc;\nuse std::collections::{BTreeMap, BTreeSet};\nuse std::sync::{Arc, Mutex};\nuse uuid::Uuid;\n\n#[derive(Clone)]\npub(crate) struct CliConfigApi {\n repository: Arc<dyn CliConfigRepository>,\n credentials: Arc<dyn CliConfigCredentialPort>,\n live: Arc<dyn CliGlobalConfigPort>,\n logging: Arc<dyn DiagnosticLogPort>,\n apply_locks: Arc<BTreeMap<String, Arc<Mutex<()>>>>,\n startup_sync: Arc<Mutex<BTreeMap<String, CliConfigStartupSyncResult>>>,\n}\n\nimpl CliConfigApi {\n pub(crate) fn new(\n repository: Arc<dyn CliConfigRepository>,\n credentials: Arc<dyn CliConfigCredentialPort>,\n live: Arc<dyn CliGlobalConfigPort>,\n logging: Arc<dyn DiagnosticLogPort>,\n ) -> Self {\n let apply_locks = super::domain::SUPPORTED_AGENT_IDS\n .into_iter()\n .map(|agent_id| (agent_id.to_string(), Arc::new(Mutex::new(()))))\n .collect();\n let startup_sync = SUPPORTED_AGENT_IDS\n .into_iter()\n .map(|agent_id| {\n (\n agent_id.to_string(),\n startup_sync_result(agent_id, CliConfigStartupSyncState::Pending),\n )\n })\n .collect();\n Self {\n repository,\n credentials,\n live,\n logging,\n apply_locks: Arc::new(apply_locks),\n startup_sync: Arc::new(Mutex::new(startup_sync)),\n }\n }\n\n pub(crate) fn synchronize_startup(&self) -> Vec<CliConfigStartupSyncResult> {\n SUPPORTED_AGENT_IDS\n .into_iter()\n .map(|agent_id| {\n let result = match self.synchronize_startup_agent(agent_id) {\n Ok(result) => result,\n Err(error) => {\n let mut result =\n startup_sync_result(agent_id, CliConfigStartupSyncState::Warning);\n result.skipped = 1;\n result.warnings.push(startup_sync_warning(&error));\n result.synchronized_at = Some(Utc::now().to_rfc3339());\n result\n }\n };\n self.write_log(\n if result.state == CliConfigStartupSyncState::Warning {\n LogSeverity::Warn\n } else {\n LogSeverity::Info\n },\n \"cli.config.startup.sync\",\n agent_id,\n None,\n None,\n &format!(\n \"startup CLI configuration sync completed: state={:?}, imported={}, updated={}, skipped={}\",\n result.state, result.imported, result.updated, result.skipped\n ),\n );\n if let Ok(mut stored) = self.startup_sync.lock() {\n stored.insert(agent_id.to_string(), result.clone());\n }\n result\n })\n .collect()\n }\n\n fn synchronize_startup_agent(\n &self,\n agent_id: &str,\n ) -> Result<CliConfigStartupSyncResult, CliConfigError> {\n if agent_id == \"opencode\" {\n return self.synchronize_opencode_startup();\n }\n let existing = self.repository.list_profiles(agent_id)?;\n if !existing.is_empty() {\n let mut result = startup_sync_result(agent_id, CliConfigStartupSyncState::Skipped);\n result.skipped = 1;\n result.synchronized_at = Some(Utc::now().to_rfc3339());\n return Ok(result);\n }\n let discovery = self.live.discover_current(agent_id)?;\n let Some(candidate) = discovery.candidates.into_iter().next() else {\n let mut result = startup_sync_result(agent_id, CliConfigStartupSyncState::Unchanged);\n result.warnings = discovery.warnings;\n result.synchronized_at = Some(Utc::now().to_rfc3339());\n return Ok(result);\n };\n let profile_id = format!(\"{agent_id}-default\");\n let imported_credential = candidate.credential.is_some();\n let record = self.persist_live_profile(\n agent_id,\n profile_id,\n \"default\".to_string(),\n candidate.payload,\n candidate.credential.as_deref().map(String::as_str),\n None,\n )?;\n let inspection = self.live.inspect(agent_id, None, Some(&record))?;\n let applied = AppliedStateRecord {\n agent_id: agent_id.to_string(),\n profile_id: Some(record.id.clone()),\n projection_fingerprint: inspection.managed_fingerprint.clone(),\n live_fingerprint: inspection.managed_fingerprint,\n drift_state: CliConfigDriftState::Applied,\n applied_at: Utc::now().to_rfc3339(),\n applied_payload: Some(record.payload.clone()),\n managed_keys: record.managed_keys.clone(),\n };\n if let Err(error) = self.repository.save_applied_state(&applied) {\n let credential_restored =\n !imported_credential || self.credentials.delete(agent_id, &record.id).is_ok();\n let profile_restored = self.repository.delete_profile(agent_id, &record.id).is_ok();\n if !credential_restored || !profile_restored {\n return Err(CliConfigError::RollbackIncomplete);\n }\n return Err(error);\n }\n let mut result = startup_sync_result(agent_id, CliConfigStartupSyncState::Imported);\n result.imported = 1;\n result.warnings = discovery.warnings;\n result.synchronized_at = Some(Utc::now().to_rfc3339());\n Ok(result)\n }\n\n fn synchronize_opencode_startup(&self) -> Result<CliConfigStartupSyncResult, CliConfigError> {\n let agent_id = \"opencode\";\n let discovery = self.live.discover_current(agent_id)?;\n let mut existing = self.repository.list_profiles(agent_id)?;\n let mut result = startup_sync_result(agent_id, CliConfigStartupSyncState::Unchanged);\n result.warnings = discovery.warnings;\n for candidate in discovery.candidates {\n let provider_id = match &candidate.payload {\n CliConfigPayload::Opencode { provider_id, .. } => provider_id.clone(),\n _ => continue,\n };\n let matched = existing.iter().find(|profile| {\n matches!(\n &profile.payload,\n CliConfigPayload::Opencode {\n provider_id: existing_id,\n ..\n } if existing_id == &provider_id\n )\n });\n let profile_id = match matched {\n Some(profile) => profile.id.clone(),\n None => self.next_profile_id(&format!(\"opencode-{provider_id}\"))?,\n };\n let prior = matched.cloned();\n let prior_secret = self.credentials.load(agent_id, &profile_id)?;\n let incoming_secret = candidate.credential.as_deref().map(String::as_str);\n let changed = prior.as_ref().is_none_or(|profile| {\n profile.payload != candidate.payload\n || profile.name != candidate.suggested_name\n || prior_secret.as_deref().map(String::as_str) != incoming_secret\n });\n if !changed {\n result.skipped += 1;\n continue;\n }\n let record = self.persist_live_profile(\n agent_id,\n profile_id,\n candidate.suggested_name,\n candidate.payload,\n incoming_secret,\n prior.as_ref(),\n )?;\n if prior.is_some() {\n result.updated += 1;\n } else {\n result.imported += 1;\n existing.push(record);\n }\n }\n result.state = if result.updated > 0 {\n CliConfigStartupSyncState::Updated\n } else if result.imported > 0 {\n CliConfigStartupSyncState::Imported\n } else {\n CliConfigStartupSyncState::Unchanged\n };\n result.synchronized_at = Some(Utc::now().to_rfc3339());\n Ok(result)\n }\n\n fn persist_live_profile(\n &self,\n agent_id: &str,\n profile_id: String,\n name: String,\n payload: CliConfigPayload,\n credential: Option<&str>,\n existing: Option<&ProfileRecord>,\n ) -> Result<ProfileRecord, CliConfigError> {\n payload.validate()?;\n if payload.agent_id() != agent_id {\n return Err(CliConfigError::Validation(\n \"live configuration payload does not match the selected Agent\".into(),\n ));\n }\n if credential\n .is_some_and(|secret| secret.is_empty() || secret.chars().any(char::is_control))\n {\n return Err(CliConfigError::Validation(\n \"live configuration credential is invalid\".into(),\n ));\n }\n let sort_position = match existing {\n Some(profile) => profile.sort_position,\n None => self.repository.list_profiles(agent_id)?.len() as i64,\n };\n let previous_secret = self.credentials.load(agent_id, &profile_id)?;\n match credential {\n Some(secret) => self.credentials.store(agent_id, &profile_id, secret)?,\n None if previous_secret.is_some() => self.credentials.delete(agent_id, &profile_id)?,\n None => {}\n }\n let now = Utc::now().to_rfc3339();\n let record = ProfileRecord {\n id: profile_id.clone(),\n agent_id: agent_id.to_string(),\n name,\n payload_version: PAYLOAD_VERSION,\n managed_keys: payload.managed_keys(),\n payload,\n source_preset_id: None,\n source_preset_version: None,\n created_at: existing\n .map(|profile| profile.created_at.clone())\n .unwrap_or_else(|| now.clone()),\n updated_at: now,\n sort_position,\n };\n if let Err(error) = self.repository.save_profile(&record) {\n if self\n .restore_credential(\n agent_id,\n &profile_id,\n previous_secret.as_deref().map(String::as_str),\n )\n .is_err()\n {\n return Err(CliConfigError::RollbackIncomplete);\n }\n return Err(error);\n }\n Ok(record)\n }\n\n pub(crate) fn list_profiles(\n &self,\n agent_id: &str,\n ) -> Result<Vec<CliConfigProfile>, CliConfigError> {\n validate_supported_agent(agent_id)?;\n let status = self.inspect_status(agent_id)?;\n self.repository\n .list_profiles(agent_id)?\n .into_iter()\n .map(|record| self.profile_view(record, &status))\n .collect()\n }\n\n pub(crate) fn inspect_status(&self, agent_id: &str) -> Result<CliConfigStatus, CliConfigError> {\n validate_supported_agent(agent_id)?;\n let applied = self.repository.applied_state(agent_id)?;\n let applied_profile = applied\n .as_ref()\n .map(|state| self.applied_profile_snapshot(agent_id, state))\n .transpose()?\n .flatten();\n let inspection = self\n .live\n .inspect(agent_id, applied.as_ref(), applied_profile.as_ref())?;\n Ok(CliConfigStatus {\n agent_id: agent_id.to_string(),\n applied_profile_id: applied.as_ref().and_then(|state| state.profile_id.clone()),\n drift_state: inspection.state,\n resolved_paths: inspection\n .paths\n .into_iter()\n .map(|path| path.display().to_string())\n .collect(),\n last_applied_at: applied.map(|state| state.applied_at),\n simulated: false,\n startup_sync: self.startup_sync_result(agent_id),\n })\n }\n\n fn startup_sync_result(&self, agent_id: &str) -> CliConfigStartupSyncResult {\n self.startup_sync\n .lock()\n .ok()\n .and_then(|results| results.get(agent_id).cloned())\n .unwrap_or_else(|| startup_sync_result(agent_id, CliConfigStartupSyncState::Warning))\n }\n\n pub(crate) fn save_profile(\n &self,\n input: SaveCliConfigProfileInput,\n ) -> Result<CliConfigProfile, CliConfigError> {\n let agent_id = input.agent_id.clone();\n let result = self.save_profile_inner(input);\n self.log_result(\n \"cli.config.profile.save\",\n &agent_id,\n result.as_ref().ok().map(|p| p.id.as_str()),\n &result,\n );\n result\n }\n\n fn save_profile_inner(\n &self,\n input: SaveCliConfigProfileInput,\n ) -> Result<CliConfigProfile, CliConfigError> {\n validate_profile_input(&input)?;\n if input.credential.is_some() && input.remove_credential {\n return Err(CliConfigError::Validation(\n \"credential cannot be replaced and removed in one request\".into(),\n ));\n }\n if let Some(source_id) = input.source_preset_id.as_deref() {\n let compatible_prefix = format!(\"{}-\", input.agent_id);\n if !source_id.starts_with(&compatible_prefix) {\n return Err(CliConfigError::Validation(\n \"preset is incompatible with the selected Agent\".into(),\n ));\n }\n }\n\n let existing = input\n .id\n .as_deref()\n .map(|id| self.repository.get_profile(&input.agent_id, id))\n .transpose()?;\n let id = match &existing {\n Some(profile) => profile.id.clone(),\n None => self.next_profile_id(&input.name)?,\n };\n let previous_secret = self.credentials.load(&input.agent_id, &id)?;\n if existing.is_none()\n && input.payload.requires_credential()\n && input.credential.is_none()\n && !input.remove_credential\n {\n return Err(CliConfigError::CredentialRequired);\n }\n\n let wrote_credential = if let Some(secret) = input.credential.as_deref() {\n self.credentials.store(&input.agent_id, &id, secret)?;\n true\n } else if input.remove_credential {\n self.credentials.delete(&input.agent_id, &id)?;\n true\n } else {\n false\n };\n\n let now = Utc::now().to_rfc3339();\n let record = ProfileRecord {\n id: id.clone(),\n agent_id: input.agent_id.clone(),\n name: input.name.trim().to_string(),\n payload_version: PAYLOAD_VERSION,\n managed_keys: input.payload.managed_keys(),\n payload: input.payload,\n source_preset_id: input.source_preset_id,\n source_preset_version: input.source_preset_version,\n created_at: existing\n .as_ref()\n .map(|profile| profile.created_at.clone())\n .unwrap_or_else(|| now.clone()),\n updated_at: now,\n sort_position: existing\n .as_ref()\n .map(|profile| profile.sort_position)\n .unwrap_or(self.repository.list_profiles(&input.agent_id)?.len() as i64),\n };\n if let Err(error) = self.repository.save_profile(&record) {\n if wrote_credential {\n self.restore_credential(\n &input.agent_id,\n &id,\n previous_secret.as_deref().map(String::as_str),\n )?;\n }\n return Err(error);\n }\n let status = self.inspect_status(&input.agent_id)?;\n self.profile_view(record, &status)\n }\n\n pub(crate) fn duplicate_profile(\n &self,\n agent_id: &str,\n profile_id: &str,\n ) -> Result<CliConfigProfile, CliConfigError> {\n validate_supported_agent(agent_id)?;\n let source = self.repository.get_profile(agent_id, profile_id)?;\n let credential = self.credentials.load(agent_id, profile_id)?;\n let names = self\n .repository\n .list_profiles(agent_id)?\n .into_iter()\n .map(|profile| profile.name)\n .collect::<Vec<_>>();\n let name = unique_copy_name(&source.name, &names);\n self.save_profile(SaveCliConfigProfileInput {\n id: None,\n agent_id: source.agent_id,\n name,\n payload: source.payload,\n source_preset_id: source.source_preset_id,\n source_preset_version: source.source_preset_version,\n credential: credential.as_deref().map(ToString::to_string),\n remove_credential: false,\n })\n }\n\n pub(crate) fn delete_profile(\n &self,\n input: DeleteCliConfigProfileInput,\n ) -> Result<(), CliConfigError> {\n validate_supported_agent(&input.agent_id)?;\n let profile = self\n .repository\n .get_profile(&input.agent_id, &input.profile_id)?;\n let applied = self.repository.applied_state(&input.agent_id)?;\n let is_applied = applied\n .as_ref()\n .and_then(|state| state.profile_id.as_deref())\n == Some(input.profile_id.as_str());\n if is_applied && !input.detach_applied {\n return Err(CliConfigError::Validation(\n \"applied profile must be detached before deletion\".into(),\n ));\n }\n let previous_secret = self.credentials.load(&input.agent_id, &input.profile_id)?;\n if is_applied {\n self.repository.clear_applied_state(&input.agent_id)?;\n }\n if let Err(error) = self.credentials.delete(&input.agent_id, &input.profile_id) {\n if let Some(state) = &applied {\n self.repository.save_applied_state(state)?;\n }\n return Err(error);\n }\n if let Err(error) = self\n .repository\n .delete_profile(&input.agent_id, &input.profile_id)\n {\n self.restore_credential(\n &input.agent_id,\n &input.profile_id,\n previous_secret.as_deref().map(String::as_str),\n )?;\n if let Some(state) = &applied {\n self.repository.save_applied_state(state)?;\n }\n return Err(error);\n }\n self.write_log(\n LogSeverity::Info,\n \"cli.config.profile.delete\",\n &input.agent_id,\n Some(&profile.id),\n None,\n \"deleted CLI configuration profile\",\n );\n Ok(())\n }\n\n pub(crate) fn import_current(\n &self,\n input: ImportCliConfigProfileInput,\n ) -> Result<CliConfigProfile, CliConfigError> {\n validate_supported_agent(&input.agent_id)?;\n let imported = self.live.import_current(&input.agent_id)?;\n let result = self.save_profile(SaveCliConfigProfileInput {\n id: None,\n agent_id: input.agent_id.clone(),\n name: input.name,\n payload: imported.payload,\n source_preset_id: None,\n source_preset_version: None,\n credential: imported.credential.as_deref().map(ToString::to_string),\n remove_credential: false,\n });\n self.log_result(\n \"cli.config.profile.import\",\n &input.agent_id,\n result.as_ref().ok().map(|profile| profile.id.as_str()),\n &result,\n );\n result\n }\n\n pub(crate) fn discover_profiles(\n &self,\n agent_id: &str,\n ) -> Result<CliConfigDiscoveryResult, CliConfigError> {\n validate_supported_agent(agent_id)?;\n let resolved_paths = self\n .live\n .paths(agent_id)?\n .into_iter()\n .map(|path| path.display().to_string())\n .collect::<Vec<_>>();\n match self.live.discover_current(agent_id) {\n Ok(discovery) => {\n let candidate_paths = discovery\n .paths\n .iter()\n .map(|path| path.display().to_string())\n .collect::<Vec<_>>();\n Ok(CliConfigDiscoveryResult {\n agent_id: agent_id.to_string(),\n state: CliConfigDiscoveryState::Available,\n candidates: discovery\n .candidates\n .into_iter()\n .map(|candidate| CliConfigDiscoveryCandidate {\n candidate_key: candidate.candidate_key,\n suggested_name: candidate.suggested_name,\n provider_name: candidate.provider_name,\n endpoint: candidate.endpoint,\n model: candidate.model,\n credential_detected: candidate.credential.is_some(),\n is_default: candidate.is_default,\n resolved_paths: candidate_paths.clone(),\n })\n .collect(),\n resolved_paths: candidate_paths,\n warnings: discovery.warnings,\n error: None,\n simulated: false,\n })\n }\n Err(CliConfigError::Parse { path, message: _ }) => Ok(CliConfigDiscoveryResult {\n agent_id: agent_id.to_string(),\n state: CliConfigDiscoveryState::ParseError,\n candidates: Vec::new(),\n resolved_paths,\n warnings: Vec::new(),\n error: Some(format!(\n \"Could not parse {path} as a supported CLI configuration.\"\n )),\n simulated: false,\n }),\n Err(error) => Err(error),\n }\n }\n\n pub(crate) fn import_discovered_profiles(\n &self,\n input: ImportDiscoveredCliConfigInput,\n ) -> Result<ImportDiscoveredCliConfigResult, CliConfigError> {\n validate_supported_agent(&input.agent_id)?;\n if input.candidate_keys.is_empty() {\n return Err(CliConfigError::Validation(\n \"at least one discovered candidate must be selected\".into(),\n ));\n }\n if input.candidate_keys.len() > 64 {\n return Err(CliConfigError::Validation(\n \"too many discovered candidates were selected\".into(),\n ));\n }\n let requested = input.candidate_keys.into_iter().collect::<BTreeSet<_>>();\n let discovery = self.live.discover_current(&input.agent_id)?;\n let available = discovery\n .candidates\n .iter()\n .map(|candidate| candidate.candidate_key.clone())\n .collect::<BTreeSet<_>>();\n if let Some(missing) = requested.difference(&available).next() {\n return Err(CliConfigError::Validation(format!(\n \"discovered candidate is no longer available: {missing}\"\n )));\n }\n let mut existing_names = self\n .repository\n .list_profiles(&input.agent_id)?\n .into_iter()\n .map(|profile| profile.name.trim().to_lowercase())\n .collect::<BTreeSet<_>>();\n let mut imported = Vec::new();\n let mut skipped = Vec::new();\n for candidate in discovery\n .candidates\n .into_iter()\n .filter(|candidate| requested.contains(&candidate.candidate_key))\n {\n let normalized_name = candidate.suggested_name.trim().to_lowercase();\n if existing_names.contains(&normalized_name) {\n skipped.push(SkippedCliConfigDiscoveryCandidate {\n candidate_key: candidate.candidate_key,\n suggested_name: candidate.suggested_name,\n reason: \"name-conflict\".into(),\n });\n continue;\n }\n let profile = self.save_profile(SaveCliConfigProfileInput {\n id: None,\n agent_id: input.agent_id.clone(),\n name: candidate.suggested_name,\n payload: candidate.payload,\n source_preset_id: None,\n source_preset_version: None,\n credential: candidate.credential.as_deref().map(ToString::to_string),\n remove_credential: false,\n })?;\n existing_names.insert(normalized_name);\n imported.push(profile);\n }\n self.write_log(\n LogSeverity::Info,\n \"cli.config.discovery.import\",\n &input.agent_id,\n None,\n None,\n &format!(\n \"imported {} discovered CLI configurations and skipped {}\",\n imported.len(),\n skipped.len()\n ),\n );\n Ok(ImportDiscoveredCliConfigResult { imported, skipped })\n }\n\n pub(crate) fn apply_profile(\n &self,\n input: ApplyCliConfigProfileInput,\n ) -> Result<CliConfigApplyResult, CliConfigError> {\n validate_supported_agent(&input.agent_id)?;\n let operation_id = Uuid::new_v4().to_string();\n let result = self.apply_profile_inner(&input);\n let apply_result = match result {\n Ok((profile, outcome, backfilled_profile_id)) => apply_result(\n operation_id,\n &profile,\n outcome,\n if backfilled_profile_id.is_some() {\n Some(CliConfigDriftResolution::ImportCurrent)\n } else {\n input.drift_resolution.clone()\n },\n backfilled_profile_id,\n ),\n Err(error) => failed_apply_result(\n operation_id,\n &input,\n self.live.paths(&input.agent_id).unwrap_or_default(),\n &error,\n ),\n };\n self.write_apply_log(&apply_result);\n Ok(apply_result)\n }\n\n fn apply_profile_inner(\n &self,\n input: &ApplyCliConfigProfileInput,\n ) -> Result<(ProfileRecord, ProjectionOutcome, Option<String>), CliConfigError> {\n let apply_lock = self\n .apply_locks\n .get(&input.agent_id)\n .cloned()\n .ok_or(CliConfigError::Repository)?;\n let _apply_guard = apply_lock.lock().map_err(|_| CliConfigError::Repository)?;\n let profile = self\n .repository\n .get_profile(&input.agent_id, &input.profile_id)?;\n profile.payload.validate()?;\n let credential = self.credentials.load(&input.agent_id, &input.profile_id)?;\n if profile.payload.requires_credential() && credential.is_none() {\n return Err(CliConfigError::CredentialRequired);\n }\n let previous_state = self.repository.applied_state(&input.agent_id)?;\n let mut previous_profile = previous_state\n .as_ref()\n .map(|state| self.applied_profile_snapshot(&input.agent_id, state))\n .transpose()?\n .flatten();\n let inspection = self.live.inspect(\n &input.agent_id,\n previous_state.as_ref(),\n previous_profile.as_ref(),\n )?;\n if inspection.state == CliConfigDriftState::Malformed {\n return Err(CliConfigError::Parse {\n path: inspection\n .paths\n .first()\n .map(|path| path.display().to_string())\n .unwrap_or_else(|| \"configuration\".into()),\n message: \"existing configuration is malformed\".into(),\n });\n }\n let switching_exclusive_profile = input.agent_id != \"opencode\"\n && previous_profile\n .as_ref()\n .is_some_and(|previous| previous.id != profile.id);\n let backfilled_profile_id = if switching_exclusive_profile {\n let previous = previous_profile\n .as_ref()\n .ok_or(CliConfigError::Repository)?;\n let (updated, source_fingerprint) = self.backfill_profile(&input.agent_id, previous)?;\n let id = updated.id.clone();\n previous_profile = Some(updated);\n Some((id, source_fingerprint))\n } else {\n None\n };\n let expected_live_fingerprint = backfilled_profile_id\n .as_ref()\n .map(|(_, fingerprint)| fingerprint.clone())\n .unwrap_or(inspection.managed_fingerprint);\n let backfilled_profile_id = backfilled_profile_id.map(|(id, _)| id);\n\n let outcome = self.live.apply(\n &profile,\n previous_profile.as_ref(),\n credential.as_deref().map(|secret| secret.as_str()),\n input.confirm_auth_file_replacement,\n &expected_live_fingerprint,\n )?;\n let applied = AppliedStateRecord {\n agent_id: input.agent_id.clone(),\n profile_id: Some(profile.id.clone()),\n projection_fingerprint: outcome.projection_fingerprint.clone(),\n live_fingerprint: outcome.live_fingerprint.clone(),\n drift_state: CliConfigDriftState::Applied,\n applied_at: Utc::now().to_rfc3339(),\n applied_payload: Some(profile.payload.clone()),\n managed_keys: profile.managed_keys.clone(),\n };\n if let Err(error) = self.repository.save_applied_state(&applied) {\n let live_restored = self.live.restore(&outcome).is_ok();\n let state_restored = if let Some(previous) = &previous_state {\n self.repository.save_applied_state(previous).is_ok()\n } else {\n self.repository.clear_applied_state(&input.agent_id).is_ok()\n };\n if !live_restored || !state_restored {\n return Err(CliConfigError::RollbackIncomplete);\n }\n return Err(error);\n }\n Ok((profile, outcome, backfilled_profile_id))\n }\n\n fn backfill_profile(\n &self,\n agent_id: &str,\n previous: &ProfileRecord,\n ) -> Result<(ProfileRecord, String), CliConfigError> {\n let imported = self.live.import_current(agent_id)?;\n let source_fingerprint = imported.source_fingerprint.clone();\n imported.payload.validate()?;\n let mut updated = previous.clone();\n updated.payload = imported.payload;\n updated.managed_keys = previous\n .managed_keys\n .iter()\n .cloned()\n .chain(updated.payload.managed_keys())\n .collect::<BTreeSet<_>>()\n .into_iter()\n .collect();\n updated.updated_at = Utc::now().to_rfc3339();\n let previous_secret = self.credentials.load(agent_id, &updated.id)?;\n let incoming_secret = imported.credential.as_deref().map(String::as_str);\n match incoming_secret {\n Some(secret) => self.credentials.store(agent_id, &updated.id, secret)?,\n None if previous_secret.is_some() => self.credentials.delete(agent_id, &updated.id)?,\n None => {}\n }\n if let Err(error) = self.repository.save_profile(&updated) {\n if self\n .restore_credential(\n agent_id,\n &updated.id,\n previous_secret.as_deref().map(String::as_str),\n )\n .is_err()\n {\n return Err(CliConfigError::RollbackIncomplete);\n }\n return Err(error);\n }\n self.write_log(\n LogSeverity::Info,\n \"cli.config.profile.backfill\",\n agent_id,\n Some(&updated.id),\n None,\n \"backfilled current live configuration into the leaving profile\",\n );\n Ok((updated, source_fingerprint))\n }\n\n fn profile_view(\n &self,\n record: ProfileRecord,\n status: &CliConfigStatus,\n ) -> Result<CliConfigProfile, CliConfigError> {\n let credential_configured = self\n .credentials\n .load(&record.agent_id, &record.id)?\n .is_some();\n let validation_state = if record.payload.validate().is_err() {\n CliConfigValidationState::Invalid\n } else if record.payload.requires_credential() && !credential_configured {\n CliConfigValidationState::NeedsCredential\n } else {\n CliConfigValidationState::Valid\n };\n let applied_state = if status.applied_profile_id.as_deref() == Some(record.id.as_str()) {\n if status.drift_state == CliConfigDriftState::Applied {\n CliConfigAppliedState::Applied\n } else {\n CliConfigAppliedState::Drifted\n }\n } else {\n CliConfigAppliedState::Saved\n };\n Ok(CliConfigProfile {\n id: record.id,\n agent_id: record.agent_id,\n name: record.name,\n payload_version: record.payload_version,\n payload: record.payload,\n source_preset_id: record.source_preset_id,\n source_preset_version: record.source_preset_version,\n credential_configured,\n validation_state,\n applied_state,\n created_at: record.created_at,\n updated_at: record.updated_at,\n })\n }\n\n fn applied_profile_snapshot(\n &self,\n agent_id: &str,\n state: &AppliedStateRecord,\n ) -> Result<Option<ProfileRecord>, CliConfigError> {\n let Some(profile_id) = state.profile_id.as_deref() else {\n return Ok(None);\n };\n let mut profile = self.repository.get_profile(agent_id, profile_id)?;\n if let Some(payload) = &state.applied_payload {\n profile.payload = payload.clone();\n }\n if !state.managed_keys.is_empty() {\n profile.managed_keys = state.managed_keys.clone();\n }\n Ok(Some(profile))\n }\n\n fn next_profile_id(&self, name: &str) -> Result<String, CliConfigError> {\n let base = slug(name);\n if !self.repository.profile_id_exists(&base)? {\n return Ok(base);\n }\n for suffix in 2..10_000 {\n let candidate = format!(\"{base}-{suffix}\");\n if !self.repository.profile_id_exists(&candidate)? {\n return Ok(candidate);\n }\n }\n Err(CliConfigError::Repository)\n }\n\n fn restore_credential(\n &self,\n agent_id: &str,\n profile_id: &str,\n previous: Option<&str>,\n ) -> Result<(), CliConfigError> {\n match previous {\n Some(secret) => self.credentials.store(agent_id, profile_id, secret),\n None => self.credentials.delete(agent_id, profile_id),\n }\n }\n\n fn log_result<T>(\n &self,\n category: &str,\n agent_id: &str,\n profile_id: Option<&str>,\n result: &Result<T, CliConfigError>,\n ) {\n self.write_log(\n if result.is_ok() {\n LogSeverity::Info\n } else {\n LogSeverity::Error\n },\n category,\n agent_id,\n profile_id,\n None,\n if result.is_ok() {\n \"CLI configuration operation succeeded\"\n } else {\n \"CLI configuration operation failed\"\n },\n );\n }\n\n fn write_log(\n &self,\n severity: LogSeverity,\n category: &str,\n agent_id: &str,\n profile_id: Option<&str>,\n operation_id: Option<&str>,\n message: &str,\n ) {\n let mut context = BTreeMap::from([(\"agentId\".into(), agent_id.to_string())]);\n if let Some(profile_id) = profile_id {\n context.insert(\"profileId\".into(), profile_id.to_string());\n }\n if let Some(operation_id) = operation_id {\n context.insert(\"operationId\".into(), operation_id.to_string());\n }\n context.insert(\n \"status\".into(),\n if severity == LogSeverity::Error {\n \"failed\"\n } else {\n \"succeeded\"\n }\n .into(),\n );\n let _ = self.logging.write_diagnostic(DiagnosticLog {\n severity,\n category: category.into(),\n message: message.into(),\n context,\n });\n }\n\n fn write_apply_log(&self, result: &CliConfigApplyResult) {\n let mut context = BTreeMap::from([\n (\"agentId\".into(), result.agent_id.clone()),\n (\"profileId\".into(), result.profile_id.clone()),\n (\"operationId\".into(), result.operation_id.clone()),\n (\"status\".into(), result.status.clone()),\n (\"restored\".into(), result.restored.to_string()),\n ]);\n let target_files = result\n .affected_paths\n .iter()\n .filter_map(|path| std::path::Path::new(path).file_name())\n .map(|name| name.to_string_lossy())\n .collect::<Vec<_>>()\n .join(\",\");\n if !target_files.is_empty() {\n context.insert(\"targetFiles\".into(), target_files);\n }\n let succeeded = result.status == \"succeeded\";\n let _ = self.logging.write_diagnostic(DiagnosticLog {\n severity: if succeeded {\n LogSeverity::Info\n } else {\n LogSeverity::Error\n },\n category: \"cli.config.profile.apply\".into(),\n message: if succeeded {\n \"applied CLI configuration profile\"\n } else {\n \"CLI configuration profile application failed\"\n }\n .into(),\n context,\n });\n }\n}\n\nfn startup_sync_result(\n agent_id: &str,\n state: CliConfigStartupSyncState,\n) -> CliConfigStartupSyncResult {\n CliConfigStartupSyncResult {\n agent_id: agent_id.to_string(),\n state,\n imported: 0,\n updated: 0,\n skipped: 0,\n warnings: Vec::new(),\n synchronized_at: None,\n simulated: false,\n }\n}\n\nfn startup_sync_warning(error: &CliConfigError) -> String {\n match error {\n CliConfigError::Parse { .. } => {\n \"The local CLI configuration could not be parsed; startup synchronization was skipped.\"\n }\n CliConfigError::Filesystem { .. } => {\n \"The local CLI configuration could not be read; startup synchronization was skipped.\"\n }\n CliConfigError::Credential | CliConfigError::CredentialRequired => {\n \"The local CLI credential could not be synchronized safely.\"\n }\n CliConfigError::RollbackIncomplete => {\n \"Startup synchronization could not fully restore an interrupted profile update.\"\n }\n _ => \"Startup synchronization could not be completed.\",\n }\n .to_string()\n}\n\nfn apply_result(\n operation_id: String,\n profile: &ProfileRecord,\n outcome: ProjectionOutcome,\n drift_resolution: Option<super::domain::CliConfigDriftResolution>,\n backfilled_profile_id: Option<String>,\n) -> CliConfigApplyResult {\n CliConfigApplyResult {\n operation_id,\n status: \"succeeded\".into(),\n agent_id: profile.agent_id.clone(),\n profile_id: profile.id.clone(),\n affected_paths: outcome\n .paths\n .into_iter()\n .map(|path| path.display().to_string())\n .collect(),\n drift_resolution,\n backfilled_profile_id,\n warnings: outcome.warnings,\n restart_required: true,\n simulated: false,\n restored: outcome.restored,\n error: None,\n }\n}\n\nfn failed_apply_result(\n operation_id: String,\n input: &ApplyCliConfigProfileInput,\n paths: Vec<std::path::PathBuf>,\n error: &CliConfigError,\n) -> CliConfigApplyResult {\n CliConfigApplyResult {\n operation_id,\n status: \"failed\".into(),\n agent_id: input.agent_id.clone(),\n profile_id: input.profile_id.clone(),\n affected_paths: paths\n .into_iter()\n .map(|path| path.display().to_string())\n .collect(),\n drift_resolution: input.drift_resolution.clone(),\n backfilled_profile_id: None,\n warnings: Vec::new(),\n restart_required: false,\n simulated: false,\n restored: !matches!(error, CliConfigError::RollbackIncomplete),\n error: Some(error.to_string()),\n }\n}\n\nfn slug(value: &str) -> String {\n let mut output = String::new();\n let mut separator = false;\n for character in value.trim().chars() {\n if character.is_ascii_alphanumeric() {\n output.push(character.to_ascii_lowercase());\n separator = false;\n } else if !separator && !output.is_empty() {\n output.push('-');\n separator = true;\n }\n }\n while output.ends_with('-') {\n output.pop();\n }\n if output.is_empty() {\n \"profile\".into()\n } else {\n output\n }\n}\n\nfn unique_copy_name(source: &str, existing: &[String]) -> String {\n let base = format!(\"{source} Copy\");\n if !existing.contains(&base) {\n return base;\n }\n for suffix in 2..10_000 {\n let candidate = format!(\"{base} {suffix}\");\n if !existing.contains(&candidate) {\n return candidate;\n }\n }\n format!(\"{base} {}\", Uuid::new_v4())\n}\n\n#[cfg(test)]\nmod tests {\n use super::*;\n use crate::contexts::operations::api::OperationsError;\n use crate::contexts::tooling::cli_config::application::{ImportedLiveConfig, LiveInspection};\n use crate::contexts::tooling::cli_config::domain::{\n ApplyCliConfigProfileInput, ClaudeAuthMode, CliConfigDriftResolution, CliConfigPayload,\n ImportDiscoveredCliConfigInput, SaveCliConfigProfileInput,\n };\n use crate::contexts::tooling::cli_config::infrastructure::NativeCliGlobalConfigAdapter;\n use std::path::PathBuf;\n use std::sync::atomic::{AtomicUsize, Ordering};\n use std::thread;\n use std::time::Duration;\n\n #[derive(Default)]\n struct MemoryRepository {\n profiles: Mutex<Vec<ProfileRecord>>,\n applied: Mutex<BTreeMap<String, AppliedStateRecord>>,\n fail_next_save: AtomicUsize,\n }\n\n impl CliConfigRepository for MemoryRepository {\n fn list_profiles(&self, agent_id: &str) -> Result<Vec<ProfileRecord>, CliConfigError> {\n Ok(self\n .profiles\n .lock()\n .map_err(|_| CliConfigError::Repository)?\n .iter()\n .filter(|profile| profile.agent_id == agent_id)\n .cloned()\n .collect())\n }\n\n fn get_profile(\n &self,\n agent_id: &str,\n profile_id: &str,\n ) -> Result<ProfileRecord, CliConfigError> {\n self.profiles\n .lock()\n .map_err(|_| CliConfigError::Repository)?\n .iter()\n .find(|profile| profile.agent_id == agent_id && profile.id == profile_id)\n .cloned()\n .ok_or(CliConfigError::NotFound)\n }\n\n fn profile_id_exists(&self, profile_id: &str) -> Result<bool, CliConfigError> {\n Ok(self\n .profiles\n .lock()\n .map_err(|_| CliConfigError::Repository)?\n .iter()\n .any(|profile| profile.id == profile_id))\n }\n\n fn save_profile(&self, profile: &ProfileRecord) -> Result<(), CliConfigError> {\n if self.fail_next_save.swap(0, Ordering::SeqCst) > 0 {\n return Err(CliConfigError::Repository);\n }\n let mut profiles = self\n .profiles\n .lock()\n .map_err(|_| CliConfigError::Repository)?;\n profiles.retain(|candidate| candidate.id != profile.id);\n profiles.push(profile.clone());\n Ok(())\n }\n\n fn delete_profile(&self, agent_id: &str, profile_id: &str) -> Result<(), CliConfigError> {\n let mut profiles = self\n .profiles\n .lock()\n .map_err(|_| CliConfigError::Repository)?;\n let before = profiles.len();\n profiles.retain(|profile| profile.agent_id != agent_id || profile.id != profile_id);\n if profiles.len() == before {\n return Err(CliConfigError::NotFound);\n }\n Ok(())\n }\n\n fn applied_state(\n &self,\n agent_id: &str,\n ) -> Result<Option<AppliedStateRecord>, CliConfigError> {\n Ok(self\n .applied\n .lock()\n .map_err(|_| CliConfigError::Repository)?\n .get(agent_id)\n .cloned())\n }\n\n fn save_applied_state(&self, state: &AppliedStateRecord) -> Result<(), CliConfigError> {\n self.applied\n .lock()\n .map_err(|_| CliConfigError::Repository)?\n .insert(state.agent_id.clone(), state.clone());\n Ok(())\n }\n\n fn clear_applied_state(&self, agent_id: &str) -> Result<(), CliConfigError> {\n self.applied\n .lock()\n .map_err(|_| CliConfigError::Repository)?\n .remove(agent_id);\n Ok(())\n }\n }\n\n #[derive(Default)]\n struct MemoryCredentials {\n values: Mutex<BTreeMap<(String, String), String>>,\n }\n\n impl CliConfigCredentialPort for MemoryCredentials {\n fn load(\n &self,\n agent_id: &str,\n profile_id: &str,\n ) -> Result<Option<zeroize::Zeroizing<String>>, CliConfigError> {\n Ok(self\n .values\n .lock()\n .map_err(|_| CliConfigError::Credential)?\n .get(&(agent_id.to_string(), profile_id.to_string()))\n .cloned()\n .map(zeroize::Zeroizing::new))\n }\n\n fn store(\n &self,\n agent_id: &str,\n profile_id: &str,\n secret: &str,\n ) -> Result<(), CliConfigError> {\n self.values\n .lock()\n .map_err(|_| CliConfigError::Credential)?\n .insert(\n (agent_id.to_string(), profile_id.to_string()),\n secret.to_string(),\n );\n Ok(())\n }\n\n fn delete(&self, agent_id: &str, profile_id: &str) -> Result<(), CliConfigError> {\n self.values\n .lock()\n .map_err(|_| CliConfigError::Credential)?\n .remove(&(agent_id.to_string(), profile_id.to_string()));\n Ok(())\n }\n }\n\n #[derive(Default)]\n struct SerialProbeLiveConfig {\n active: AtomicUsize,\n max_active: AtomicUsize,\n }\n\n impl CliGlobalConfigPort for SerialProbeLiveConfig {\n fn paths(&self, _agent_id: &str) -> Result<Vec<PathBuf>, CliConfigError> {\n Ok(vec![PathBuf::from(\"safe-config\")])\n }\n\n fn inspect(\n &self,\n agent_id: &str,\n _applied: Option<&AppliedStateRecord>,\n _applied_profile: Option<&ProfileRecord>,\n ) -> Result<LiveInspection, CliConfigError> {\n Ok(LiveInspection {\n paths: self.paths(agent_id)?,\n state: CliConfigDriftState::Detached,\n managed_fingerprint: \"before\".into(),\n })\n }\n\n fn import_current(&self, _agent_id: &str) -> Result<ImportedLiveConfig, CliConfigError> {\n Err(CliConfigError::NotFound)\n }\n\n fn apply(\n &self,\n _profile: &ProfileRecord,\n _previous: Option<&ProfileRecord>,\n _credential: Option<&str>,\n _confirm_auth_file_replacement: bool,\n _expected_live_fingerprint: &str,\n ) -> Result<ProjectionOutcome, CliConfigError> {\n let active = self.active.fetch_add(1, Ordering::SeqCst) + 1;\n self.max_active.fetch_max(active, Ordering::SeqCst);\n thread::sleep(Duration::from_millis(30));\n self.active.fetch_sub(1, Ordering::SeqCst);\n Ok(ProjectionOutcome {\n paths: vec![PathBuf::from(\"safe-config\")],\n projection_fingerprint: \"projection\".into(),\n live_fingerprint: \"live\".into(),\n warnings: Vec::new(),\n restored: true,\n backups: Vec::new(),\n })\n }\n\n fn restore(&self, _outcome: &ProjectionOutcome) -> Result<(), CliConfigError> {\n Ok(())\n }\n }\n\n #[derive(Default)]\n struct NoopLog;\n\n impl DiagnosticLogPort for NoopLog {\n fn write_diagnostic(&self, _log: DiagnosticLog) -> Result<(), OperationsError> {\n Ok(())\n }\n }\n\n #[derive(Default)]\n struct CapturingLog {\n entries: Mutex<Vec<DiagnosticLog>>,\n }\n\n impl DiagnosticLogPort for CapturingLog {\n fn write_diagnostic(&self, log: DiagnosticLog) -> Result<(), OperationsError> {\n self.entries.lock().expect(\"log entries\").push(log);\n Ok(())\n }\n }\n\n #[derive(Default)]\n struct RollbackFailLiveConfig;\n\n impl CliGlobalConfigPort for RollbackFailLiveConfig {\n fn paths(&self, _agent_id: &str) -> Result<Vec<PathBuf>, CliConfigError> {\n Ok(vec![PathBuf::from(\"safe-config\")])\n }\n\n fn inspect(\n &self,\n agent_id: &str,\n _applied: Option<&AppliedStateRecord>,\n _applied_profile: Option<&ProfileRecord>,\n ) -> Result<LiveInspection, CliConfigError> {\n Ok(LiveInspection {\n paths: self.paths(agent_id)?,\n state: CliConfigDriftState::Detached,\n managed_fingerprint: \"before\".into(),\n })\n }\n\n fn import_current(&self, _agent_id: &str) -> Result<ImportedLiveConfig, CliConfigError> {\n Err(CliConfigError::NotFound)\n }\n\n fn apply(\n &self,\n _profile: &ProfileRecord,\n _previous: Option<&ProfileRecord>,\n _credential: Option<&str>,\n _confirm_auth_file_replacement: bool,\n _expected_live_fingerprint: &str,\n ) -> Result<ProjectionOutcome, CliConfigError> {\n Err(CliConfigError::RollbackIncomplete)\n }\n\n fn restore(&self, _outcome: &ProjectionOutcome) -> Result<(), CliConfigError> {\n Err(CliConfigError::RollbackIncomplete)\n }\n }\n\n #[derive(Default)]\n struct DriftImportLiveConfig;\n\n impl CliGlobalConfigPort for DriftImportLiveConfig {\n fn paths(&self, _agent_id: &str) -> Result<Vec<PathBuf>, CliConfigError> {\n Ok(vec![PathBuf::from(\"safe-config\")])\n }\n\n fn inspect(\n &self,\n agent_id: &str,\n _applied: Option<&AppliedStateRecord>,\n _applied_profile: Option<&ProfileRecord>,\n ) -> Result<LiveInspection, CliConfigError> {\n Ok(LiveInspection {\n paths: self.paths(agent_id)?,\n state: CliConfigDriftState::Drifted,\n managed_fingerprint: \"drifted\".into(),\n })\n }\n\n fn import_current(&self, _agent_id: &str) -> Result<ImportedLiveConfig, CliConfigError> {\n Ok(ImportedLiveConfig {\n payload: CliConfigPayload::ClaudeCode {\n base_url: \"https://drifted.example.com\".into(),\n auth_mode: ClaudeAuthMode::AuthToken,\n model: \"drifted-model\".into(),\n haiku_model: \"drifted-model\".into(),\n sonnet_model: \"drifted-model\".into(),\n opus_model: \"drifted-model\".into(),\n advanced_env: BTreeMap::new(),\n },\n credential: Some(zeroize::Zeroizing::new(\"new-secret\".into())),\n source_fingerprint: \"file:drifted\".into(),\n })\n }\n\n fn apply(\n &self,\n _profile: &ProfileRecord,\n _previous: Option<&ProfileRecord>,\n _credential: Option<&str>,\n _confirm_auth_file_replacement: bool,\n _expected_live_fingerprint: &str,\n ) -> Result<ProjectionOutcome, CliConfigError> {\n Err(CliConfigError::Repository)\n }\n\n fn restore(&self, _outcome: &ProjectionOutcome) -> Result<(), CliConfigError> {\n Ok(())\n }\n }\n\n fn claude_without_credential(name: &str) -> SaveCliConfigProfileInput {\n SaveCliConfigProfileInput {\n id: None,\n agent_id: \"claude-code\".into(),\n name: name.into(),\n payload: CliConfigPayload::ClaudeCode {\n base_url: \"https://api.anthropic.com\".into(),\n auth_mode: ClaudeAuthMode::None,\n model: \"claude-sonnet-4-6\".into(),\n haiku_model: \"claude-haiku-4-5\".into(),\n sonnet_model: \"claude-sonnet-4-6\".into(),\n opus_model: \"claude-opus-4-6\".into(),\n advanced_env: BTreeMap::new(),\n },\n source_preset_id: None,\n source_preset_version: None,\n credential: None,\n remove_credential: false,\n }\n }\n\n #[test]\n fn profile_ids_are_stable_safe_slugs() {\n assert_eq!(slug(\" OpenRouter Primary \"), \"openrouter-primary\");\n assert_eq!(slug(\"智谱 GLM\"), \"glm\");\n assert_eq!(slug(\"智谱\"), \"profile\");\n }\n\n #[test]\n fn duplicate_names_do_not_collide() {\n assert_eq!(unique_copy_name(\"DeepSeek\", &[]), \"DeepSeek Copy\");\n assert_eq!(\n unique_copy_name(\"DeepSeek\", &[\"DeepSeek Copy\".into()]),\n \"DeepSeek Copy 2\"\n );\n }\n\n #[test]\n fn discovered_import_redacts_credentials_and_skips_case_insensitive_name_conflicts() {\n let directory = tempfile::tempdir().expect(\"temporary home\");\n let path = directory.path().join(\".claude\").join(\"settings.json\");\n std::fs::create_dir_all(path.parent().expect(\"parent\")).expect(\"directory\");\n std::fs::write(\n &path,\n r#\"{\"env\":{\"ANTHROPIC_AUTH_TOKEN\":\"discovery-secret\",\"ANTHROPIC_MODEL\":\"claude-sonnet-4-6\"}}\"#,\n )\n .expect(\"fixture\");\n let repository = Arc::new(MemoryRepository::default());\n let credentials = Arc::new(MemoryCredentials::default());\n let api = CliConfigApi::new(\n repository,\n credentials.clone(),\n Arc::new(NativeCliGlobalConfigAdapter::with_home(\n directory.path().to_path_buf(),\n )),\n Arc::new(NoopLog),\n );\n\n let discovery = api.discover_profiles(\"claude-code\").expect(\"discovery\");\n assert_eq!(discovery.candidates.len(), 1);\n assert!(discovery.candidates[0].credential_detected);\n let serialized = serde_json::to_string(&discovery).expect(\"serialize discovery\");\n assert!(!serialized.contains(\"discovery-secret\"));\n\n let first = api\n .import_discovered_profiles(ImportDiscoveredCliConfigInput {\n agent_id: \"claude-code\".into(),\n candidate_keys: vec![\"current\".into()],\n })\n .expect(\"first import\");\n assert_eq!(first.imported.len(), 1);\n assert!(credentials\n .load(\"claude-code\", &first.imported[0].id)\n .expect(\"credential\")\n .is_some());\n\n let second = api\n .import_discovered_profiles(ImportDiscoveredCliConfigInput {\n agent_id: \"claude-code\".into(),\n candidate_keys: vec![\"current\".into()],\n })\n .expect(\"conflict is reported\");\n assert!(second.imported.is_empty());\n assert_eq!(second.skipped.len(), 1);\n assert_eq!(second.skipped[0].reason, \"name-conflict\");\n\n std::fs::write(&path, r#\"{\"env\":{\"ANTHROPIC_AUTH_TOKEN\":\"must-not-leak\"}\"#)\n .expect(\"malformed fixture\");\n let malformed = api\n .discover_profiles(\"claude-code\")\n .expect(\"parse state is data\");\n assert_eq!(malformed.state, CliConfigDiscoveryState::ParseError);\n assert!(malformed.candidates.is_empty());\n assert!(!serde_json::to_string(&malformed)\n .expect(\"serialize malformed result\")\n .contains(\"must-not-leak\"));\n }\n\n #[test]\n fn command_errors_do_not_render_secret_values() {\n let rendered = CliConfigError::Credential.to_string();\n assert!(!rendered.contains(\"sk-secret\"));\n assert_eq!(rendered, \"secure credential operation failed\");\n }\n\n #[test]\n fn concurrent_applies_for_one_agent_are_serialized_end_to_end() {\n let repository = Arc::new(MemoryRepository::default());\n let live = Arc::new(SerialProbeLiveConfig::default());\n let api = CliConfigApi::new(\n repository,\n Arc::new(MemoryCredentials::default()),\n live.clone(),\n Arc::new(NoopLog),\n );\n let first = api\n .save_profile(claude_without_credential(\"First\"))\n .expect(\"first profile\");\n let second = api\n .save_profile(claude_without_credential(\"Second\"))\n .expect(\"second profile\");\n\n let first_api = api.clone();\n let first_handle = thread::spawn(move || {\n first_api.apply_profile(ApplyCliConfigProfileInput {\n agent_id: \"claude-code\".into(),\n profile_id: first.id,\n drift_resolution: None,\n confirm_auth_file_replacement: false,\n })\n });\n let second_api = api.clone();\n let second_handle = thread::spawn(move || {\n second_api.apply_profile(ApplyCliConfigProfileInput {\n agent_id: \"claude-code\".into(),\n profile_id: second.id,\n drift_resolution: None,\n confirm_auth_file_replacement: false,\n })\n });\n\n first_handle\n .join()\n .expect(\"first thread\")\n .expect(\"first apply\");\n second_handle\n .join()\n .expect(\"second thread\")\n .expect(\"second apply\");\n assert_eq!(live.max_active.load(Ordering::SeqCst), 1);\n }\n\n #[test]\n fn failed_profile_update_restores_the_previous_credential() {\n let repository = Arc::new(MemoryRepository::default());\n let credentials = Arc::new(MemoryCredentials::default());\n let api = CliConfigApi::new(\n repository.clone(),\n credentials.clone(),\n Arc::new(SerialProbeLiveConfig::default()),\n Arc::new(NoopLog),\n );\n let mut create = claude_without_credential(\"Credential profile\");\n if let CliConfigPayload::ClaudeCode { auth_mode, .. } = &mut create.payload {\n *auth_mode = ClaudeAuthMode::AuthToken;\n }\n create.credential = Some(\"old-secret\".into());\n let saved = api.save_profile(create.clone()).expect(\"initial profile\");\n\n repository.fail_next_save.store(1, Ordering::SeqCst);\n create.id = Some(saved.id.clone());\n create.credential = Some(\"new-secret\".into());\n assert!(matches!(\n api.save_profile(create),\n Err(CliConfigError::Repository)\n ));\n let restored = credentials\n .load(\"claude-code\", &saved.id)\n .expect(\"credential load\")\n .expect(\"restored credential\");\n assert_eq!(restored.as_str(), \"old-secret\");\n }\n\n #[test]\n fn applied_snapshot_removes_keys_owned_before_profile_edit() {\n let directory = tempfile::tempdir().expect(\"temporary home\");\n let repository = Arc::new(MemoryRepository::default());\n let api = CliConfigApi::new(\n repository,\n Arc::new(MemoryCredentials::default()),\n Arc::new(NativeCliGlobalConfigAdapter::with_home(\n directory.path().to_path_buf(),\n )),\n Arc::new(NoopLog),\n );\n let mut first_input = claude_without_credential(\"First\");\n if let CliConfigPayload::ClaudeCode { advanced_env, .. } = &mut first_input.payload {\n advanced_env.insert(\"VANEHUB_OLD_MANAGED\".into(), \"old\".into());\n }\n let first = api\n .save_profile(first_input.clone())\n .expect(\"first profile\");\n let first_apply = api\n .apply_profile(ApplyCliConfigProfileInput {\n agent_id: \"claude-code\".into(),\n profile_id: first.id.clone(),\n drift_resolution: None,\n confirm_auth_file_replacement: false,\n })\n .expect(\"first apply\");\n assert_eq!(first_apply.status, \"succeeded\");\n\n first_input.id = Some(first.id);\n if let CliConfigPayload::ClaudeCode { advanced_env, .. } = &mut first_input.payload {\n advanced_env.clear();\n }\n api.save_profile(first_input).expect(\"edit applied profile\");\n let second = api\n .save_profile(claude_without_credential(\"Second\"))\n .expect(\"second profile\");\n let second_apply = api\n .apply_profile(ApplyCliConfigProfileInput {\n agent_id: \"claude-code\".into(),\n profile_id: second.id,\n drift_resolution: None,\n confirm_auth_file_replacement: false,\n })\n .expect(\"second apply\");\n assert_eq!(second_apply.status, \"succeeded\");\n\n let settings =\n std::fs::read_to_string(directory.path().join(\".claude\").join(\"settings.json\"))\n .expect(\"settings\");\n assert!(!settings.contains(\"VANEHUB_OLD_MANAGED\"));\n }\n\n #[test]\n fn apply_failure_returns_restoration_status_and_redacted_log() {\n let repository = Arc::new(MemoryRepository::default());\n let logging = Arc::new(CapturingLog::default());\n let api = CliConfigApi::new(\n repository,\n Arc::new(MemoryCredentials::default()),\n Arc::new(RollbackFailLiveConfig),\n logging.clone(),\n );\n let profile = api\n .save_profile(claude_without_credential(\"Failure\"))\n .expect(\"profile\");\n let result = api\n .apply_profile(ApplyCliConfigProfileInput {\n agent_id: \"claude-code\".into(),\n profile_id: profile.id,\n drift_resolution: None,\n confirm_auth_file_replacement: false,\n })\n .expect(\"structured failure\");\n\n assert_eq!(result.status, \"failed\");\n assert!(!result.restored);\n assert_eq!(\n result.error.as_deref(),\n Some(\"configuration rollback was incomplete\")\n );\n let entries = logging.entries.lock().expect(\"logs\");\n let apply_log = entries\n .iter()\n .find(|entry| entry.category == \"cli.config.profile.apply\")\n .expect(\"apply log\");\n assert_eq!(\n apply_log.context.get(\"status\").map(String::as_str),\n Some(\"failed\")\n );\n assert_eq!(\n apply_log.context.get(\"restored\").map(String::as_str),\n Some(\"false\")\n );\n assert!(!format!(\"{apply_log:?}\").contains(\"secret\"));\n }\n\n #[test]\n fn drift_import_restores_previous_credential_when_profile_save_fails() {\n let repository = Arc::new(MemoryRepository::default());\n let credentials = Arc::new(MemoryCredentials::default());\n let api = CliConfigApi::new(\n repository.clone(),\n credentials.clone(),\n Arc::new(DriftImportLiveConfig),\n Arc::new(NoopLog),\n );\n let mut previous_input = claude_without_credential(\"Previous\");\n if let CliConfigPayload::ClaudeCode { auth_mode, .. } = &mut previous_input.payload {\n *auth_mode = ClaudeAuthMode::AuthToken;\n }\n previous_input.credential = Some(\"old-secret\".into());\n let previous = api.save_profile(previous_input).expect(\"previous profile\");\n let target = api\n .save_profile(claude_without_credential(\"Target\"))\n .expect(\"target profile\");\n repository\n .save_applied_state(&AppliedStateRecord {\n agent_id: \"claude-code\".into(),\n profile_id: Some(previous.id.clone()),\n projection_fingerprint: \"projection\".into(),\n live_fingerprint: \"live\".into(),\n drift_state: CliConfigDriftState::Applied,\n applied_at: \"2026-01-01T00:00:00Z\".into(),\n applied_payload: Some(previous.payload.clone()),\n managed_keys: previous.payload.managed_keys(),\n })\n .expect(\"applied state\");\n repository.fail_next_save.store(1, Ordering::SeqCst);\n\n let result = api\n .apply_profile(ApplyCliConfigProfileInput {\n agent_id: \"claude-code\".into(),\n profile_id: target.id,\n drift_resolution: Some(CliConfigDriftResolution::ImportCurrent),\n confirm_auth_file_replacement: false,\n })\n .expect(\"structured failure\");\n assert_eq!(result.status, \"failed\");\n assert!(result.restored);\n let restored = credentials\n .load(\"claude-code\", &previous.id)\n .expect(\"credential load\")\n .expect(\"restored credential\");\n assert_eq!(restored.as_str(), \"old-secret\");\n }\n\n #[test]\n fn startup_sync_bootstraps_an_exclusive_profile_once_without_rewriting_live() {\n let directory = tempfile::tempdir().expect(\"temporary home\");\n let settings_path = directory.path().join(\".claude\").join(\"settings.json\");\n std::fs::create_dir_all(settings_path.parent().expect(\"settings parent\"))\n .expect(\"create settings directory\");\n let live_bytes = br#\"{\"env\":{\"ANTHROPIC_BASE_URL\":\"https://external.example.com\",\"ANTHROPIC_MODEL\":\"claude-external\"}}\"#;\n std::fs::write(&settings_path, live_bytes).expect(\"write live settings\");\n let repository = Arc::new(MemoryRepository::default());\n let api = CliConfigApi::new(\n repository.clone(),\n Arc::new(MemoryCredentials::default()),\n Arc::new(NativeCliGlobalConfigAdapter::with_home(\n directory.path().to_path_buf(),\n )),\n Arc::new(NoopLog),\n );\n\n let first = api.synchronize_startup();\n let claude = first\n .iter()\n .find(|result| result.agent_id == \"claude-code\")\n .expect(\"claude startup result\");\n assert_eq!(claude.state, CliConfigStartupSyncState::Imported);\n assert_eq!(claude.imported, 1);\n let profiles = repository\n .list_profiles(\"claude-code\")\n .expect(\"list imported profiles\");\n assert_eq!(profiles.len(), 1);\n assert_eq!(profiles[0].id, \"claude-code-default\");\n assert_eq!(profiles[0].name, \"default\");\n assert_eq!(\n repository\n .applied_state(\"claude-code\")\n .expect(\"applied state\")\n .and_then(|state| state.profile_id),\n Some(\"claude-code-default\".into())\n );\n assert_eq!(\n std::fs::read(&settings_path).expect(\"read live\"),\n live_bytes\n );\n\n let second = api.synchronize_startup();\n assert_eq!(\n second\n .iter()\n .find(|result| result.agent_id == \"claude-code\")\n .expect(\"second claude result\")\n .state,\n CliConfigStartupSyncState::Skipped\n );\n assert_eq!(\n repository\n .list_profiles(\"claude-code\")\n .expect(\"list profiles after second startup\")\n .len(),\n 1\n );\n }\n\n #[test]\n fn startup_sync_upserts_opencode_by_provider_id_without_deleting_missing_profiles() {\n let directory = tempfile::tempdir().expect(\"temporary home\");\n let config_path = directory\n .path()\n .join(\".config\")\n .join(\"opencode\")\n .join(\"opencode.json\");\n std::fs::create_dir_all(config_path.parent().expect(\"config parent\"))\n .expect(\"create config directory\");\n std::fs::write(\n &config_path,\n r#\"{\"model\":\"deepseek/deepseek-chat\",\"provider\":{\"deepseek\":{\"name\":\"DeepSeek\",\"npm\":\"@ai-sdk/openai-compatible\",\"options\":{\"baseURL\":\"https://api.deepseek.com/v1\",\"apiKey\":\"startup-secret\"},\"models\":{\"deepseek-chat\":{\"name\":\"DeepSeek Chat\"}}}}}\"#,\n )\n .expect(\"write OpenCode config\");\n let repository = Arc::new(MemoryRepository::default());\n let credentials = Arc::new(MemoryCredentials::default());\n let api = CliConfigApi::new(\n repository.clone(),\n credentials.clone(),\n Arc::new(NativeCliGlobalConfigAdapter::with_home(\n directory.path().to_path_buf(),\n )),\n Arc::new(NoopLog),\n );\n\n let first = api.synchronize_startup();\n assert_eq!(\n first\n .iter()\n .find(|result| result.agent_id == \"opencode\")\n .expect(\"OpenCode startup result\")\n .imported,\n 1\n );\n let imported = repository\n .list_profiles(\"opencode\")\n .expect(\"OpenCode profiles\")\n .into_iter()\n .next()\n .expect(\"imported profile\");\n assert!(credentials\n .load(\"opencode\", &imported.id)\n .expect(\"credential lookup\")\n .is_some());\n\n std::fs::write(\n &config_path,\n r#\"{\"model\":\"deepseek/deepseek-reasoner\",\"provider\":{\"deepseek\":{\"name\":\"DeepSeek Updated\",\"npm\":\"@ai-sdk/openai-compatible\",\"options\":{\"baseURL\":\"https://api.deepseek.com/v2\",\"apiKey\":\"updated-secret\"},\"models\":{\"deepseek-reasoner\":{\"name\":\"DeepSeek Reasoner\"}}}}}\"#,\n )\n .expect(\"update OpenCode config\");\n let second = api.synchronize_startup();\n assert_eq!(\n second\n .iter()\n .find(|result| result.agent_id == \"opencode\")\n .expect(\"updated OpenCode result\")\n .updated,\n 1\n );\n let updated = repository\n .get_profile(\"opencode\", &imported.id)\n .expect(\"updated profile\");\n assert_eq!(updated.name, \"DeepSeek Updated\");\n assert!(matches!(\n updated.payload,\n CliConfigPayload::Opencode { ref base_url, ref default_model, .. }\n if base_url == \"https://api.deepseek.com/v2\" && default_model == \"deepseek-reasoner\"\n ));\n\n std::fs::write(&config_path, r#\"{\"provider\":{}}\"#).expect(\"remove live provider\");\n api.synchronize_startup();\n assert!(repository.get_profile(\"opencode\", &imported.id).is_ok());\n }\n\n #[test]\n fn exclusive_switch_backfills_external_live_changes_without_a_resolution_choice() {\n let directory = tempfile::tempdir().expect(\"temporary home\");\n let repository = Arc::new(MemoryRepository::default());\n let api = CliConfigApi::new(\n repository.clone(),\n Arc::new(MemoryCredentials::default()),\n Arc::new(NativeCliGlobalConfigAdapter::with_home(\n directory.path().to_path_buf(),\n )),\n Arc::new(NoopLog),\n );\n let previous = api\n .save_profile(claude_without_credential(\"Previous\"))\n .expect(\"previous profile\");\n let target = api\n .save_profile(claude_without_credential(\"Target\"))\n .expect(\"target profile\");\n assert_eq!(\n api.apply_profile(ApplyCliConfigProfileInput {\n agent_id: \"claude-code\".into(),\n profile_id: previous.id.clone(),\n drift_resolution: None,\n confirm_auth_file_replacement: false,\n })\n .expect(\"apply previous\")\n .status,\n \"succeeded\"\n );\n let settings_path = directory.path().join(\".claude\").join(\"settings.json\");\n std::fs::write(\n &settings_path,\n r#\"{\"env\":{\"ANTHROPIC_BASE_URL\":\"https://edited.example.com\",\"ANTHROPIC_MODEL\":\"claude-edited\"}}\"#,\n )\n .expect(\"external edit\");\n\n let switched = api\n .apply_profile(ApplyCliConfigProfileInput {\n agent_id: \"claude-code\".into(),\n profile_id: target.id,\n drift_resolution: None,\n confirm_auth_file_replacement: false,\n })\n .expect(\"switch after external edit\");\n assert_eq!(switched.status, \"succeeded\");\n assert_eq!(switched.backfilled_profile_id, Some(previous.id.clone()));\n assert_eq!(\n switched.drift_resolution,\n Some(CliConfigDriftResolution::ImportCurrent)\n );\n let stored = repository\n .get_profile(\"claude-code\", &previous.id)\n .expect(\"backfilled profile\");\n assert!(matches!(\n stored.payload,\n CliConfigPayload::ClaudeCode { ref base_url, ref model, .. }\n if base_url == \"https://edited.example.com\" && model == \"claude-edited\"\n ));\n }\n}\n"}, "1fabf4a4d94f158d201e0aae0e22385888b8ab1f": {"t": 1785761113.409329, "n": 74890, "h": "5625cc3a76311599", "c": "use super::application::{\n CliConfigCredentialPort, CliConfigRepository, CliGlobalConfigPort, ProjectionOutcome,\n};\nuse super::domain::{\n validate_profile_input, validate_supported_agent, AppliedStateRecord,\n ApplyCliConfigProfileInput, CliConfigAppliedState, CliConfigApplyResult,\n CliConfigDiscoveryCandidate, CliConfigDiscoveryResult, CliConfigDiscoveryState,\n CliConfigDriftResolution, CliConfigDriftState, CliConfigError, CliConfigPayload,\n CliConfigProfile, CliConfigStartupSyncResult, CliConfigStartupSyncState, CliConfigStatus,\n CliConfigValidationState, DeleteCliConfigProfileInput, ImportCliConfigProfileInput,\n ImportDiscoveredCliConfigInput, ImportDiscoveredCliConfigResult, ProfileRecord,\n SaveCliConfigProfileInput, SkippedCliConfigDiscoveryCandidate, PAYLOAD_VERSION,\n SUPPORTED_AGENT_IDS,\n};\nuse crate::contexts::operations::api::{DiagnosticLog, DiagnosticLogPort, LogSeverity};\nuse chrono::Utc;\nuse std::collections::{BTreeMap, BTreeSet};\nuse std::sync::{Arc, Mutex};\nuse uuid::Uuid;\n\n#[derive(Clone)]\npub(crate) struct CliConfigApi {\n repository: Arc<dyn CliConfigRepository>,\n credentials: Arc<dyn CliConfigCredentialPort>,\n live: Arc<dyn CliGlobalConfigPort>,\n logging: Arc<dyn DiagnosticLogPort>,\n apply_locks: Arc<BTreeMap<String, Arc<Mutex<()>>>>,\n startup_sync: Arc<Mutex<BTreeMap<String, CliConfigStartupSyncResult>>>,\n}\n\nimpl CliConfigApi {\n pub(crate) fn new(\n repository: Arc<dyn CliConfigRepository>,\n credentials: Arc<dyn CliConfigCredentialPort>,\n live: Arc<dyn CliGlobalConfigPort>,\n logging: Arc<dyn DiagnosticLogPort>,\n ) -> Self {\n let apply_locks = super::domain::SUPPORTED_AGENT_IDS\n .into_iter()\n .map(|agent_id| (agent_id.to_string(), Arc::new(Mutex::new(()))))\n .collect();\n let startup_sync = SUPPORTED_AGENT_IDS\n .into_iter()\n .map(|agent_id| {\n (\n agent_id.to_string(),\n startup_sync_result(agent_id, CliConfigStartupSyncState::Pending),\n )\n })\n .collect();\n Self {\n repository,\n credentials,\n live,\n logging,\n apply_locks: Arc::new(apply_locks),\n startup_sync: Arc::new(Mutex::new(startup_sync)),\n }\n }\n\n pub(crate) fn synchronize_startup(&self) -> Vec<CliConfigStartupSyncResult> {\n SUPPORTED_AGENT_IDS\n .into_iter()\n .map(|agent_id| {\n let result = match self.synchronize_startup_agent(agent_id) {\n Ok(result) => result,\n Err(error) => {\n let mut result =\n startup_sync_result(agent_id, CliConfigStartupSyncState::Warning);\n result.skipped = 1;\n result.warnings.push(startup_sync_warning(&error));\n result.synchronized_at = Some(Utc::now().to_rfc3339());\n result\n }\n };\n self.write_log(\n if result.state == CliConfigStartupSyncState::Warning {\n LogSeverity::Warn\n } else {\n LogSeverity::Info\n },\n \"cli.config.startup.sync\",\n agent_id,\n None,\n None,\n &format!(\n \"startup CLI configuration sync completed: state={:?}, imported={}, updated={}, skipped={}\",\n result.state, result.imported, result.updated, result.skipped\n ),\n );\n if let Ok(mut stored) = self.startup_sync.lock() {\n stored.insert(agent_id.to_string(), result.clone());\n }\n result\n })\n .collect()\n }\n\n fn synchronize_startup_agent(\n &self,\n agent_id: &str,\n ) -> Result<CliConfigStartupSyncResult, CliConfigError> {\n if agent_id == \"opencode\" {\n return self.synchronize_opencode_startup();\n }\n let existing = self.repository.list_profiles(agent_id)?;\n if !existing.is_empty() {\n let mut result = startup_sync_result(agent_id, CliConfigStartupSyncState::Skipped);\n result.skipped = 1;\n result.synchronized_at = Some(Utc::now().to_rfc3339());\n return Ok(result);\n }\n let discovery = self.live.discover_current(agent_id)?;\n let Some(candidate) = discovery.candidates.into_iter().next() else {\n let mut result = startup_sync_result(agent_id, CliConfigStartupSyncState::Unchanged);\n result.warnings = discovery.warnings;\n result.synchronized_at = Some(Utc::now().to_rfc3339());\n return Ok(result);\n };\n let profile_id = format!(\"{agent_id}-default\");\n let imported_credential = candidate.credential.is_some();\n let record = self.persist_live_profile(\n agent_id,\n profile_id,\n \"default\".to_string(),\n candidate.payload,\n candidate.credential.as_deref().map(String::as_str),\n None,\n )?;\n let inspection = self.live.inspect(agent_id, None, Some(&record))?;\n let applied = AppliedStateRecord {\n agent_id: agent_id.to_string(),\n profile_id: Some(record.id.clone()),\n projection_fingerprint: inspection.managed_fingerprint.clone(),\n live_fingerprint: inspection.managed_fingerprint,\n drift_state: CliConfigDriftState::Applied,\n applied_at: Utc::now().to_rfc3339(),\n applied_payload: Some(record.payload.clone()),\n managed_keys: record.managed_keys.clone(),\n };\n if let Err(error) = self.repository.save_applied_state(&applied) {\n let credential_restored =\n !imported_credential || self.credentials.delete(agent_id, &record.id).is_ok();\n let profile_restored = self.repository.delete_profile(agent_id, &record.id).is_ok();\n if !credential_restored || !profile_restored {\n return Err(CliConfigError::RollbackIncomplete);\n }\n return Err(error);\n }\n let mut result = startup_sync_result(agent_id, CliConfigStartupSyncState::Imported);\n result.imported = 1;\n result.warnings = discovery.warnings;\n result.synchronized_at = Some(Utc::now().to_rfc3339());\n Ok(result)\n }\n\n fn synchronize_opencode_startup(&self) -> Result<CliConfigStartupSyncResult, CliConfigError> {\n let agent_id = \"opencode\";\n let discovery = self.live.discover_current(agent_id)?;\n let mut existing = self.repository.list_profiles(agent_id)?;\n let mut result = startup_sync_result(agent_id, CliConfigStartupSyncState::Unchanged);\n result.warnings = discovery.warnings;\n for candidate in discovery.candidates {\n let provider_id = match &candidate.payload {\n CliConfigPayload::Opencode { provider_id, .. } => provider_id.clone(),\n _ => continue,\n };\n let matched = existing.iter().find(|profile| {\n matches!(\n &profile.payload,\n CliConfigPayload::Opencode {\n provider_id: existing_id,\n ..\n } if existing_id == &provider_id\n )\n });\n let profile_id = match matched {\n Some(profile) => profile.id.clone(),\n None => self.next_profile_id(&format!(\"opencode-{provider_id}\"))?,\n };\n let prior = matched.cloned();\n let prior_secret = self.credentials.load(agent_id, &profile_id)?;\n let incoming_secret = candidate.credential.as_deref().map(String::as_str);\n let changed = prior.as_ref().is_none_or(|profile| {\n profile.payload != candidate.payload\n || profile.name != candidate.suggested_name\n || prior_secret.as_deref().map(String::as_str) != incoming_secret\n });\n if !changed {\n result.skipped += 1;\n continue;\n }\n let record = self.persist_live_profile(\n agent_id,\n profile_id,\n candidate.suggested_name,\n candidate.payload,\n incoming_secret,\n prior.as_ref(),\n )?;\n if prior.is_some() {\n result.updated += 1;\n } else {\n result.imported += 1;\n existing.push(record);\n }\n }\n result.state = if result.updated > 0 {\n CliConfigStartupSyncState::Updated\n } else if result.imported > 0 {\n CliConfigStartupSyncState::Imported\n } else {\n CliConfigStartupSyncState::Unchanged\n };\n result.synchronized_at = Some(Utc::now().to_rfc3339());\n Ok(result)\n }\n\n fn persist_live_profile(\n &self,\n agent_id: &str,\n profile_id: String,\n name: String,\n payload: CliConfigPayload,\n credential: Option<&str>,\n existing: Option<&ProfileRecord>,\n ) -> Result<ProfileRecord, CliConfigError> {\n payload.validate()?;\n if payload.agent_id() != agent_id {\n return Err(CliConfigError::Validation(\n \"live configuration payload does not match the selected Agent\".into(),\n ));\n }\n if credential\n .is_some_and(|secret| secret.is_empty() || secret.chars().any(char::is_control))\n {\n return Err(CliConfigError::Validation(\n \"live configuration credential is invalid\".into(),\n ));\n }\n let sort_position = match existing {\n Some(profile) => profile.sort_position,\n None => self.repository.list_profiles(agent_id)?.len() as i64,\n };\n let previous_secret = self.credentials.load(agent_id, &profile_id)?;\n match credential {\n Some(secret) => self.credentials.store(agent_id, &profile_id, secret)?,\n None if previous_secret.is_some() => self.credentials.delete(agent_id, &profile_id)?,\n None => {}\n }\n let now = Utc::now().to_rfc3339();\n let record = ProfileRecord {\n id: profile_id.clone(),\n agent_id: agent_id.to_string(),\n name,\n payload_version: PAYLOAD_VERSION,\n managed_keys: payload.managed_keys(),\n payload,\n source_preset_id: None,\n source_preset_version: None,\n created_at: existing\n .map(|profile| profile.created_at.clone())\n .unwrap_or_else(|| now.clone()),\n updated_at: now,\n sort_position,\n };\n if let Err(error) = self.repository.save_profile(&record) {\n if self\n .restore_credential(\n agent_id,\n &profile_id,\n previous_secret.as_deref().map(String::as_str),\n )\n .is_err()\n {\n return Err(CliConfigError::RollbackIncomplete);\n }\n return Err(error);\n }\n Ok(record)\n }\n\n pub(crate) fn list_profiles(\n &self,\n agent_id: &str,\n ) -> Result<Vec<CliConfigProfile>, CliConfigError> {\n validate_supported_agent(agent_id)?;\n let status = self.inspect_status(agent_id)?;\n self.repository\n .list_profiles(agent_id)?\n .into_iter()\n .map(|record| self.profile_view(record, &status))\n .collect()\n }\n\n pub(crate) fn inspect_status(&self, agent_id: &str) -> Result<CliConfigStatus, CliConfigError> {\n validate_supported_agent(agent_id)?;\n let applied = self.repository.applied_state(agent_id)?;\n let applied_profile = applied\n .as_ref()\n .map(|state| self.applied_profile_snapshot(agent_id, state))\n .transpose()?\n .flatten();\n let inspection = self\n .live\n .inspect(agent_id, applied.as_ref(), applied_profile.as_ref())?;\n Ok(CliConfigStatus {\n agent_id: agent_id.to_string(),\n applied_profile_id: applied.as_ref().and_then(|state| state.profile_id.clone()),\n drift_state: inspection.state,\n resolved_paths: inspection\n .paths\n .into_iter()\n .map(|path| path.display().to_string())\n .collect(),\n last_applied_at: applied.map(|state| state.applied_at),\n simulated: false,\n startup_sync: self.startup_sync_result(agent_id),\n })\n }\n\n fn startup_sync_result(&self, agent_id: &str) -> CliConfigStartupSyncResult {\n self.startup_sync\n .lock()\n .ok()\n .and_then(|results| results.get(agent_id).cloned())\n .unwrap_or_else(|| startup_sync_result(agent_id, CliConfigStartupSyncState::Warning))\n }\n\n pub(crate) fn save_profile(\n &self,\n input: SaveCliConfigProfileInput,\n ) -> Result<CliConfigProfile, CliConfigError> {\n let agent_id = input.agent_id.clone();\n let result = self.save_profile_inner(input);\n self.log_result(\n \"cli.config.profile.save\",\n &agent_id,\n result.as_ref().ok().map(|p| p.id.as_str()),\n &result,\n );\n result\n }\n\n fn save_profile_inner(\n &self,\n input: SaveCliConfigProfileInput,\n ) -> Result<CliConfigProfile, CliConfigError> {\n validate_profile_input(&input)?;\n if input.credential.is_some() && input.remove_credential {\n return Err(CliConfigError::Validation(\n \"credential cannot be replaced and removed in one request\".into(),\n ));\n }\n if let Some(source_id) = input.source_preset_id.as_deref() {\n let compatible_prefix = format!(\"{}-\", input.agent_id);\n if !source_id.starts_with(&compatible_prefix) {\n return Err(CliConfigError::Validation(\n \"preset is incompatible with the selected Agent\".into(),\n ));\n }\n }\n\n let existing = input\n .id\n .as_deref()\n .map(|id| self.repository.get_profile(&input.agent_id, id))\n .transpose()?;\n let id = match &existing {\n Some(profile) => profile.id.clone(),\n None => self.next_profile_id(&input.name)?,\n };\n let previous_secret = self.credentials.load(&input.agent_id, &id)?;\n if existing.is_none()\n && input.payload.requires_credential()\n && input.credential.is_none()\n && !input.remove_credential\n {\n return Err(CliConfigError::CredentialRequired);\n }\n\n let wrote_credential = if let Some(secret) = input.credential.as_deref() {\n self.credentials.store(&input.agent_id, &id, secret)?;\n true\n } else if input.remove_credential {\n self.credentials.delete(&input.agent_id, &id)?;\n true\n } else {\n false\n };\n\n let now = Utc::now().to_rfc3339();\n let record = ProfileRecord {\n id: id.clone(),\n agent_id: input.agent_id.clone(),\n name: input.name.trim().to_string(),\n payload_version: PAYLOAD_VERSION,\n managed_keys: input.payload.managed_keys(),\n payload: input.payload,\n source_preset_id: input.source_preset_id,\n source_preset_version: input.source_preset_version,\n created_at: existing\n .as_ref()\n .map(|profile| profile.created_at.clone())\n .unwrap_or_else(|| now.clone()),\n updated_at: now,\n sort_position: existing\n .as_ref()\n .map(|profile| profile.sort_position)\n .unwrap_or(self.repository.list_profiles(&input.agent_id)?.len() as i64),\n };\n if let Err(error) = self.repository.save_profile(&record) {\n if wrote_credential {\n self.restore_credential(\n &input.agent_id,\n &id,\n previous_secret.as_deref().map(String::as_str),\n )?;\n }\n return Err(error);\n }\n let status = self.inspect_status(&input.agent_id)?;\n self.profile_view(record, &status)\n }\n\n pub(crate) fn duplicate_profile(\n &self,\n agent_id: &str,\n profile_id: &str,\n ) -> Result<CliConfigProfile, CliConfigError> {\n validate_supported_agent(agent_id)?;\n let source = self.repository.get_profile(agent_id, profile_id)?;\n let credential = self.credentials.load(agent_id, profile_id)?;\n let names = self\n .repository\n .list_profiles(agent_id)?\n .into_iter()\n .map(|profile| profile.name)\n .collect::<Vec<_>>();\n let name = unique_copy_name(&source.name, &names);\n self.save_profile(SaveCliConfigProfileInput {\n id: None,\n agent_id: source.agent_id,\n name,\n payload: source.payload,\n source_preset_id: source.source_preset_id,\n source_preset_version: source.source_preset_version,\n credential: credential.as_deref().map(ToString::to_string),\n remove_credential: false,\n })\n }\n\n pub(crate) fn delete_profile(\n &self,\n input: DeleteCliConfigProfileInput,\n ) -> Result<(), CliConfigError> {\n validate_supported_agent(&input.agent_id)?;\n let profile = self\n .repository\n .get_profile(&input.agent_id, &input.profile_id)?;\n let applied = self.repository.applied_state(&input.agent_id)?;\n let is_applied = applied\n .as_ref()\n .and_then(|state| state.profile_id.as_deref())\n == Some(input.profile_id.as_str());\n if is_applied && !input.detach_applied {\n return Err(CliConfigError::Validation(\n \"applied profile must be detached before deletion\".into(),\n ));\n }\n let previous_secret = self.credentials.load(&input.agent_id, &input.profile_id)?;\n if is_applied {\n self.repository.clear_applied_state(&input.agent_id)?;\n }\n if let Err(error) = self.credentials.delete(&input.agent_id, &input.profile_id) {\n if let Some(state) = &applied {\n self.repository.save_applied_state(state)?;\n }\n return Err(error);\n }\n if let Err(error) = self\n .repository\n .delete_profile(&input.agent_id, &input.profile_id)\n {\n self.restore_credential(\n &input.agent_id,\n &input.profile_id,\n previous_secret.as_deref().map(String::as_str),\n )?;\n if let Some(state) = &applied {\n self.repository.save_applied_state(state)?;\n }\n return Err(error);\n }\n self.write_log(\n LogSeverity::Info,\n \"cli.config.profile.delete\",\n &input.agent_id,\n Some(&profile.id),\n None,\n \"deleted CLI configuration profile\",\n );\n Ok(())\n }\n\n pub(crate) fn import_current(\n &self,\n input: ImportCliConfigProfileInput,\n ) -> Result<CliConfigProfile, CliConfigError> {\n validate_supported_agent(&input.agent_id)?;\n let imported = self.live.import_current(&input.agent_id)?;\n let result = self.save_profile(SaveCliConfigProfileInput {\n id: None,\n agent_id: input.agent_id.clone(),\n name: input.name,\n payload: imported.payload,\n source_preset_id: None,\n source_preset_version: None,\n credential: imported.credential.as_deref().map(ToString::to_string),\n remove_credential: false,\n });\n self.log_result(\n \"cli.config.profile.import\",\n &input.agent_id,\n result.as_ref().ok().map(|profile| profile.id.as_str()),\n &result,\n );\n result\n }\n\n pub(crate) fn discover_profiles(\n &self,\n agent_id: &str,\n ) -> Result<CliConfigDiscoveryResult, CliConfigError> {\n validate_supported_agent(agent_id)?;\n let resolved_paths = self\n .live\n .paths(agent_id)?\n .into_iter()\n .map(|path| path.display().to_string())\n .collect::<Vec<_>>();\n match self.live.discover_current(agent_id) {\n Ok(discovery) => {\n let candidate_paths = discovery\n .paths\n .iter()\n .map(|path| path.display().to_string())\n .collect::<Vec<_>>();\n Ok(CliConfigDiscoveryResult {\n agent_id: agent_id.to_string(),\n state: CliConfigDiscoveryState::Available,\n candidates: discovery\n .candidates\n .into_iter()\n .map(|candidate| CliConfigDiscoveryCandidate {\n candidate_key: candidate.candidate_key,\n suggested_name: candidate.suggested_name,\n provider_name: candidate.provider_name,\n endpoint: candidate.endpoint,\n model: candidate.model,\n credential_detected: candidate.credential.is_some(),\n is_default: candidate.is_default,\n resolved_paths: candidate_paths.clone(),\n })\n .collect(),\n resolved_paths: candidate_paths,\n warnings: discovery.warnings,\n error: None,\n simulated: false,\n })\n }\n Err(CliConfigError::Parse { path, message: _ }) => Ok(CliConfigDiscoveryResult {\n agent_id: agent_id.to_string(),\n state: CliConfigDiscoveryState::ParseError,\n candidates: Vec::new(),\n resolved_paths,\n warnings: Vec::new(),\n error: Some(format!(\n \"Could not parse {path} as a supported CLI configuration.\"\n )),\n simulated: false,\n }),\n Err(error) => Err(error),\n }\n }\n\n pub(crate) fn import_discovered_profiles(\n &self,\n input: ImportDiscoveredCliConfigInput,\n ) -> Result<ImportDiscoveredCliConfigResult, CliConfigError> {\n validate_supported_agent(&input.agent_id)?;\n if input.candidate_keys.is_empty() {\n return Err(CliConfigError::Validation(\n \"at least one discovered candidate must be selected\".into(),\n ));\n }\n if input.candidate_keys.len() > 64 {\n return Err(CliConfigError::Validation(\n \"too many discovered candidates were selected\".into(),\n ));\n }\n let requested = input.candidate_keys.into_iter().collect::<BTreeSet<_>>();\n let discovery = self.live.discover_current(&input.agent_id)?;\n let available = discovery\n .candidates\n .iter()\n .map(|candidate| candidate.candidate_key.clone())\n .collect::<BTreeSet<_>>();\n if let Some(missing) = requested.difference(&available).next() {\n return Err(CliConfigError::Validation(format!(\n \"discovered candidate is no longer available: {missing}\"\n )));\n }\n let mut existing_names = self\n .repository\n .list_profiles(&input.agent_id)?\n .into_iter()\n .map(|profile| profile.name.trim().to_lowercase())\n .collect::<BTreeSet<_>>();\n let mut imported = Vec::new();\n let mut skipped = Vec::new();\n for candidate in discovery\n .candidates\n .into_iter()\n .filter(|candidate| requested.contains(&candidate.candidate_key))\n {\n let normalized_name = candidate.suggested_name.trim().to_lowercase();\n if existing_names.contains(&normalized_name) {\n skipped.push(SkippedCliConfigDiscoveryCandidate {\n candidate_key: candidate.candidate_key,\n suggested_name: candidate.suggested_name,\n reason: \"name-conflict\".into(),\n });\n continue;\n }\n let profile = self.save_profile(SaveCliConfigProfileInput {\n id: None,\n agent_id: input.agent_id.clone(),\n name: candidate.suggested_name,\n payload: candidate.payload,\n source_preset_id: None,\n source_preset_version: None,\n credential: candidate.credential.as_deref().map(ToString::to_string),\n remove_credential: false,\n })?;\n existing_names.insert(normalized_name);\n imported.push(profile);\n }\n self.write_log(\n LogSeverity::Info,\n \"cli.config.discovery.import\",\n &input.agent_id,\n None,\n None,\n &format!(\n \"imported {} discovered CLI configurations and skipped {}\",\n imported.len(),\n skipped.len()\n ),\n );\n Ok(ImportDiscoveredCliConfigResult { imported, skipped })\n }\n\n pub(crate) fn apply_profile(\n &self,\n input: ApplyCliConfigProfileInput,\n ) -> Result<CliConfigApplyResult, CliConfigError> {\n validate_supported_agent(&input.agent_id)?;\n let operation_id = Uuid::new_v4().to_string();\n let result = self.apply_profile_inner(&input);\n let apply_result = match result {\n Ok((profile, outcome, backfilled_profile_id)) => apply_result(\n operation_id,\n &profile,\n outcome,\n if backfilled_profile_id.is_some() {\n Some(CliConfigDriftResolution::ImportCurrent)\n } else {\n input.drift_resolution.clone()\n },\n backfilled_profile_id,\n ),\n Err(error) => failed_apply_result(\n operation_id,\n &input,\n self.live.paths(&input.agent_id).unwrap_or_default(),\n &error,\n ),\n };\n self.write_apply_log(&apply_result);\n Ok(apply_result)\n }\n\n fn apply_profile_inner(\n &self,\n input: &ApplyCliConfigProfileInput,\n ) -> Result<(ProfileRecord, ProjectionOutcome, Option<String>), CliConfigError> {\n let apply_lock = self\n .apply_locks\n .get(&input.agent_id)\n .cloned()\n .ok_or(CliConfigError::Repository)?;\n let _apply_guard = apply_lock.lock().map_err(|_| CliConfigError::Repository)?;\n let profile = self\n .repository\n .get_profile(&input.agent_id, &input.profile_id)?;\n profile.payload.validate()?;\n let credential = self.credentials.load(&input.agent_id, &input.profile_id)?;\n if profile.payload.requires_credential() && credential.is_none() {\n return Err(CliConfigError::CredentialRequired);\n }\n let previous_state = self.repository.applied_state(&input.agent_id)?;\n let mut previous_profile = previous_state\n .as_ref()\n .map(|state| self.applied_profile_snapshot(&input.agent_id, state))\n .transpose()?\n .flatten();\n let inspection = self.live.inspect(\n &input.agent_id,\n previous_state.as_ref(),\n previous_profile.as_ref(),\n )?;\n if inspection.state == CliConfigDriftState::Malformed {\n return Err(CliConfigError::Parse {\n path: inspection\n .paths\n .first()\n .map(|path| path.display().to_string())\n .unwrap_or_else(|| \"configuration\".into()),\n message: \"existing configuration is malformed\".into(),\n });\n }\n let switching_exclusive_profile = input.agent_id != \"opencode\"\n && previous_profile\n .as_ref()\n .is_some_and(|previous| previous.id != profile.id);\n let backfilled_profile_id = if switching_exclusive_profile {\n let previous = previous_profile\n .as_ref()\n .ok_or(CliConfigError::Repository)?;\n let (updated, source_fingerprint) = self.backfill_profile(&input.agent_id, previous)?;\n let id = updated.id.clone();\n previous_profile = Some(updated);\n Some((id, source_fingerprint))\n } else {\n None\n };\n let expected_live_fingerprint = backfilled_profile_id\n .as_ref()\n .map(|(_, fingerprint)| fingerprint.clone())\n .unwrap_or(inspection.managed_fingerprint);\n let backfilled_profile_id = backfilled_profile_id.map(|(id, _)| id);\n\n let outcome = self.live.apply(\n &profile,\n previous_profile.as_ref(),\n credential.as_deref().map(|secret| secret.as_str()),\n input.confirm_auth_file_replacement,\n &expected_live_fingerprint,\n )?;\n let applied = AppliedStateRecord {\n agent_id: input.agent_id.clone(),\n profile_id: Some(profile.id.clone()),\n projection_fingerprint: outcome.projection_fingerprint.clone(),\n live_fingerprint: outcome.live_fingerprint.clone(),\n drift_state: CliConfigDriftState::Applied,\n applied_at: Utc::now().to_rfc3339(),\n applied_payload: Some(profile.payload.clone()),\n managed_keys: profile.managed_keys.clone(),\n };\n if let Err(error) = self.repository.save_applied_state(&applied) {\n let live_restored = self.live.restore(&outcome).is_ok();\n let state_restored = if let Some(previous) = &previous_state {\n self.repository.save_applied_state(previous).is_ok()\n } else {\n self.repository.clear_applied_state(&input.agent_id).is_ok()\n };\n if !live_restored || !state_restored {\n return Err(CliConfigError::RollbackIncomplete);\n }\n return Err(error);\n }\n Ok((profile, outcome, backfilled_profile_id))\n }\n\n fn backfill_profile(\n &self,\n agent_id: &str,\n previous: &ProfileRecord,\n ) -> Result<(ProfileRecord, String), CliConfigError> {\n let imported = self.live.import_current(agent_id)?;\n let source_fingerprint = imported.source_fingerprint.clone();\n imported.payload.validate()?;\n let mut updated = previous.clone();\n updated.payload = imported.payload;\n updated.managed_keys = previous\n .managed_keys\n .iter()\n .cloned()\n .chain(updated.payload.managed_keys())\n .collect::<BTreeSet<_>>()\n .into_iter()\n .collect();\n updated.updated_at = Utc::now().to_rfc3339();\n let previous_secret = self.credentials.load(agent_id, &updated.id)?;\n let incoming_secret = imported.credential.as_deref().map(String::as_str);\n match incoming_secret {\n Some(secret) => self.credentials.store(agent_id, &updated.id, secret)?,\n None if previous_secret.is_some() => self.credentials.delete(agent_id, &updated.id)?,\n None => {}\n }\n if let Err(error) = self.repository.save_profile(&updated) {\n if self\n .restore_credential(\n agent_id,\n &updated.id,\n previous_secret.as_deref().map(String::as_str),\n )\n .is_err()\n {\n return Err(CliConfigError::RollbackIncomplete);\n }\n return Err(error);\n }\n self.write_log(\n LogSeverity::Info,\n \"cli.config.profile.backfill\",\n agent_id,\n Some(&updated.id),\n None,\n \"backfilled current live configuration into the leaving profile\",\n );\n Ok((updated, source_fingerprint))\n }\n\n fn profile_view(\n &self,\n record: ProfileRecord,\n status: &CliConfigStatus,\n ) -> Result<CliConfigProfile, CliConfigError> {\n let credential_configured = self\n .credentials\n .load(&record.agent_id, &record.id)?\n .is_some();\n let validation_state = if record.payload.validate().is_err() {\n CliConfigValidationState::Invalid\n } else if record.payload.requires_credential() && !credential_configured {\n CliConfigValidationState::NeedsCredential\n } else {\n CliConfigValidationState::Valid\n };\n let applied_state = if status.applied_profile_id.as_deref() == Some(record.id.as_str()) {\n if status.drift_state == CliConfigDriftState::Applied {\n CliConfigAppliedState::Applied\n } else {\n CliConfigAppliedState::Drifted\n }\n } else {\n CliConfigAppliedState::Saved\n };\n Ok(CliConfigProfile {\n id: record.id,\n agent_id: record.agent_id,\n name: record.name,\n payload_version: record.payload_version,\n payload: record.payload,\n source_preset_id: record.source_preset_id,\n source_preset_version: record.source_preset_version,\n credential_configured,\n validation_state,\n applied_state,\n created_at: record.created_at,\n updated_at: record.updated_at,\n })\n }\n\n fn applied_profile_snapshot(\n &self,\n agent_id: &str,\n state: &AppliedStateRecord,\n ) -> Result<Option<ProfileRecord>, CliConfigError> {\n let Some(profile_id) = state.profile_id.as_deref() else {\n return Ok(None);\n };\n let mut profile = self.repository.get_profile(agent_id, profile_id)?;\n if let Some(payload) = &state.applied_payload {\n profile.payload = payload.clone();\n }\n if !state.managed_keys.is_empty() {\n profile.managed_keys = state.managed_keys.clone();\n }\n Ok(Some(profile))\n }\n\n fn next_profile_id(&self, name: &str) -> Result<String, CliConfigError> {\n let base = slug(name);\n if !self.repository.profile_id_exists(&base)? {\n return Ok(base);\n }\n for suffix in 2..10_000 {\n let candidate = format!(\"{base}-{suffix}\");\n if !self.repository.profile_id_exists(&candidate)? {\n return Ok(candidate);\n }\n }\n Err(CliConfigError::Repository)\n }\n\n fn restore_credential(\n &self,\n agent_id: &str,\n profile_id: &str,\n previous: Option<&str>,\n ) -> Result<(), CliConfigError> {\n match previous {\n Some(secret) => self.credentials.store(agent_id, profile_id, secret),\n None => self.credentials.delete(agent_id, profile_id),\n }\n }\n\n fn log_result<T>(\n &self,\n category: &str,\n agent_id: &str,\n profile_id: Option<&str>,\n result: &Result<T, CliConfigError>,\n ) {\n self.write_log(\n if result.is_ok() {\n LogSeverity::Info\n } else {\n LogSeverity::Error\n },\n category,\n agent_id,\n profile_id,\n None,\n if result.is_ok() {\n \"CLI configuration operation succeeded\"\n } else {\n \"CLI configuration operation failed\"\n },\n );\n }\n\n fn write_log(\n &self,\n severity: LogSeverity,\n category: &str,\n agent_id: &str,\n profile_id: Option<&str>,\n operation_id: Option<&str>,\n message: &str,\n ) {\n let mut context = BTreeMap::from([(\"agentId\".into(), agent_id.to_string())]);\n if let Some(profile_id) = profile_id {\n context.insert(\"profileId\".into(), profile_id.to_string());\n }\n if let Some(operation_id) = operation_id {\n context.insert(\"operationId\".into(), operation_id.to_string());\n }\n context.insert(\n \"status\".into(),\n if severity == LogSeverity::Error {\n \"failed\"\n } else {\n \"succeeded\"\n }\n .into(),\n );\n let _ = self.logging.write_diagnostic(DiagnosticLog {\n severity,\n category: category.into(),\n message: message.into(),\n context,\n });\n }\n\n fn write_apply_log(&self, result: &CliConfigApplyResult) {\n let mut context = BTreeMap::from([\n (\"agentId\".into(), result.agent_id.clone()),\n (\"profileId\".into(), result.profile_id.clone()),\n (\"operationId\".into(), result.operation_id.clone()),\n (\"status\".into(), result.status.clone()),\n (\"restored\".into(), result.restored.to_string()),\n ]);\n let target_files = result\n .affected_paths\n .iter()\n .filter_map(|path| std::path::Path::new(path).file_name())\n .map(|name| name.to_string_lossy())\n .collect::<Vec<_>>()\n .join(\",\");\n if !target_files.is_empty() {\n context.insert(\"targetFiles\".into(), target_files);\n }\n let succeeded = result.status == \"succeeded\";\n let _ = self.logging.write_diagnostic(DiagnosticLog {\n severity: if succeeded {\n LogSeverity::Info\n } else {\n LogSeverity::Error\n },\n category: \"cli.config.profile.apply\".into(),\n message: if succeeded {\n \"applied CLI configuration profile\"\n } else {\n \"CLI configuration profile application failed\"\n }\n .into(),\n context,\n });\n }\n}\n\nfn startup_sync_result(\n agent_id: &str,\n state: CliConfigStartupSyncState,\n) -> CliConfigStartupSyncResult {\n CliConfigStartupSyncResult {\n agent_id: agent_id.to_string(),\n state,\n imported: 0,\n updated: 0,\n skipped: 0,\n warnings: Vec::new(),\n synchronized_at: None,\n simulated: false,\n }\n}\n\nfn startup_sync_warning(error: &CliConfigError) -> String {\n match error {\n CliConfigError::Parse { .. } => {\n \"The local CLI configuration could not be parsed; startup synchronization was skipped.\"\n }\n CliConfigError::Filesystem { .. } => {\n \"The local CLI configuration could not be read; startup synchronization was skipped.\"\n }\n CliConfigError::Credential | CliConfigError::CredentialRequired => {\n \"The local CLI credential could not be synchronized safely.\"\n }\n CliConfigError::RollbackIncomplete => {\n \"Startup synchronization could not fully restore an interrupted profile update.\"\n }\n _ => \"Startup synchronization could not be completed.\",\n }\n .to_string()\n}\n\nfn apply_result(\n operation_id: String,\n profile: &ProfileRecord,\n outcome: ProjectionOutcome,\n drift_resolution: Option<super::domain::CliConfigDriftResolution>,\n backfilled_profile_id: Option<String>,\n) -> CliConfigApplyResult {\n CliConfigApplyResult {\n operation_id,\n status: \"succeeded\".into(),\n agent_id: profile.agent_id.clone(),\n profile_id: profile.id.clone(),\n affected_paths: outcome\n .paths\n .into_iter()\n .map(|path| path.display().to_string())\n .collect(),\n drift_resolution,\n backfilled_profile_id,\n warnings: outcome.warnings,\n restart_required: true,\n simulated: false,\n restored: outcome.restored,\n error: None,\n }\n}\n\nfn failed_apply_result(\n operation_id: String,\n input: &ApplyCliConfigProfileInput,\n paths: Vec<std::path::PathBuf>,\n error: &CliConfigError,\n) -> CliConfigApplyResult {\n CliConfigApplyResult {\n operation_id,\n status: \"failed\".into(),\n agent_id: input.agent_id.clone(),\n profile_id: input.profile_id.clone(),\n affected_paths: paths\n .into_iter()\n .map(|path| path.display().to_string())\n .collect(),\n drift_resolution: input.drift_resolution.clone(),\n backfilled_profile_id: None,\n warnings: Vec::new(),\n restart_required: false,\n simulated: false,\n restored: !matches!(error, CliConfigError::RollbackIncomplete),\n error: Some(error.to_string()),\n }\n}\n\nfn slug(value: &str) -> String {\n let mut output = String::new();\n let mut separator = false;\n for character in value.trim().chars() {\n if character.is_ascii_alphanumeric() {\n output.push(character.to_ascii_lowercase());\n separator = false;\n } else if !separator && !output.is_empty() {\n output.push('-');\n separator = true;\n }\n }\n while output.ends_with('-') {\n output.pop();\n }\n if output.is_empty() {\n \"profile\".into()\n } else {\n output\n }\n}\n\nfn unique_copy_name(source: &str, existing: &[String]) -> String {\n let base = format!(\"{source} Copy\");\n if !existing.contains(&base) {\n return base;\n }\n for suffix in 2..10_000 {\n let candidate = format!(\"{base} {suffix}\");\n if !existing.contains(&candidate) {\n return candidate;\n }\n }\n format!(\"{base} {}\", Uuid::new_v4())\n}\n\n#[cfg(test)]\nmod tests {\n use super::*;\n use crate::contexts::operations::api::OperationsError;\n use crate::contexts::tooling::cli_config::application::{ImportedLiveConfig, LiveInspection};\n use crate::contexts::tooling::cli_config::domain::{\n ApplyCliConfigProfileInput, ClaudeAuthMode, CliConfigDriftResolution, CliConfigPayload,\n ImportDiscoveredCliConfigInput, SaveCliConfigProfileInput,\n };\n use crate::contexts::tooling::cli_config::infrastructure::NativeCliGlobalConfigAdapter;\n use std::path::PathBuf;\n use std::sync::atomic::{AtomicUsize, Ordering};\n use std::thread;\n use std::time::Duration;\n\n #[derive(Default)]\n struct MemoryRepository {\n profiles: Mutex<Vec<ProfileRecord>>,\n applied: Mutex<BTreeMap<String, AppliedStateRecord>>,\n fail_next_save: AtomicUsize,\n }\n\n impl CliConfigRepository for MemoryRepository {\n fn list_profiles(&self, agent_id: &str) -> Result<Vec<ProfileRecord>, CliConfigError> {\n Ok(self\n .profiles\n .lock()\n .map_err(|_| CliConfigError::Repository)?\n .iter()\n .filter(|profile| profile.agent_id == agent_id)\n .cloned()\n .collect())\n }\n\n fn get_profile(\n &self,\n agent_id: &str,\n profile_id: &str,\n ) -> Result<ProfileRecord, CliConfigError> {\n self.profiles\n .lock()\n .map_err(|_| CliConfigError::Repository)?\n .iter()\n .find(|profile| profile.agent_id == agent_id && profile.id == profile_id)\n .cloned()\n .ok_or(CliConfigError::NotFound)\n }\n\n fn profile_id_exists(&self, profile_id: &str) -> Result<bool, CliConfigError> {\n Ok(self\n .profiles\n .lock()\n .map_err(|_| CliConfigError::Repository)?\n .iter()\n .any(|profile| profile.id == profile_id))\n }\n\n fn save_profile(&self, profile: &ProfileRecord) -> Result<(), CliConfigError> {\n if self.fail_next_save.swap(0, Ordering::SeqCst) > 0 {\n return Err(CliConfigError::Repository);\n }\n let mut profiles = self\n .profiles\n .lock()\n .map_err(|_| CliConfigError::Repository)?;\n profiles.retain(|candidate| candidate.id != profile.id);\n profiles.push(profile.clone());\n Ok(())\n }\n\n fn delete_profile(&self, agent_id: &str, profile_id: &str) -> Result<(), CliConfigError> {\n let mut profiles = self\n .profiles\n .lock()\n .map_err(|_| CliConfigError::Repository)?;\n let before = profiles.len();\n profiles.retain(|profile| profile.agent_id != agent_id || profile.id != profile_id);\n if profiles.len() == before {\n return Err(CliConfigError::NotFound);\n }\n Ok(())\n }\n\n fn applied_state(\n &self,\n agent_id: &str,\n ) -> Result<Option<AppliedStateRecord>, CliConfigError> {\n Ok(self\n .applied\n .lock()\n .map_err(|_| CliConfigError::Repository)?\n .get(agent_id)\n .cloned())\n }\n\n fn save_applied_state(&self, state: &AppliedStateRecord) -> Result<(), CliConfigError> {\n self.applied\n .lock()\n .map_err(|_| CliConfigError::Repository)?\n .insert(state.agent_id.clone(), state.clone());\n Ok(())\n }\n\n fn clear_applied_state(&self, agent_id: &str) -> Result<(), CliConfigError> {\n self.applied\n .lock()\n .map_err(|_| CliConfigError::Repository)?\n .remove(agent_id);\n Ok(())\n }\n }\n\n #[derive(Default)]\n struct MemoryCredentials {\n values: Mutex<BTreeMap<(String, String), String>>,\n }\n\n impl CliConfigCredentialPort for MemoryCredentials {\n fn load(\n &self,\n agent_id: &str,\n profile_id: &str,\n ) -> Result<Option<zeroize::Zeroizing<String>>, CliConfigError> {\n Ok(self\n .values\n .lock()\n .map_err(|_| CliConfigError::Credential)?\n .get(&(agent_id.to_string(), profile_id.to_string()))\n .cloned()\n .map(zeroize::Zeroizing::new))\n }\n\n fn store(\n &self,\n agent_id: &str,\n profile_id: &str,\n secret: &str,\n ) -> Result<(), CliConfigError> {\n self.values\n .lock()\n .map_err(|_| CliConfigError::Credential)?\n .insert(\n (agent_id.to_string(), profile_id.to_string()),\n secret.to_string(),\n );\n Ok(())\n }\n\n fn delete(&self, agent_id: &str, profile_id: &str) -> Result<(), CliConfigError> {\n self.values\n .lock()\n .map_err(|_| CliConfigError::Credential)?\n .remove(&(agent_id.to_string(), profile_id.to_string()));\n Ok(())\n }\n }\n\n #[derive(Default)]\n struct SerialProbeLiveConfig {\n active: AtomicUsize,\n max_active: AtomicUsize,\n }\n\n impl CliGlobalConfigPort for SerialProbeLiveConfig {\n fn paths(&self, _agent_id: &str) -> Result<Vec<PathBuf>, CliConfigError> {\n Ok(vec![PathBuf::from(\"safe-config\")])\n }\n\n fn inspect(\n &self,\n agent_id: &str,\n _applied: Option<&AppliedStateRecord>,\n _applied_profile: Option<&ProfileRecord>,\n ) -> Result<LiveInspection, CliConfigError> {\n Ok(LiveInspection {\n paths: self.paths(agent_id)?,\n state: CliConfigDriftState::Detached,\n managed_fingerprint: \"before\".into(),\n })\n }\n\n fn import_current(&self, _agent_id: &str) -> Result<ImportedLiveConfig, CliConfigError> {\n Err(CliConfigError::NotFound)\n }\n\n fn apply(\n &self,\n _profile: &ProfileRecord,\n _previous: Option<&ProfileRecord>,\n _credential: Option<&str>,\n _confirm_auth_file_replacement: bool,\n _expected_live_fingerprint: &str,\n ) -> Result<ProjectionOutcome, CliConfigError> {\n let active = self.active.fetch_add(1, Ordering::SeqCst) + 1;\n self.max_active.fetch_max(active, Ordering::SeqCst);\n thread::sleep(Duration::from_millis(30));\n self.active.fetch_sub(1, Ordering::SeqCst);\n Ok(ProjectionOutcome {\n paths: vec![PathBuf::from(\"safe-config\")],\n projection_fingerprint: \"projection\".into(),\n live_fingerprint: \"live\".into(),\n warnings: Vec::new(),\n restored: true,\n backups: Vec::new(),\n })\n }\n\n fn restore(&self, _outcome: &ProjectionOutcome) -> Result<(), CliConfigError> {\n Ok(())\n }\n }\n\n #[derive(Default)]\n struct NoopLog;\n\n impl DiagnosticLogPort for NoopLog {\n fn write_diagnostic(&self, _log: DiagnosticLog) -> Result<(), OperationsError> {\n Ok(())\n }\n }\n\n #[derive(Default)]\n struct CapturingLog {\n entries: Mutex<Vec<DiagnosticLog>>,\n }\n\n impl DiagnosticLogPort for CapturingLog {\n fn write_diagnostic(&self, log: DiagnosticLog) -> Result<(), OperationsError> {\n self.entries.lock().expect(\"log entries\").push(log);\n Ok(())\n }\n }\n\n #[derive(Default)]\n struct RollbackFailLiveConfig;\n\n impl CliGlobalConfigPort for RollbackFailLiveConfig {\n fn paths(&self, _agent_id: &str) -> Result<Vec<PathBuf>, CliConfigError> {\n Ok(vec![PathBuf::from(\"safe-config\")])\n }\n\n fn inspect(\n &self,\n agent_id: &str,\n _applied: Option<&AppliedStateRecord>,\n _applied_profile: Option<&ProfileRecord>,\n ) -> Result<LiveInspection, CliConfigError> {\n Ok(LiveInspection {\n paths: self.paths(agent_id)?,\n state: CliConfigDriftState::Detached,\n managed_fingerprint: \"before\".into(),\n })\n }\n\n fn import_current(&self, _agent_id: &str) -> Result<ImportedLiveConfig, CliConfigError> {\n Err(CliConfigError::NotFound)\n }\n\n fn apply(\n &self,\n _profile: &ProfileRecord,\n _previous: Option<&ProfileRecord>,\n _credential: Option<&str>,\n _confirm_auth_file_replacement: bool,\n _expected_live_fingerprint: &str,\n ) -> Result<ProjectionOutcome, CliConfigError> {\n Err(CliConfigError::RollbackIncomplete)\n }\n\n fn restore(&self, _outcome: &ProjectionOutcome) -> Result<(), CliConfigError> {\n Err(CliConfigError::RollbackIncomplete)\n }\n }\n\n #[derive(Default)]\n struct DriftImportLiveConfig;\n\n impl CliGlobalConfigPort for DriftImportLiveConfig {\n fn paths(&self, _agent_id: &str) -> Result<Vec<PathBuf>, CliConfigError> {\n Ok(vec![PathBuf::from(\"safe-config\")])\n }\n\n fn inspect(\n &self,\n agent_id: &str,\n _applied: Option<&AppliedStateRecord>,\n _applied_profile: Option<&ProfileRecord>,\n ) -> Result<LiveInspection, CliConfigError> {\n Ok(LiveInspection {\n paths: self.paths(agent_id)?,\n state: CliConfigDriftState::Drifted,\n managed_fingerprint: \"drifted\".into(),\n })\n }\n\n fn import_current(&self, _agent_id: &str) -> Result<ImportedLiveConfig, CliConfigError> {\n Ok(ImportedLiveConfig {\n payload: CliConfigPayload::ClaudeCode {\n base_url: \"https://drifted.example.com\".into(),\n auth_mode: ClaudeAuthMode::AuthToken,\n model: \"drifted-model\".into(),\n haiku_model: \"drifted-model\".into(),\n sonnet_model: \"drifted-model\".into(),\n opus_model: \"drifted-model\".into(),\n advanced_env: BTreeMap::new(),\n },\n credential: Some(zeroize::Zeroizing::new(\"new-secret\".into())),\n source_fingerprint: \"file:drifted\".into(),\n })\n }\n\n fn apply(\n &self,\n _profile: &ProfileRecord,\n _previous: Option<&ProfileRecord>,\n _credential: Option<&str>,\n _confirm_auth_file_replacement: bool,\n _expected_live_fingerprint: &str,\n ) -> Result<ProjectionOutcome, CliConfigError> {\n Err(CliConfigError::Repository)\n }\n\n fn restore(&self, _outcome: &ProjectionOutcome) -> Result<(), CliConfigError> {\n Ok(())\n }\n }\n\n fn claude_without_credential(name: &str) -> SaveCliConfigProfileInput {\n SaveCliConfigProfileInput {\n id: None,\n agent_id: \"claude-code\".into(),\n name: name.into(),\n payload: CliConfigPayload::ClaudeCode {\n base_url: \"https://api.anthropic.com\".into(),\n auth_mode: ClaudeAuthMode::None,\n model: \"claude-sonnet-4-6\".into(),\n haiku_model: \"claude-haiku-4-5\".into(),\n sonnet_model: \"claude-sonnet-4-6\".into(),\n opus_model: \"claude-opus-4-6\".into(),\n advanced_env: BTreeMap::new(),\n },\n source_preset_id: None,\n source_preset_version: None,\n credential: None,\n remove_credential: false,\n }\n }\n\n #[test]\n fn profile_ids_are_stable_safe_slugs() {\n assert_eq!(slug(\" OpenRouter Primary \"), \"openrouter-primary\");\n assert_eq!(slug(\"智谱 GLM\"), \"glm\");\n assert_eq!(slug(\"智谱\"), \"profile\");\n }\n\n #[test]\n fn duplicate_names_do_not_collide() {\n assert_eq!(unique_copy_name(\"DeepSeek\", &[]), \"DeepSeek Copy\");\n assert_eq!(\n unique_copy_name(\"DeepSeek\", &[\"DeepSeek Copy\".into()]),\n \"DeepSeek Copy 2\"\n );\n }\n\n #[test]\n fn discovered_import_redacts_credentials_and_skips_case_insensitive_name_conflicts() {\n let directory = tempfile::tempdir().expect(\"temporary home\");\n let path = directory.path().join(\".claude\").join(\"settings.json\");\n std::fs::create_dir_all(path.parent().expect(\"parent\")).expect(\"directory\");\n std::fs::write(\n &path,\n r#\"{\"env\":{\"ANTHROPIC_AUTH_TOKEN\":\"discovery-secret\",\"ANTHROPIC_MODEL\":\"claude-sonnet-4-6\"}}\"#,\n )\n .expect(\"fixture\");\n let repository = Arc::new(MemoryRepository::default());\n let credentials = Arc::new(MemoryCredentials::default());\n let api = CliConfigApi::new(\n repository,\n credentials.clone(),\n Arc::new(NativeCliGlobalConfigAdapter::with_home(\n directory.path().to_path_buf(),\n )),\n Arc::new(NoopLog),\n );\n\n let discovery = api.discover_profiles(\"claude-code\").expect(\"discovery\");\n assert_eq!(discovery.candidates.len(), 1);\n assert!(discovery.candidates[0].credential_detected);\n let serialized = serde_json::to_string(&discovery).expect(\"serialize discovery\");\n assert!(!serialized.contains(\"discovery-secret\"));\n\n let first = api\n .import_discovered_profiles(ImportDiscoveredCliConfigInput {\n agent_id: \"claude-code\".into(),\n candidate_keys: vec![\"current\".into()],\n })\n .expect(\"first import\");\n assert_eq!(first.imported.len(), 1);\n assert!(credentials\n .load(\"claude-code\", &first.imported[0].id)\n .expect(\"credential\")\n .is_some());\n\n let second = api\n .import_discovered_profiles(ImportDiscoveredCliConfigInput {\n agent_id: \"claude-code\".into(),\n candidate_keys: vec![\"current\".into()],\n })\n .expect(\"conflict is reported\");\n assert!(second.imported.is_empty());\n assert_eq!(second.skipped.len(), 1);\n assert_eq!(second.skipped[0].reason, \"name-conflict\");\n\n std::fs::write(&path, r#\"{\"env\":{\"ANTHROPIC_AUTH_TOKEN\":\"must-not-leak\"}\"#)\n .expect(\"malformed fixture\");\n let malformed = api\n .discover_profiles(\"claude-code\")\n .expect(\"parse state is data\");\n assert_eq!(malformed.state, CliConfigDiscoveryState::ParseError);\n assert!(malformed.candidates.is_empty());\n assert!(!serde_json::to_string(&malformed)\n .expect(\"serialize malformed result\")\n .contains(\"must-not-leak\"));\n }\n\n #[test]\n fn command_errors_do_not_render_secret_values() {\n let rendered = CliConfigError::Credential.to_string();\n assert!(!rendered.contains(\"sk-secret\"));\n assert_eq!(rendered, \"secure credential operation failed\");\n }\n\n #[test]\n fn concurrent_applies_for_one_agent_are_serialized_end_to_end() {\n let repository = Arc::new(MemoryRepository::default());\n let live = Arc::new(SerialProbeLiveConfig::default());\n let api = CliConfigApi::new(\n repository,\n Arc::new(MemoryCredentials::default()),\n live.clone(),\n Arc::new(NoopLog),\n );\n let first = api\n .save_profile(claude_without_credential(\"First\"))\n .expect(\"first profile\");\n let second = api\n .save_profile(claude_without_credential(\"Second\"))\n .expect(\"second profile\");\n\n let first_api = api.clone();\n let first_handle = thread::spawn(move || {\n first_api.apply_profile(ApplyCliConfigProfileInput {\n agent_id: \"claude-code\".into(),\n profile_id: first.id,\n drift_resolution: None,\n confirm_auth_file_replacement: false,\n })\n });\n let second_api = api.clone();\n let second_handle = thread::spawn(move || {\n second_api.apply_profile(ApplyCliConfigProfileInput {\n agent_id: \"claude-code\".into(),\n profile_id: second.id,\n drift_resolution: None,\n confirm_auth_file_replacement: false,\n })\n });\n\n first_handle\n .join()\n .expect(\"first thread\")\n .expect(\"first apply\");\n second_handle\n .join()\n .expect(\"second thread\")\n .expect(\"second apply\");\n assert_eq!(live.max_active.load(Ordering::SeqCst), 1);\n }\n\n #[test]\n fn failed_profile_update_restores_the_previous_credential() {\n let repository = Arc::new(MemoryRepository::default());\n let credentials = Arc::new(MemoryCredentials::default());\n let api = CliConfigApi::new(\n repository.clone(),\n credentials.clone(),\n Arc::new(SerialProbeLiveConfig::default()),\n Arc::new(NoopLog),\n );\n let mut create = claude_without_credential(\"Credential profile\");\n if let CliConfigPayload::ClaudeCode { auth_mode, .. } = &mut create.payload {\n *auth_mode = ClaudeAuthMode::AuthToken;\n }\n create.credential = Some(\"old-secret\".into());\n let saved = api.save_profile(create.clone()).expect(\"initial profile\");\n\n repository.fail_next_save.store(1, Ordering::SeqCst);\n create.id = Some(saved.id.clone());\n create.credential = Some(\"new-secret\".into());\n assert!(matches!(\n api.save_profile(create),\n Err(CliConfigError::Repository)\n ));\n let restored = credentials\n .load(\"claude-code\", &saved.id)\n .expect(\"credential load\")\n .expect(\"restored credential\");\n assert_eq!(restored.as_str(), \"old-secret\");\n }\n\n #[test]\n fn applied_snapshot_removes_keys_owned_before_profile_edit() {\n let directory = tempfile::tempdir().expect(\"temporary home\");\n let repository = Arc::new(MemoryRepository::default());\n let api = CliConfigApi::new(\n repository,\n Arc::new(MemoryCredentials::default()),\n Arc::new(NativeCliGlobalConfigAdapter::with_home(\n directory.path().to_path_buf(),\n )),\n Arc::new(NoopLog),\n );\n let mut first_input = claude_without_credential(\"First\");\n if let CliConfigPayload::ClaudeCode { advanced_env, .. } = &mut first_input.payload {\n advanced_env.insert(\"VANEHUB_OLD_MANAGED\".into(), \"old\".into());\n }\n let first = api\n .save_profile(first_input.clone())\n .expect(\"first profile\");\n let first_apply = api\n .apply_profile(ApplyCliConfigProfileInput {\n agent_id: \"claude-code\".into(),\n profile_id: first.id.clone(),\n drift_resolution: None,\n confirm_auth_file_replacement: false,\n })\n .expect(\"first apply\");\n assert_eq!(first_apply.status, \"succeeded\");\n\n first_input.id = Some(first.id);\n if let CliConfigPayload::ClaudeCode { advanced_env, .. } = &mut first_input.payload {\n advanced_env.clear();\n }\n api.save_profile(first_input).expect(\"edit applied profile\");\n let second = api\n .save_profile(claude_without_credential(\"Second\"))\n .expect(\"second profile\");\n let second_apply = api\n .apply_profile(ApplyCliConfigProfileInput {\n agent_id: \"claude-code\".into(),\n profile_id: second.id,\n drift_resolution: None,\n confirm_auth_file_replacement: false,\n })\n .expect(\"second apply\");\n assert_eq!(second_apply.status, \"succeeded\");\n\n let settings =\n std::fs::read_to_string(directory.path().join(\".claude\").join(\"settings.json\"))\n .expect(\"settings\");\n assert!(!settings.contains(\"VANEHUB_OLD_MANAGED\"));\n }\n\n #[test]\n fn apply_failure_returns_restoration_status_and_redacted_log() {\n let repository = Arc::new(MemoryRepository::default());\n let logging = Arc::new(CapturingLog::default());\n let api = CliConfigApi::new(\n repository,\n Arc::new(MemoryCredentials::default()),\n Arc::new(RollbackFailLiveConfig),\n logging.clone(),\n );\n let profile = api\n .save_profile(claude_without_credential(\"Failure\"))\n .expect(\"profile\");\n let result = api\n .apply_profile(ApplyCliConfigProfileInput {\n agent_id: \"claude-code\".into(),\n profile_id: profile.id,\n drift_resolution: None,\n confirm_auth_file_replacement: false,\n })\n .expect(\"structured failure\");\n\n assert_eq!(result.status, \"failed\");\n assert!(!result.restored);\n assert_eq!(\n result.error.as_deref(),\n Some(\"configuration rollback was incomplete\")\n );\n let entries = logging.entries.lock().expect(\"logs\");\n let apply_log = entries\n .iter()\n .find(|entry| entry.category == \"cli.config.profile.apply\")\n .expect(\"apply log\");\n assert_eq!(\n apply_log.context.get(\"status\").map(String::as_str),\n Some(\"failed\")\n );\n assert_eq!(\n apply_log.context.get(\"restored\").map(String::as_str),\n Some(\"false\")\n );\n assert!(!format!(\"{apply_log:?}\").contains(\"secret\"));\n }\n\n #[test]\n fn drift_import_restores_previous_credential_when_profile_save_fails() {\n let repository = Arc::new(MemoryRepository::default());\n let credentials = Arc::new(MemoryCredentials::default());\n let api = CliConfigApi::new(\n repository.clone(),\n credentials.clone(),\n Arc::new(DriftImportLiveConfig),\n Arc::new(NoopLog),\n );\n let mut previous_input = claude_without_credential(\"Previous\");\n if let CliConfigPayload::ClaudeCode { auth_mode, .. } = &mut previous_input.payload {\n *auth_mode = ClaudeAuthMode::AuthToken;\n }\n previous_input.credential = Some(\"old-secret\".into());\n let previous = api.save_profile(previous_input).expect(\"previous profile\");\n let target = api\n .save_profile(claude_without_credential(\"Target\"))\n .expect(\"target profile\");\n repository\n .save_applied_state(&AppliedStateRecord {\n agent_id: \"claude-code\".into(),\n profile_id: Some(previous.id.clone()),\n projection_fingerprint: \"projection\".into(),\n live_fingerprint: \"live\".into(),\n drift_state: CliConfigDriftState::Applied,\n applied_at: \"2026-01-01T00:00:00Z\".into(),\n applied_payload: Some(previous.payload.clone()),\n managed_keys: previous.payload.managed_keys(),\n })\n .expect(\"applied state\");\n repository.fail_next_save.store(1, Ordering::SeqCst);\n\n let result = api\n .apply_profile(ApplyCliConfigProfileInput {\n agent_id: \"claude-code\".into(),\n profile_id: target.id,\n drift_resolution: Some(CliConfigDriftResolution::ImportCurrent),\n confirm_auth_file_replacement: false,\n })\n .expect(\"structured failure\");\n assert_eq!(result.status, \"failed\");\n assert!(result.restored);\n let restored = credentials\n .load(\"claude-code\", &previous.id)\n .expect(\"credential load\")\n .expect(\"restored credential\");\n assert_eq!(restored.as_str(), \"old-secret\");\n }\n\n #[test]\n fn startup_sync_bootstraps_an_exclusive_profile_once_without_rewriting_live() {\n let directory = tempfile::tempdir().expect(\"temporary home\");\n let settings_path = directory.path().join(\".claude\").join(\"settings.json\");\n std::fs::create_dir_all(settings_path.parent().expect(\"settings parent\"))\n .expect(\"create settings directory\");\n let live_bytes = br#\"{\"env\":{\"ANTHROPIC_BASE_URL\":\"https://external.example.com\",\"ANTHROPIC_MODEL\":\"claude-external\"}}\"#;\n std::fs::write(&settings_path, live_bytes).expect(\"write live settings\");\n let repository = Arc::new(MemoryRepository::default());\n let api = CliConfigApi::new(\n repository.clone(),\n Arc::new(MemoryCredentials::default()),\n Arc::new(NativeCliGlobalConfigAdapter::with_home(\n directory.path().to_path_buf(),\n )),\n Arc::new(NoopLog),\n );\n\n let first = api.synchronize_startup();\n let claude = first\n .iter()\n .find(|result| result.agent_id == \"claude-code\")\n .expect(\"claude startup result\");\n assert_eq!(claude.state, CliConfigStartupSyncState::Imported);\n assert_eq!(claude.imported, 1);\n let profiles = repository\n .list_profiles(\"claude-code\")\n .expect(\"list imported profiles\");\n assert_eq!(profiles.len(), 1);\n assert_eq!(profiles[0].id, \"claude-code-default\");\n assert_eq!(profiles[0].name, \"default\");\n assert_eq!(\n repository\n .applied_state(\"claude-code\")\n .expect(\"applied state\")\n .and_then(|state| state.profile_id),\n Some(\"claude-code-default\".into())\n );\n assert_eq!(\n std::fs::read(&settings_path).expect(\"read live\"),\n live_bytes\n );\n\n let second = api.synchronize_startup();\n assert_eq!(\n second\n .iter()\n .find(|result| result.agent_id == \"claude-code\")\n .expect(\"second claude result\")\n .state,\n CliConfigStartupSyncState::Skipped\n );\n assert_eq!(\n repository\n .list_profiles(\"claude-code\")\n .expect(\"list profiles after second startup\")\n .len(),\n 1\n );\n }\n\n #[test]\n fn startup_sync_upserts_opencode_by_provider_id_without_deleting_missing_profiles() {\n let directory = tempfile::tempdir().expect(\"temporary home\");\n let config_path = directory\n .path()\n .join(\".config\")\n .join(\"opencode\")\n .join(\"opencode.json\");\n std::fs::create_dir_all(config_path.parent().expect(\"config parent\"))\n .expect(\"create config directory\");\n std::fs::write(\n &config_path,\n r#\"{\"model\":\"deepseek/deepseek-chat\",\"provider\":{\"deepseek\":{\"name\":\"DeepSeek\",\"npm\":\"@ai-sdk/openai-compatible\",\"options\":{\"baseURL\":\"https://api.deepseek.com/v1\",\"apiKey\":\"startup-secret\"},\"models\":{\"deepseek-chat\":{\"name\":\"DeepSeek Chat\"}}}}}\"#,\n )\n .expect(\"write OpenCode config\");\n let repository = Arc::new(MemoryRepository::default());\n let credentials = Arc::new(MemoryCredentials::default());\n let api = CliConfigApi::new(\n repository.clone(),\n credentials.clone(),\n Arc::new(NativeCliGlobalConfigAdapter::with_home(\n directory.path().to_path_buf(),\n )),\n Arc::new(NoopLog),\n );\n\n let first = api.synchronize_startup();\n assert_eq!(\n first\n .iter()\n .find(|result| result.agent_id == \"opencode\")\n .expect(\"OpenCode startup result\")\n .imported,\n 1\n );\n let imported = repository\n .list_profiles(\"opencode\")\n .expect(\"OpenCode profiles\")\n .into_iter()\n .next()\n .expect(\"imported profile\");\n assert!(credentials\n .load(\"opencode\", &imported.id)\n .expect(\"credential lookup\")\n .is_some());\n\n std::fs::write(\n &config_path,\n r#\"{\"model\":\"deepseek/deepseek-reasoner\",\"provider\":{\"deepseek\":{\"name\":\"DeepSeek Updated\",\"npm\":\"@ai-sdk/openai-compatible\",\"options\":{\"baseURL\":\"https://api.deepseek.com/v2\",\"apiKey\":\"updated-secret\"},\"models\":{\"deepseek-reasoner\":{\"name\":\"DeepSeek Reasoner\"}}}}}\"#,\n )\n .expect(\"update OpenCode config\");\n let second = api.synchronize_startup();\n assert_eq!(\n second\n .iter()\n .find(|result| result.agent_id == \"opencode\")\n .expect(\"updated OpenCode result\")\n .updated,\n 1\n );\n let updated = repository\n .get_profile(\"opencode\", &imported.id)\n .expect(\"updated profile\");\n assert_eq!(updated.name, \"DeepSeek Updated\");\n assert!(matches!(\n updated.payload,\n CliConfigPayload::Opencode { ref base_url, ref default_model, .. }\n if base_url == \"https://api.deepseek.com/v2\" && default_model == \"deepseek-reasoner\"\n ));\n\n std::fs::write(&config_path, r#\"{\"provider\":{}}\"#).expect(\"remove live provider\");\n api.synchronize_startup();\n assert!(repository.get_profile(\"opencode\", &imported.id).is_ok());\n }\n\n #[test]\n fn exclusive_switch_backfills_external_live_changes_without_a_resolution_choice() {\n let directory = tempfile::tempdir().expect(\"temporary home\");\n let repository = Arc::new(MemoryRepository::default());\n let api = CliConfigApi::new(\n repository.clone(),\n Arc::new(MemoryCredentials::default()),\n Arc::new(NativeCliGlobalConfigAdapter::with_home(\n directory.path().to_path_buf(),\n )),\n Arc::new(NoopLog),\n );\n let previous = api\n .save_profile(claude_without_credential(\"Previous\"))\n .expect(\"previous profile\");\n let target = api\n .save_profile(claude_without_credential(\"Target\"))\n .expect(\"target profile\");\n assert_eq!(\n api.apply_profile(ApplyCliConfigProfileInput {\n agent_id: \"claude-code\".into(),\n profile_id: previous.id.clone(),\n drift_resolution: None,\n confirm_auth_file_replacement: false,\n })\n .expect(\"apply previous\")\n .status,\n \"succeeded\"\n );\n let settings_path = directory.path().join(\".claude\").join(\"settings.json\");\n std::fs::write(\n &settings_path,\n r#\"{\"env\":{\"ANTHROPIC_BASE_URL\":\"https://edited.example.com\",\"ANTHROPIC_MODEL\":\"claude-edited\"}}\"#,\n )\n .expect(\"external edit\");\n\n let switched = api\n .apply_profile(ApplyCliConfigProfileInput {\n agent_id: \"claude-code\".into(),\n profile_id: target.id,\n drift_resolution: None,\n confirm_auth_file_replacement: false,\n })\n .expect(\"switch after external edit\");\n assert_eq!(switched.status, \"succeeded\");\n assert_eq!(switched.backfilled_profile_id, Some(previous.id.clone()));\n assert_eq!(\n switched.drift_resolution,\n Some(CliConfigDriftResolution::ImportCurrent)\n );\n let stored = repository\n .get_profile(\"claude-code\", &previous.id)\n .expect(\"backfilled profile\");\n assert!(matches!(\n stored.payload,\n CliConfigPayload::ClaudeCode { ref base_url, ref model, .. }\n if base_url == \"https://edited.example.com\" && model == \"claude-edited\"\n ));\n }\n}\n"}}}}