Skip to main content

chio_workflow_preflight/
lib.rs

1//! Read-only workflow preflight validation.
2
3mod scope;
4mod types;
5mod validation;
6
7pub use types::{
8    WorkflowApprovalPreflight, WorkflowBudgetPool, WorkflowPlanningArtifact,
9    WorkflowPreflightCheck, WorkflowPreflightChildTask, WorkflowPreflightError,
10    WorkflowPreflightParentTask, WorkflowPreflightPlan, WorkflowPreflightReport,
11    WorkflowPreflightScope, WorkflowPreflightVerdict, WorkflowRegistrySupport,
12    WorkflowRevocationPreflight, WorkflowRoutePlanPreflight, WORKFLOW_PREFLIGHT_PLAN_SCHEMA,
13    WORKFLOW_PREFLIGHT_REPORT_SCHEMA,
14};
15
16use scope::collect_child_scope_checks;
17use validation::{collect_plan_gate_checks, validate_plan_shape};
18
19const CLAIM_PREFLIGHT_CHILD_SCOPE_BOUNDED: &str = "claim.workflow.preflight_child_scope_bounded";
20const CLAIM_PREFLIGHT_PLANNING_ONLY: &str = "claim.workflow.preflight_planning_only";
21
22pub fn evaluate_workflow_preflight(
23    plan: &WorkflowPreflightPlan,
24) -> Result<WorkflowPreflightReport, WorkflowPreflightError> {
25    validate_plan_shape(plan)?;
26
27    let mut rejected_checks = Vec::new();
28    collect_child_scope_checks(plan, &mut rejected_checks);
29    collect_plan_gate_checks(plan, &mut rejected_checks);
30
31    let verdict = if rejected_checks.is_empty() {
32        WorkflowPreflightVerdict::Accepted
33    } else {
34        WorkflowPreflightVerdict::Rejected
35    };
36    let verified_claims = if verdict == WorkflowPreflightVerdict::Accepted {
37        vec![
38            CLAIM_PREFLIGHT_CHILD_SCOPE_BOUNDED.to_string(),
39            CLAIM_PREFLIGHT_PLANNING_ONLY.to_string(),
40        ]
41    } else {
42        Vec::new()
43    };
44
45    Ok(WorkflowPreflightReport {
46        schema: WORKFLOW_PREFLIGHT_REPORT_SCHEMA.to_string(),
47        id: format!("workflow-preflight-report-{}", plan.id),
48        issued_at: plan.issued_at.clone(),
49        plan_id: plan.id.clone(),
50        verdict,
51        evidence_class: "planning".to_string(),
52        verified_claims,
53        rejected_checks,
54        live_authority_claims: Vec::new(),
55    })
56}