1pub(crate) mod baseline;
4pub(crate) mod disposition;
5mod eval;
6pub(crate) mod fingerprint;
7pub(crate) mod reports;
8pub(crate) mod sarif;
9pub(crate) mod serializers;
10pub(crate) mod state;
11pub(crate) mod types;
12
13use crate::findings::{OperationalContext, RecommendedAction, Severity};
14
15pub use self::baseline::{BaselineEntry, BaselineFile, WaiverEntry, WaiverFile};
16pub use self::disposition::{
17 adjust_confidence, learned_allowlist, learned_confidence_adjustments, Disposition,
18 DispositionOverlay, DispositionRecord,
19};
20pub use self::fingerprint::finding_fingerprint;
21pub use self::reports::{JsonReport, PolicyGenerator};
22pub(crate) use self::sarif::{
23 SarifArtifactLocation, SarifConfiguration, SarifDriver, SarifLocation, SarifMessage,
24 SarifPhysicalLocation, SarifRegion, SarifReport, SarifResult, SarifRule, SarifRun, SarifTool,
25};
26pub use self::serializers::empty_sarif_report;
27pub use self::state::{
28 apply_baseline, apply_policy_overrides, apply_policy_overrides_with_audit, apply_waivers,
29 baseline_from_reports, count_baseline_matches, diff_reports, diff_reports_with_policy_state,
30 load_baseline, load_disposition_overlay, load_policy, load_waivers, validate_policy,
31 validate_waivers, PolicyLoadError,
32};
33pub(crate) use self::types::{default_policy_schema_version, empty_finding_summary};
34pub use self::types::{
35 AppliedPolicyOverride, ConfiguredProfile, ContextActionOverride, ContextPolicy, DiffEntry,
36 DiffReport, PolicyAudit, PolicyFile, PolicyOverride, PolicyProfile, PolicyProfiles,
37 ShieldPolicy, SuppressionSummary, POLICY_AUDIT_PRECEDENCE,
38};
39
40pub(crate) const POLICY_EXPIRY_DAYS: i64 = 365;
42pub const POLICY_SCHEMA_VERSION: &str = "skill-veil.dev/v1alpha1";
44
45impl PolicyProfile {
46 #[must_use]
47 pub fn default_fail_on(self) -> Option<Severity> {
48 match self {
49 Self::Personal => Some(Severity::Critical),
50 Self::Team => Some(Severity::High),
51 Self::Enterprise => Some(Severity::Medium),
52 Self::Research => None,
53 }
54 }
55
56 #[must_use]
57 pub fn default_action_for_context(self, context: OperationalContext) -> RecommendedAction {
58 match self {
59 Self::Personal => RecommendedAction::RequireApproval,
60 Self::Team => match context {
61 OperationalContext::Secrets => RecommendedAction::Block,
62 _ => RecommendedAction::RequireApproval,
63 },
64 Self::Enterprise => match context {
65 OperationalContext::Install
66 | OperationalContext::Secrets
67 | OperationalContext::ExternalComms => RecommendedAction::Block,
68 OperationalContext::Network | OperationalContext::CodeModification => {
69 RecommendedAction::RequireApproval
70 }
71 },
72 Self::Research => match context {
73 OperationalContext::Secrets | OperationalContext::ExternalComms => {
74 RecommendedAction::RequireApproval
75 }
76 _ => RecommendedAction::Log,
77 },
78 }
79 }
80}
81
82impl Default for PolicyFile {
83 fn default() -> Self {
84 Self {
85 schema_version: self::types::default_policy_schema_version(),
86 profiles: PolicyProfiles::default(),
87 overrides: Vec::new(),
88 }
89 }
90}
91
92impl PolicyFile {
93 #[must_use]
94 pub fn profile_config(&self, profile: PolicyProfile) -> Option<&ConfiguredProfile> {
95 match profile {
96 PolicyProfile::Personal => self.profiles.personal.as_ref(),
97 PolicyProfile::Team => self.profiles.team.as_ref(),
98 PolicyProfile::Enterprise => self.profiles.enterprise.as_ref(),
99 PolicyProfile::Research => self.profiles.research.as_ref(),
100 }
101 }
102
103 #[must_use]
104 pub fn resolve_fail_on(&self, profile: PolicyProfile) -> Option<Severity> {
105 self.profile_config(profile)
106 .and_then(|config| config.fail_on)
107 .or_else(|| profile.default_fail_on())
108 }
109
110 #[must_use]
111 pub fn resolve_context_action(
112 &self,
113 profile: PolicyProfile,
114 context: OperationalContext,
115 ) -> RecommendedAction {
116 self.profile_config(profile)
117 .and_then(|config| {
118 config
119 .context_actions
120 .iter()
121 .find(|entry| entry.context == context)
122 .map(|entry| entry.action)
123 })
124 .unwrap_or_else(|| profile.default_action_for_context(context))
125 }
126}
127
128impl Default for PolicyAudit {
129 fn default() -> Self {
130 Self {
131 precedence_order: POLICY_AUDIT_PRECEDENCE
132 .iter()
133 .map(|s| (*s).to_string())
134 .collect(),
135 effective_fail_on: None,
136 applied_overrides: Vec::new(),
137 }
138 }
139}
140
141pub(crate) fn context_label(context: OperationalContext) -> &'static str {
142 match context {
143 OperationalContext::Install => "install",
144 OperationalContext::Network => "network",
145 OperationalContext::Secrets => "secrets",
146 OperationalContext::CodeModification => "code_modification",
147 OperationalContext::ExternalComms => "external_comms",
148 }
149}
150
151pub(crate) fn severity_to_sarif_level(severity: Severity) -> &'static str {
152 match severity {
153 Severity::Critical | Severity::High => "error",
154 Severity::Medium => "warning",
155 Severity::Low => "note",
156 }
157}
158
159#[cfg(test)]
160mod tests_filtering;
161#[cfg(test)]
162mod tests_generation;