allow-report 0.1.8

Report and receipt rendering for cargo-allow source exception scans.
Documentation
use super::*;

#[test]
fn propose_json_renderer_records_options_summary_and_defaults() {
    let report = ProposeReport {
        inventory: InventoryContext::source_syntax(
            "git_tracked",
            Some("H:/Code/Rust/cargo-allow"),
            Some(76),
        ),
        kind: Some("panic"),
        expires: "2026-08-02",
        policy_output: Some("target/cargo-allow/proposed.toml"),
        force: true,
        findings_scanned: 54,
        baseline_debt_entries_proposed: 2,
        unsafe_baseline_debt_entries_proposed: 1,
    };

    let json = render_propose_json(report);

    assert!(json.contains("\"schema_id\": \"cargo-allow.propose.v1\""));
    assert!(json.contains("\"command\": \"propose\""));
    assert!(json.contains("\"source\": \"git_tracked\""));
    assert!(json.contains("\"files_scanned\": 76"));
    assert!(json.contains("\"kind\": \"panic\""));
    assert!(json.contains("\"expires\": \"2026-08-02\""));
    assert!(json.contains("\"policy_output\": \"target/cargo-allow/proposed.toml\""));
    assert!(json.contains("\"force\": true"));
    assert!(json.contains("\"findings_scanned\": 54"));
    assert!(json.contains("\"baseline_debt_entries_proposed\": 2"));
    assert!(json.contains("\"unsafe_baseline_debt_entries_proposed\": 1"));
    assert!(json.contains("\"follow_up_queues\""));
    assert!(json.contains("\"signal\": \"baseline_debt_entries_proposed\""));
    assert!(json.contains("\"label\": \"baseline debt entries\""));
    assert!(json.contains("\"route_kind\": \"worklist_filter\""));
    assert!(json.contains("\"item_kind\": \"baseline_debt\""));
    assert!(json.contains("\"worklist_filter\": \"baseline_debt\""));
    assert!(json.contains("\"command\": \"cargo-allow worklist --baseline-debt --format json\""));
    assert!(json.contains("\"signal\": \"unsafe_baseline_debt_entries_proposed\""));
    assert!(json.contains("\"label\": \"unsafe baseline debt entries\""));
    assert!(json.contains("\"route_kind\": \"worklist_item_kind\""));
    assert!(json.contains("\"item_kind\": \"weak_evidence_reference\""));
    assert!(json.contains(
        "\"command\": \"cargo-allow worklist --item-kind weak_evidence_reference --kind unsafe --format json\""
    ));
    assert!(json.contains("\"owner\": \"unowned\""));
    assert!(json.contains("\"classification\": \"baseline_debt\""));
    let expected = format!(
        r#"{{
  "schema_version": 1,
  "schema_id": "cargo-allow.propose.v1",
  "tool": "cargo-allow",
  "command": "propose",
  "claim_boundary": {},
  "scanner_limitations": {},
  "inventory": {{
    "scope": "source_tree",
    "scanner": "source_syntax",
    "source": "git_tracked",
    "root": "H:/Code/Rust/cargo-allow",
    "files_scanned": 76
  }},
  "options": {{
    "kind": "panic",
    "expires": "2026-08-02",
    "policy_output": "target/cargo-allow/proposed.toml",
    "force": true
  }},
  "summary": {{
    "findings_scanned": 54,
    "baseline_debt_entries_proposed": 2,
    "unsafe_baseline_debt_entries_proposed": 1
  }},
  "follow_up_queues": [
    {{
      "signal": "baseline_debt_entries_proposed",
      "label": "baseline debt entries",
      "route_kind": "worklist_filter",
      "item_kind": "baseline_debt",
      "worklist_filter": "baseline_debt",
      "count": 2,
      "command": "cargo-allow worklist --baseline-debt --format json"
    }},
    {{
      "signal": "unsafe_baseline_debt_entries_proposed",
      "label": "unsafe baseline debt entries",
      "route_kind": "worklist_item_kind",
      "item_kind": "weak_evidence_reference",
      "count": 1,
      "command": "cargo-allow worklist --item-kind weak_evidence_reference --kind unsafe --format json"
    }}
  ],
  "generated_entry_defaults": {{
    "owner": "unowned",
    "classification": "baseline_debt",
    "reason": "Generated by cargo-allow propose; requires human review.",
    "expires": "2026-08-02"
  }}
}}
"#,
        render_claim_boundary_json(),
        render_scanner_limitations_json()
    );
    assert_eq!(json, expected);

    let text = render_propose_human(report);

    assert!(text.contains("cargo-allow propose summary"));
    assert!(
        text.contains("inventory: source_tree/source_syntax via git_tracked; files scanned: 76")
    );
    assert!(text.contains("source_tree_root: H:/Code/Rust/cargo-allow"));
    assert!(text.contains("kind filter: panic"));
    assert!(text.contains("findings scanned: 54"));
    assert!(text.contains("baseline_debt entries proposed: 2"));
    assert!(text.contains("unsafe baseline_debt entries proposed: 1"));
    assert!(text.contains("owner: unowned"));
    assert!(text.contains("classification: baseline_debt"));
    assert!(text.contains("expires: 2026-08-02"));
    assert!(text.contains("output: target/cargo-allow/proposed.toml"));
    assert!(text.contains("follow_up_queues:"));
    assert!(text.contains("cargo-allow worklist --baseline-debt --format json"));
    assert!(text.contains(
        "cargo-allow worklist --item-kind weak_evidence_reference --kind unsafe --format json"
    ));
    assert!(text.contains("generated debt still requires human review"));
    assert!(text.contains("Claim boundary: scanned source-tree/source syntax only"));
}

#[test]
fn propose_renderer_omits_follow_up_queues_when_nothing_proposed() {
    let report = ProposeReport {
        inventory: InventoryContext::source_syntax("git_tracked", None, Some(12)),
        kind: None,
        expires: "2026-08-02",
        policy_output: None,
        force: false,
        findings_scanned: 12,
        baseline_debt_entries_proposed: 0,
        unsafe_baseline_debt_entries_proposed: 0,
    };

    let json = render_propose_json(report);
    let text = render_propose_human(report);

    assert!(!json.contains("\"follow_up_queues\""));
    assert!(!text.contains("follow_up_queues:"));
}