refactor(config): generate scalar validation boundaries
This commit is contained in:
1 parent
afafd126d7
commit
8134235f48
29 files changed
+1008
-480
No files matched your search
@@ -22,4 +22,4 @@ pub use field::{
|
||||
pub use kaptan_config_derive::ConfigValidate;
|
||||
pub use lifecycle::{BeginError, CommitError, ConfigManager, ConfigState, SetError, StartupError};
|
||||
pub use storage::{Generation, ProfileStore};
|
||||
pub use validation::ValidateFields;
|
||||
pub use validation::{ConfigAggregate, ConfigSection, ValidateFields};
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Local scalar validation implemented by the configuration derive macro.
|
||||
//! Local scalar configuration sections implemented by the derive macro.
|
||||
|
||||
use crate::ConfigViolation;
|
||||
use crate::{ConfigValue, ConfigViolation, FieldId, FieldWriteError};
|
||||
|
||||
/// Validates local scalar invariants of one record.
|
||||
///
|
||||
@@ -11,3 +11,53 @@ pub trait ValidateFields {
|
||||
/// Rejects the first violated scalar or declared post-validation rule.
|
||||
fn validate_fields(&self) -> Result<(), ConfigViolation>;
|
||||
}
|
||||
|
||||
/// A complete scalar configuration section generated from `#[config(...)]`
|
||||
/// field attributes.
|
||||
///
|
||||
/// Its metadata, default construction, reads, local writes, and scalar
|
||||
/// validation are all produced from the same field declarations. A section
|
||||
/// setter never commits a locally invalid value. Cross-section and capability
|
||||
/// invariants deliberately remain the aggregate candidate's responsibility.
|
||||
pub trait ConfigSection: ValidateFields {
|
||||
/// Number of scalar descriptors generated for this section.
|
||||
const FIELD_COUNT: usize;
|
||||
|
||||
/// Builds the section from derive-generated defaults after validating it.
|
||||
fn default_section() -> Result<Self, ConfigViolation>
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
/// Returns one scalar by stable field identity.
|
||||
fn field_value(&self, id: FieldId) -> Option<ConfigValue>;
|
||||
|
||||
/// Applies one scalar only when this section owns the ID and its local
|
||||
/// generated validation accepts the new value.
|
||||
fn set_field(&mut self, id: FieldId, value: ConfigValue) -> Result<(), FieldWriteError>;
|
||||
|
||||
/// Validates only generated scalar invariants. This intentionally omits
|
||||
/// a derive `post` hook so staged multi-field edits can remain temporarily
|
||||
/// cross-field-invalid until aggregate validation/commit.
|
||||
fn validate_local_fields(&self) -> Result<(), ConfigViolation>;
|
||||
}
|
||||
|
||||
/// An ordered aggregate of generated configuration sections.
|
||||
///
|
||||
/// The derive owns routing/default construction so adding a field to an
|
||||
/// existing section cannot silently bypass local validation. The aggregate
|
||||
/// owner still defines capability checks and immutable active construction.
|
||||
pub trait ConfigAggregate: ValidateFields {
|
||||
/// Builds and fully validates all nested sections from their derived
|
||||
/// defaults.
|
||||
fn default_aggregate() -> Result<Self, ConfigViolation>
|
||||
where
|
||||
Self: Sized;
|
||||
|
||||
/// Returns one nested scalar by stable field identity.
|
||||
fn field_value(&self, id: FieldId) -> Option<ConfigValue>;
|
||||
|
||||
/// Routes one scalar write to its owning generated section. The setter
|
||||
/// applies local validation only, so a transaction may temporarily hold a
|
||||
/// cross-field-invalid multi-edit candidate.
|
||||
fn set_field(&mut self, id: FieldId, value: ConfigValue) -> Result<(), FieldWriteError>;
|
||||
}
|
||||
Reference in new issue
Block a user