Skip to main content

copybook_governance/
lib.rs

1#![cfg_attr(not(test), deny(clippy::unwrap_used, clippy::expect_used))]
2// SPDX-License-Identifier: AGPL-3.0-or-later
3//! Governance contracts and runtime interoperability for copybook-rs feature controls.
4//!
5//! This crate is the canonical compatibility façade for:
6//! - Runtime feature flags and support-matrix rows (`copybook-governance-contracts`).
7//! - Static governance bindings between support rows and feature flags (`copybook-governance-grid`).
8//! - Runtime evaluation of those bindings (`copybook-governance-runtime`).
9
10/// Re-exported feature flag types from the governance grid.
11pub mod feature_flags {
12    pub use copybook_governance_grid::feature_flags::*;
13}
14
15/// Re-exported support matrix types from the governance grid.
16pub mod support_matrix {
17    pub use copybook_governance_grid::support_matrix::*;
18}
19
20pub use feature_flags::{
21    Feature, FeatureCategory, FeatureFlags, FeatureFlagsBuilder, FeatureFlagsHandle,
22    FeatureLifecycle,
23};
24pub use support_matrix::{FeatureId, FeatureSupport, SupportStatus};
25
26pub use copybook_governance_grid::{
27    GovernanceSummary, GovernedFeatureBinding, feature_flags_for_support_id, governance_bindings,
28    summarize_governance,
29};
30
31pub use copybook_governance_runtime::{
32    FeatureGovernanceState, FeatureGovernanceSummary, governance_state_for_support_id,
33    governance_states, is_support_runtime_available, runtime_summary, support_states,
34};
35
36#[cfg(test)]
37#[allow(clippy::expect_used)]
38#[allow(clippy::unwrap_used)]
39mod tests {
40    use super::*;
41
42    #[test]
43    fn test_facade_feature_flags_default() {
44        let flags = FeatureFlags::default();
45        assert!(flags.is_enabled(Feature::SignSeparate));
46        assert!(flags.is_enabled(Feature::Comp1));
47        assert!(flags.is_enabled(Feature::Comp2));
48        assert!(flags.is_enabled(Feature::LruCache));
49    }
50
51    #[test]
52    fn test_facade_builder_enable_disable() {
53        let flags = FeatureFlags::builder()
54            .enable(Feature::Profiling)
55            .disable(Feature::LruCache)
56            .build();
57        assert!(flags.is_enabled(Feature::Profiling));
58        assert!(!flags.is_enabled(Feature::LruCache));
59    }
60
61    #[test]
62    fn test_facade_support_matrix_lookup() {
63        let f = support_matrix::find_feature_by_id(FeatureId::EditedPic);
64        assert!(f.is_some());
65        assert_eq!(f.unwrap().status, SupportStatus::Supported);
66    }
67
68    #[test]
69    fn test_facade_governance_bindings_nonempty() {
70        let bindings = governance_bindings();
71        assert!(!bindings.is_empty());
72        assert_eq!(bindings.len(), 7);
73    }
74
75    #[test]
76    fn test_facade_feature_flags_for_support_id() {
77        let flags = feature_flags_for_support_id(FeatureId::Comp1Comp2).unwrap();
78        assert_eq!(flags.len(), 2);
79    }
80
81    #[test]
82    fn test_facade_summarize_governance() {
83        let summary = summarize_governance();
84        assert!(summary.all_features_known());
85        assert_eq!(summary.total_support_features, 7);
86    }
87
88    #[test]
89    fn test_facade_governance_states_nonempty() {
90        let flags = FeatureFlags::default();
91        let states = governance_states(&flags);
92        assert!(!states.is_empty());
93    }
94
95    #[test]
96    fn test_facade_runtime_summary_totals() {
97        let flags = FeatureFlags::default();
98        let summary = runtime_summary(&flags);
99        assert_eq!(summary.total_support_features, 7);
100        assert_eq!(summary.mapped_support_features, 7);
101        assert!(summary.all_support_rows_present());
102    }
103
104    #[test]
105    fn test_facade_is_support_runtime_available() {
106        let flags = FeatureFlags::default();
107        assert!(is_support_runtime_available(
108            FeatureId::SignSeparate,
109            &flags
110        ));
111        assert!(is_support_runtime_available(
112            FeatureId::Level88Conditions,
113            &flags
114        ));
115    }
116
117    #[test]
118    fn test_facade_support_states_nonempty() {
119        let states = support_states();
120        assert_eq!(states.len(), 7);
121        for state in &states {
122            assert!(state.runtime_enabled);
123        }
124    }
125
126    #[test]
127    fn test_facade_end_to_end_governance_flow() {
128        // Build flags with specific configuration
129        let flags = FeatureFlags::builder()
130            .disable(Feature::Comp1)
131            .disable(Feature::Comp2)
132            .build();
133
134        // Check specific governance state
135        let state = governance_state_for_support_id(FeatureId::Comp1Comp2, &flags).unwrap();
136        assert!(!state.runtime_enabled);
137        assert_eq!(state.missing_feature_flags.len(), 2);
138
139        // Check overall summary
140        let summary = runtime_summary(&flags);
141        assert!(summary.has_runtime_unavailable_features());
142        assert!(summary.runtime_disabled_features >= 1);
143    }
144
145    #[test]
146    fn test_facade_feature_lifecycle_accessible() {
147        let _ = FeatureLifecycle::Experimental;
148        let _ = FeatureLifecycle::Stable;
149        let _ = FeatureLifecycle::Deprecated;
150    }
151
152    #[test]
153    fn test_facade_handle_roundtrip() {
154        let handle = FeatureFlagsHandle::new();
155        handle.enable(Feature::AdvancedOptimization);
156        assert!(handle.is_enabled(Feature::AdvancedOptimization));
157        let snap = handle.snapshot();
158        assert!(snap.is_enabled(Feature::AdvancedOptimization));
159    }
160}