Skip to main content

agent_graph_mcp/
policy.rs

1use crate::spec::{GraphSpec, MAX_INPUT_BYTES, MAX_ITERATIONS, MAX_OUTPUT_BYTES};
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub struct PolicyFinding {
5    pub code: &'static str,
6    pub detail: String,
7}
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct PolicyReport {
11    pub substantive: bool,
12    pub findings: Vec<PolicyFinding>,
13}
14
15/// Non-authoritative admission preflight. It never grants authorization.
16pub fn preflight(spec: &GraphSpec, provider: &str) -> PolicyReport {
17    let mut findings = Vec::new();
18    if spec.spec_version != "2" {
19        findings.push(PolicyFinding {
20            code: "GRAPH_VERSION_UNSUPPORTED",
21            detail: spec.spec_version.clone(),
22        });
23    }
24    if spec.max_iterations.unwrap_or(MAX_ITERATIONS) > MAX_ITERATIONS {
25        findings.push(PolicyFinding {
26            code: "BUDGET_EXCEEDED",
27            detail: "max_iterations".into(),
28        });
29    }
30    if provider.trim().is_empty() {
31        findings.push(PolicyFinding {
32            code: "PROVIDER_DESTINATION_MISSING",
33            detail: "provider destination is empty".into(),
34        });
35    }
36    if spec
37        .nodes
38        .iter()
39        .any(|n| n.max_tokens.unwrap_or(0) > MAX_OUTPUT_BYTES)
40    {
41        findings.push(PolicyFinding {
42            code: "OUTPUT_BUDGET_EXCEEDED",
43            detail: "max_tokens".into(),
44        });
45    }
46    let _ = MAX_INPUT_BYTES;
47    for node in &spec.nodes {
48        if let Err(error) = GraphSpec::executable_node_type(&node.node_type) {
49            findings.push(PolicyFinding {
50                code: "UNSUPPORTED_NODE_TYPE",
51                detail: error,
52            });
53        }
54        if node.evidence_required {
55            findings.push(PolicyFinding {
56                code: "WITNESS_REQUIREMENT",
57                detail: node.id.clone(),
58            });
59        }
60    }
61    PolicyReport {
62        substantive: true,
63        findings,
64    }
65}