Skip to main content

allow_report/
diff_human.rs

1use 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}