Skip to main content

systemprompt_traits/
domain_config.rs

1//! Per-domain configuration loading and validation.
2//!
3//! Each domain crate registers a [`DomainConfig`] implementation in the
4//! [`DomainConfigRegistry`]; the runtime walks the registry at startup,
5//! ordered by [`DomainConfig::priority`], to load and validate domain
6//! configuration.
7
8use std::fmt::Debug;
9
10use crate::context::ConfigProvider;
11use crate::validation_report::ValidationReport;
12
13#[derive(Debug, thiserror::Error)]
14#[non_exhaustive]
15pub enum DomainConfigError {
16    #[error("Failed to load config: {0}")]
17    LoadError(String),
18
19    #[error("Config file not found: {0}")]
20    NotFound(String),
21
22    #[error("Failed to parse config: {0}")]
23    ParseError(String),
24
25    #[error("Validation failed: {0}")]
26    ValidationError(String),
27
28    #[error(transparent)]
29    Other(#[from] anyhow::Error),
30}
31
32pub trait DomainConfig: Send + Sync + Debug {
33    fn domain_id(&self) -> &'static str;
34
35    fn load(&mut self, config: &dyn ConfigProvider) -> Result<(), DomainConfigError>;
36
37    fn validate(&self) -> Result<ValidationReport, DomainConfigError>;
38
39    fn dependencies(&self) -> &[&'static str] {
40        &[]
41    }
42
43    fn priority(&self) -> u32 {
44        100
45    }
46}
47
48pub struct DomainConfigRegistry {
49    validators: Vec<Box<dyn DomainConfig>>,
50}
51
52impl DomainConfigRegistry {
53    #[must_use]
54    pub fn new() -> Self {
55        Self {
56            validators: Vec::new(),
57        }
58    }
59
60    pub fn register(&mut self, validator: Box<dyn DomainConfig>) {
61        self.validators.push(validator);
62    }
63
64    pub fn validators_sorted(&self) -> Vec<&dyn DomainConfig> {
65        let mut validators: Vec<_> = self.validators.iter().map(AsRef::as_ref).collect();
66        validators.sort_by_key(|v| v.priority());
67        validators
68    }
69
70    pub fn validators_mut(&mut self) -> impl Iterator<Item = &mut Box<dyn DomainConfig>> {
71        self.validators.sort_by_key(|v| v.priority());
72        self.validators.iter_mut()
73    }
74}
75
76impl Default for DomainConfigRegistry {
77    fn default() -> Self {
78        Self::new()
79    }
80}
81
82impl Debug for DomainConfigRegistry {
83    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84        f.debug_struct("DomainConfigRegistry")
85            .field("validator_count", &self.validators.len())
86            .finish()
87    }
88}