soma-som-core 0.1.0

Universal soma(som) structural primitives โ€” Quad / Tree / Ring / Genesis / Fingerprint / TemporalLedger / CrossingRecord
Documentation
// SPDX-License-Identifier: LGPL-3.0-only
#![allow(missing_docs)]

//! `GovernanceContext` โ€” boxed bundle of all seven governance trait objects.
//!
//! Injected into unit processors at startup via the extension registration API.
//! soma(som) ring foundation purity ยง3.

use std::sync::Arc;

use crate::authorization::{AuthorizationProvider, PermitAll};
use crate::autonomy::{AutonomyEvaluator, FullAutonomy};
use crate::configuration::{ConfigurationProvider, EmptyConfig};
use crate::evidence::{AcceptAll, EvidenceValidator};
use crate::process_engine::{LinearProcess, ProcessEngine};
use crate::process_gate::{NoGate, ProcessGate};
use crate::traceability::{CycleAnnotator, NullAnnotator};

/// Bundles the seven pluggable governance trait objects for injection.
///
/// All seven default to their no-op implementations. Concrete applications
/// replace any subset at startup by constructing a `GovernanceContext` with
/// their own impls.
pub struct GovernanceContext {
    pub authorization: Arc<dyn AuthorizationProvider>,
    pub autonomy: Arc<dyn AutonomyEvaluator>,
    pub configuration: Arc<dyn ConfigurationProvider>,
    pub process_gate: Arc<dyn ProcessGate>,
    pub evidence: Arc<dyn EvidenceValidator>,
    pub process_engine: Arc<dyn ProcessEngine>,
    pub cycle_annotator: Arc<dyn CycleAnnotator>,
}

impl Default for GovernanceContext {
    fn default() -> Self {
        Self {
            authorization: Arc::new(PermitAll),
            autonomy: Arc::new(FullAutonomy),
            configuration: Arc::new(EmptyConfig),
            process_gate: Arc::new(NoGate),
            evidence: Arc::new(AcceptAll),
            process_engine: Arc::new(LinearProcess),
            cycle_annotator: Arc::new(NullAnnotator),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::process_engine::ProcessStep;
    use crate::quad::Tree;

    fn tree() -> Tree { Tree::new() }

    #[test]
    fn permit_all_always_permits() {
        assert!(PermitAll.authorize(&tree(), 0).is_ok());
        assert!(PermitAll.authorize(&tree(), u64::MAX).is_ok());
    }

    #[test]
    fn full_autonomy_returns_255() {
        let d = FullAutonomy.evaluate(&tree());
        assert_eq!(d.effective_level, 255);
        assert!(d.limiting_factor.is_empty());
        assert!(!d.escalated);
    }

    #[test]
    fn empty_config_resolves_none() {
        assert!(EmptyConfig.resolve("any.key").is_none());
        assert!(EmptyConfig.resolve("").is_none());
    }

    #[test]
    fn accept_all_validates_ok() {
        assert!(AcceptAll.validate("any-gate", &tree()).is_ok());
    }

    #[test]
    fn no_gate_permits_transition() {
        assert!(NoGate.evaluate_transition(&tree()).is_ok());
    }

    #[test]
    fn linear_process_continues() {
        assert!(matches!(LinearProcess.step(&tree()), ProcessStep::Continue));
    }

    #[test]
    fn null_annotator_returns_empty() {
        assert!(NullAnnotator.annotate(&tree(), 0).is_empty());
    }

    #[test]
    fn governance_context_default_composes_all_seven() {
        let ctx = GovernanceContext::default();
        assert!(ctx.authorization.authorize(&tree(), 0).is_ok());
        let d = ctx.autonomy.evaluate(&tree());
        assert_eq!(d.effective_level, 255);
        assert!(ctx.configuration.resolve("x").is_none());
        assert!(ctx.process_gate.evaluate_transition(&tree()).is_ok());
        assert!(ctx.evidence.validate("g", &tree()).is_ok());
        assert!(matches!(ctx.process_engine.step(&tree()), ProcessStep::Continue));
        assert!(ctx.cycle_annotator.annotate(&tree(), 0).is_empty());
    }
}