#![cfg_attr(not(test), deny(clippy::unwrap_used, clippy::expect_used))]
pub mod feature_flags {
pub use copybook_governance_grid::feature_flags::*;
}
pub mod support_matrix {
pub use copybook_governance_grid::support_matrix::*;
}
use serde::Serialize;
pub use copybook_governance_grid::{
GovernanceSummary, GovernedFeatureBinding, feature_flags_for_support_id, governance_bindings,
summarize_governance,
};
pub use feature_flags::{
Feature, FeatureCategory, FeatureFlags, FeatureFlagsBuilder, FeatureFlagsHandle,
FeatureLifecycle,
};
pub use support_matrix::{FeatureId, FeatureSupport, SupportStatus};
#[derive(Debug, Clone, Serialize)]
#[non_exhaustive]
pub struct FeatureGovernanceState {
pub support_id: FeatureId,
pub support_name: &'static str,
pub support_description: &'static str,
pub support_status: SupportStatus,
pub doc_ref: Option<&'static str>,
pub rationale: &'static str,
pub required_feature_flags: &'static [Feature],
pub missing_feature_flags: Vec<Feature>,
pub runtime_enabled: bool,
}
impl FeatureGovernanceState {
#[inline]
#[must_use]
pub fn from_support(feature: &'static FeatureSupport) -> Self {
Self {
support_id: feature.id,
support_name: feature.name,
support_description: feature.description,
support_status: feature.status,
doc_ref: feature.doc_ref,
rationale: "No runtime governance mapping requested.",
required_feature_flags: &[],
missing_feature_flags: Vec::new(),
runtime_enabled: true,
}
}
}
#[derive(Debug, Clone, Copy, Serialize)]
#[non_exhaustive]
pub struct FeatureGovernanceSummary {
pub total_support_features: usize,
pub mapped_support_features: usize,
pub total_linked_feature_flags: usize,
pub runtime_enabled_features: usize,
pub runtime_disabled_features: usize,
}
impl FeatureGovernanceSummary {
#[inline]
#[must_use]
pub const fn all_support_rows_present(&self) -> bool {
self.total_support_features == self.mapped_support_features
}
#[inline]
#[must_use]
pub const fn has_runtime_unavailable_features(&self) -> bool {
self.runtime_disabled_features > 0
}
}
#[inline]
#[must_use]
pub fn support_states() -> Vec<FeatureGovernanceState> {
support_matrix::all_features()
.iter()
.map(FeatureGovernanceState::from_support)
.collect()
}
#[inline]
#[must_use]
pub fn governance_states(feature_flags: &FeatureFlags) -> Vec<FeatureGovernanceState> {
governance_bindings()
.iter()
.filter_map(|binding| governance_state_for_support_id(binding.support_id, feature_flags))
.collect()
}
#[inline]
#[must_use]
pub fn governance_state_for_support_id(
support_id: FeatureId,
feature_flags: &FeatureFlags,
) -> Option<FeatureGovernanceState> {
let binding = governance_bindings()
.iter()
.find(|entry| entry.support_id == support_id)?;
let support = support_matrix::find_feature_by_id(support_id)?;
let mut missing_feature_flags = Vec::new();
for flag in binding.feature_flags {
if !feature_flags.is_enabled(*flag) {
missing_feature_flags.push(*flag);
}
}
let runtime_enabled = missing_feature_flags.is_empty();
Some(FeatureGovernanceState {
support_id,
support_name: support.name,
support_description: support.description,
support_status: support.status,
doc_ref: support.doc_ref,
rationale: binding.rationale,
required_feature_flags: binding.feature_flags,
missing_feature_flags,
runtime_enabled,
})
}
#[inline]
#[must_use]
pub fn is_support_runtime_available(support_id: FeatureId, feature_flags: &FeatureFlags) -> bool {
governance_state_for_support_id(support_id, feature_flags)
.is_some_and(|state| state.runtime_enabled)
}
#[inline]
#[must_use]
pub fn runtime_summary(feature_flags: &FeatureFlags) -> FeatureGovernanceSummary {
let base = summarize_governance();
let states = governance_states(feature_flags);
let runtime_enabled_features = states.iter().filter(|state| state.runtime_enabled).count();
FeatureGovernanceSummary {
total_support_features: base.total_support_features,
mapped_support_features: base.mapped_support_features,
total_linked_feature_flags: base.total_linked_feature_flags,
runtime_enabled_features,
runtime_disabled_features: states.len().saturating_sub(runtime_enabled_features),
}
}
#[cfg(test)]
#[allow(clippy::expect_used)]
#[allow(clippy::unwrap_used)]
mod tests {
use super::*;
#[test]
fn test_support_states_nonempty() {
let states = support_states();
assert!(!states.is_empty());
assert!(states.iter().all(|state| state.runtime_enabled));
}
#[test]
fn test_runtime_state_for_supported_feature() {
let flags = FeatureFlags::default();
let state = governance_state_for_support_id(FeatureId::Comp1Comp2, &flags)
.expect("state should exist for mapped feature");
assert_eq!(state.support_id, FeatureId::Comp1Comp2);
assert!(state.runtime_enabled);
assert_eq!(state.required_feature_flags.len(), 2);
}
#[test]
fn test_runtime_state_reports_missing_feature_flags() {
let flags = FeatureFlags::builder()
.disable(Feature::Comp1)
.disable(Feature::Comp2)
.build();
let state = governance_state_for_support_id(FeatureId::Comp1Comp2, &flags)
.expect("state should exist for mapped feature");
assert!(!state.runtime_enabled);
assert_eq!(state.missing_feature_flags.len(), 2);
}
#[test]
fn test_runtime_summary_counts() {
let flags = FeatureFlags::builder()
.disable(Feature::SignSeparate)
.build();
let summary = runtime_summary(&flags);
assert!(summary.total_support_features >= 1);
assert!(summary.mapped_support_features <= summary.total_support_features);
assert!(summary.runtime_enabled_features <= summary.total_support_features);
}
#[test]
fn test_is_support_runtime_available() {
let flags = FeatureFlags::builder()
.enable(Feature::SignSeparate)
.disable(Feature::Comp1)
.build();
assert!(is_support_runtime_available(
FeatureId::SignSeparate,
&flags
));
assert!(!is_support_runtime_available(FeatureId::Comp1Comp2, &flags));
}
#[test]
fn test_support_id_lookup() {
assert!(support_matrix::find_feature_by_id(FeatureId::Level88Conditions).is_some());
assert!(support_matrix::find_feature_by_id(FeatureId::NestedOdo).is_some());
assert!(support_matrix::find_feature_by_id(FeatureId::SignSeparate).is_some());
}
#[test]
fn test_support_states_count_matches_all_features() {
let states = support_states();
assert_eq!(states.len(), support_matrix::all_features().len());
}
#[test]
fn test_support_states_all_have_empty_required_flags() {
for state in support_states() {
assert!(
state.required_feature_flags.is_empty(),
"support_states should have no required flags for {:?}",
state.support_id
);
assert!(state.missing_feature_flags.is_empty());
}
}
#[test]
fn test_governance_states_with_all_defaults() {
let flags = FeatureFlags::default();
let states = governance_states(&flags);
assert!(!states.is_empty());
let renames_state = states
.iter()
.find(|s| s.support_id == FeatureId::Level66Renames)
.expect("Level66Renames should be in governance states");
assert!(!renames_state.runtime_enabled);
}
#[test]
fn test_governance_states_with_all_features_enabled() {
let mut flags = FeatureFlags::default();
for feature in feature_flags::all_features() {
flags.enable(feature);
}
let states = governance_states(&flags);
for state in &states {
assert!(
state.runtime_enabled,
"{:?} should be runtime enabled when all flags on",
state.support_id
);
assert!(state.missing_feature_flags.is_empty());
}
}
#[test]
fn test_governance_states_with_all_features_disabled() {
let mut flags = FeatureFlags::default();
for feature in feature_flags::all_features() {
flags.disable(feature);
}
let states = governance_states(&flags);
for state in &states {
if !state.required_feature_flags.is_empty() {
assert!(
!state.runtime_enabled,
"{:?} should be disabled when all flags off",
state.support_id
);
}
}
}
#[test]
fn test_runtime_summary_with_all_enabled() {
let mut flags = FeatureFlags::default();
for feature in feature_flags::all_features() {
flags.enable(feature);
}
let summary = runtime_summary(&flags);
assert!(!summary.has_runtime_unavailable_features());
assert_eq!(summary.runtime_disabled_features, 0);
assert_eq!(
summary.runtime_enabled_features,
summary.mapped_support_features
);
}
#[test]
fn test_runtime_summary_all_support_rows_present() {
let flags = FeatureFlags::default();
let summary = runtime_summary(&flags);
assert!(summary.all_support_rows_present());
assert_eq!(summary.total_support_features, 7);
assert_eq!(summary.mapped_support_features, 7);
}
#[test]
fn test_from_support_sets_no_governance_rationale() {
let feature = support_matrix::find_feature_by_id(FeatureId::EditedPic).unwrap();
let state = FeatureGovernanceState::from_support(feature);
assert_eq!(state.rationale, "No runtime governance mapping requested.");
assert!(state.runtime_enabled);
assert!(state.required_feature_flags.is_empty());
assert!(state.missing_feature_flags.is_empty());
}
#[test]
fn test_governance_state_for_support_id_preserves_metadata() {
let flags = FeatureFlags::default();
let state = governance_state_for_support_id(FeatureId::SignSeparate, &flags).unwrap();
assert_eq!(state.support_id, FeatureId::SignSeparate);
assert!(!state.support_name.is_empty());
assert!(!state.support_description.is_empty());
assert!(state.doc_ref.is_some());
assert!(!state.rationale.is_empty());
}
#[test]
fn test_is_support_runtime_available_for_ungoverned_feature() {
let flags = FeatureFlags::default();
let state = governance_state_for_support_id(FeatureId::Level88Conditions, &flags).unwrap();
assert!(state.runtime_enabled);
assert!(state.required_feature_flags.is_empty());
}
#[test]
fn test_runtime_summary_disabled_count_matches_expectations() {
let flags = FeatureFlags::builder()
.disable(Feature::SignSeparate)
.disable(Feature::Comp1)
.disable(Feature::Comp2)
.build();
let summary = runtime_summary(&flags);
assert!(summary.runtime_disabled_features >= 3);
assert!(summary.has_runtime_unavailable_features());
}
}