allow_report/
diff_human.rs1use crate::diff_policy_detail::policy_change_detail;
2use crate::diff_posture::{diff_net_posture, diff_posture_summary};
3use crate::{DiffFindingChange, DiffPolicyChange};
4
5pub fn render_diff_posture_summary_human(
6 current_failures: usize,
7 finding_changes: &[DiffFindingChange<'_>],
8 policy_changes: &[DiffPolicyChange<'_>],
9) -> String {
10 let summary = diff_posture_summary(current_failures, finding_changes, policy_changes);
11 let posture = diff_net_posture(summary);
12 let mut out = String::new();
13 out.push_str("\nDiff posture summary:\n");
14 out.push_str(&format!(" net_posture: {}\n", posture.as_str()));
15 out.push_str(&format!(
16 " reviewer_action: {}\n",
17 posture.reviewer_action()
18 ));
19 out.push_str(&format!(
20 " current_check_failures: {}\n",
21 summary.current_failures
22 ));
23 out.push_str(&format!(
24 " new_source_findings: {}\n",
25 summary.new_findings
26 ));
27 out.push_str(&format!(
28 " removed_source_findings: {}\n",
29 summary.removed_findings
30 ));
31 out.push_str(&format!(" policy_failures: {}\n", summary.policy_failures));
32 out.push_str(&format!(
33 " policy_review_items: {}\n",
34 summary.policy_review_items
35 ));
36 out.push_str(&format!(
37 " policy_improvements: {}\n",
38 summary.policy_improvements
39 ));
40 out
41}
42
43pub fn render_diff_finding_changes_human(changes: &[DiffFindingChange<'_>]) -> String {
44 let mut out = String::new();
45 out.push_str("\nFinding posture changes:\n");
46 if changes.is_empty() {
47 out.push_str(" none\n");
48 return out;
49 }
50 for change in changes.iter().take(120) {
51 out.push_str(&format!(
52 " {} {}{} at {}\n",
53 change.change,
54 change.kind,
55 change
56 .family
57 .map(|family| format!(".{family}"))
58 .unwrap_or_default(),
59 change.path
60 ));
61 }
62 if changes.len() > 120 {
63 out.push_str(&format!(" ... {} more omitted\n", changes.len() - 120));
64 }
65 out
66}
67
68pub fn render_diff_policy_changes_human(changes: &[DiffPolicyChange<'_>]) -> String {
69 let mut out = String::new();
70 out.push_str("\nPolicy posture changes:\n");
71 if changes.is_empty() {
72 out.push_str(" none\n");
73 return out;
74 }
75 for change in changes {
76 out.push_str(&format!(
77 " {} {} {}: {}\n",
78 change.severity, change.allow_id, change.kind, change.message
79 ));
80 if let Some(detail) = policy_change_detail(change) {
81 out.push_str(&format!(" detail: {detail}\n"));
82 }
83 }
84 out
85}