#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum PolicyPreset {
#[default]
Enterprise,
Strict,
Permissive,
Cra,
Ntia,
Fda,
NistSsdf,
Eo14028,
Cnsa2,
NistPqc,
}
impl PolicyPreset {
pub const fn next(self) -> Self {
match self {
Self::Enterprise => Self::Strict,
Self::Strict => Self::Permissive,
Self::Permissive => Self::Cra,
Self::Cra => Self::Ntia,
Self::Ntia => Self::Fda,
Self::Fda => Self::NistSsdf,
Self::NistSsdf => Self::Eo14028,
Self::Eo14028 => Self::Cnsa2,
Self::Cnsa2 => Self::NistPqc,
Self::NistPqc => Self::Enterprise,
}
}
pub const fn label(self) -> &'static str {
match self {
Self::Enterprise => "Enterprise",
Self::Strict => "Strict",
Self::Permissive => "Permissive",
Self::Cra => "EU CRA",
Self::Ntia => "NTIA",
Self::Fda => "FDA",
Self::NistSsdf => "NIST SSDF",
Self::Eo14028 => "EO 14028",
Self::Cnsa2 => "CNSA 2.0",
Self::NistPqc => "NIST PQC",
}
}
pub const fn is_standards_based(self) -> bool {
matches!(
self,
Self::Cra
| Self::Ntia
| Self::Fda
| Self::NistSsdf
| Self::Eo14028
| Self::Cnsa2
| Self::NistPqc
)
}
pub const fn compliance_level(self) -> Option<crate::quality::ComplianceLevel> {
match self {
Self::Cra => Some(crate::quality::ComplianceLevel::CraPhase2),
Self::Ntia => Some(crate::quality::ComplianceLevel::NtiaMinimum),
Self::Fda => Some(crate::quality::ComplianceLevel::FdaMedicalDevice),
Self::NistSsdf => Some(crate::quality::ComplianceLevel::NistSsdf),
Self::Eo14028 => Some(crate::quality::ComplianceLevel::Eo14028),
Self::Cnsa2 => Some(crate::quality::ComplianceLevel::Cnsa2),
Self::NistPqc => Some(crate::quality::ComplianceLevel::NistPqc),
_ => None,
}
}
}
#[derive(Debug, Clone, Default)]
pub struct PolicyComplianceState {
pub policy_preset: PolicyPreset,
pub result: Option<crate::tui::security::ComplianceResult>,
pub selected_violation: usize,
pub checked: bool,
pub show_details: bool,
}
impl PolicyComplianceState {
pub fn new() -> Self {
Self::default()
}
pub fn toggle_policy(&mut self) {
self.policy_preset = self.policy_preset.next();
self.result = None; self.checked = false;
}
pub const fn toggle_details(&mut self) {
self.show_details = !self.show_details;
}
pub fn passes(&self) -> bool {
self.result.as_ref().is_none_or(|r| r.passes)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ComplianceSeverityFilter {
#[default]
All,
ErrorsOnly,
WarningsAndAbove,
}
impl ComplianceSeverityFilter {
pub const fn next(self) -> Self {
match self {
Self::All => Self::ErrorsOnly,
Self::ErrorsOnly => Self::WarningsAndAbove,
Self::WarningsAndAbove => Self::All,
}
}
pub const fn label(self) -> &'static str {
match self {
Self::All => "All",
Self::ErrorsOnly => "Errors",
Self::WarningsAndAbove => "Warn+",
}
}
pub fn matches(self, severity: crate::quality::ViolationSeverity) -> bool {
match self {
Self::All => true,
Self::ErrorsOnly => {
matches!(severity, crate::quality::ViolationSeverity::Error)
}
Self::WarningsAndAbove => {
matches!(
severity,
crate::quality::ViolationSeverity::Error
| crate::quality::ViolationSeverity::Warning
)
}
}
}
}
#[derive(Debug, Clone)]
pub struct DiffComplianceState {
pub selected_standard: usize,
pub selected_violation: usize,
pub scroll_offset: usize,
pub view_mode: DiffComplianceViewMode,
pub show_detail: bool,
pub severity_filter: ComplianceSeverityFilter,
pub group_by_element: bool,
pub expanded_groups: std::collections::HashSet<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DiffComplianceViewMode {
Overview,
NewViolations,
ResolvedViolations,
OldViolations,
NewSbomViolations,
}
impl Default for DiffComplianceState {
fn default() -> Self {
Self {
selected_standard: 3,
selected_violation: 0,
scroll_offset: 0,
show_detail: false,
view_mode: DiffComplianceViewMode::Overview,
severity_filter: ComplianceSeverityFilter::default(),
group_by_element: false,
expanded_groups: std::collections::HashSet::new(),
}
}
}
impl DiffComplianceState {
pub fn new() -> Self {
Self::default()
}
pub const fn next_standard(&mut self) {
let count = crate::quality::ComplianceLevel::all().len();
self.selected_standard = (self.selected_standard + 1) % count;
self.selected_violation = 0;
self.scroll_offset = 0;
}
pub const fn prev_standard(&mut self) {
let count = crate::quality::ComplianceLevel::all().len();
self.selected_standard = if self.selected_standard == 0 {
count - 1
} else {
self.selected_standard - 1
};
self.selected_violation = 0;
self.scroll_offset = 0;
}
pub const fn next_view_mode(&mut self) {
self.view_mode = match self.view_mode {
DiffComplianceViewMode::Overview => DiffComplianceViewMode::NewViolations,
DiffComplianceViewMode::NewViolations => DiffComplianceViewMode::ResolvedViolations,
DiffComplianceViewMode::ResolvedViolations => DiffComplianceViewMode::OldViolations,
DiffComplianceViewMode::OldViolations => DiffComplianceViewMode::NewSbomViolations,
DiffComplianceViewMode::NewSbomViolations => DiffComplianceViewMode::Overview,
};
self.selected_violation = 0;
self.scroll_offset = 0;
}
pub const fn select_next(&mut self, max: usize) {
if max > 0 && self.selected_violation + 1 < max {
self.selected_violation += 1;
}
}
pub const fn select_prev(&mut self) {
if self.selected_violation > 0 {
self.selected_violation -= 1;
}
}
pub const fn toggle_severity_filter(&mut self) {
self.severity_filter = self.severity_filter.next();
self.selected_violation = 0;
self.scroll_offset = 0;
}
pub fn toggle_group_by_element(&mut self) {
self.group_by_element = !self.group_by_element;
self.selected_violation = 0;
self.scroll_offset = 0;
}
}