cargo-allow 0.1.1

Source-tree exception ledger and policy scanner for Rust repositories.
use super::worklist_item_kind::{BROKEN_EVIDENCE_LINK, WEAK_EVIDENCE_REFERENCE};
use super::worklist_priority::{DIFFICULTY_SMALL, RISK_HIGH, RISK_MEDIUM};
use super::{WorkItem, WorkItemEvidenceReference, proof_commands};
use allow_core::{AllowConfig, AllowEntry, FindingKind, MatchStatus, normalize_path};
use allow_policy::{EvidenceReferenceDiagnostic, evidence_reference_diagnostics};
use std::path::Path;

pub(super) fn work_items_from_evidence_diagnostics(
    root: &Path,
    cfg: &AllowConfig,
    start_index: usize,
) -> Vec<WorkItem> {
    let mut items = Vec::new();
    for entry in &cfg.allow {
        for diagnostic in evidence_reference_diagnostics(root, entry)
            .into_iter()
            .filter(|diagnostic| {
                diagnostic.status.is_broken_local_link() || diagnostic.status.is_weak_reference()
            })
        {
            let item_index = start_index + items.len();
            items.push(work_item_from_evidence_diagnostic(
                entry, diagnostic, item_index,
            ));
        }
    }
    items
}

fn work_item_from_evidence_diagnostic(
    entry: &AllowEntry,
    diagnostic: EvidenceReferenceDiagnostic,
    item_index: usize,
) -> WorkItem {
    let kind = if diagnostic.status.is_weak_reference() {
        WEAK_EVIDENCE_REFERENCE
    } else {
        debug_assert!(diagnostic.status.is_broken_local_link());
        BROKEN_EVIDENCE_LINK
    };
    let proof_commands = proof_commands(kind, None, Some(entry));
    let path = if kind == BROKEN_EVIDENCE_LINK {
        diagnostic.target.as_ref().map(normalize_path)
    } else {
        None
    };
    let evidence_reference = WorkItemEvidenceReference {
        raw: diagnostic.raw.clone(),
        prefix: diagnostic.prefix.clone(),
        target: diagnostic.target.as_ref().map(normalize_path),
        status: diagnostic.status.as_str().to_string(),
        message: diagnostic.message.clone(),
    };
    WorkItem {
        id: format!("work-{}-{item_index:04}", kind.replace('_', "-")),
        kind: kind.to_string(),
        exception_kind: Some(entry.kind.as_str().to_string()),
        family: entry.family.clone(),
        owner: Some(entry.owner.clone()),
        classification: Some(entry.classification.clone()),
        reason: Some(entry.reason.clone()),
        created: entry.lifecycle.created.clone(),
        review_after: entry.lifecycle.review_after.clone(),
        expires: entry.lifecycle.expires.clone(),
        evidence_count: Some(entry.evidence.len()),
        risk: if entry.kind == FindingKind::Unsafe {
            RISK_HIGH
        } else {
            RISK_MEDIUM
        },
        difficulty: DIFFICULTY_SMALL,
        status: MatchStatus::EvidenceMissing,
        allow_id: Some(entry.id.clone()),
        finding_index: None,
        path,
        evidence_reference: Some(evidence_reference),
        source_package: None,
        message: format!(
            "{} evidence `{}`: {}",
            entry.id, diagnostic.raw, diagnostic.message
        ),
        suggested_actions: super::suggested_actions(kind),
        proof_commands,
    }
}