Skip to main content

tracevault_core/
policy.rs

1use serde::{Deserialize, Serialize};
2use uuid::Uuid;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct PolicyRule {
6    pub id: Uuid,
7    pub org_id: Option<String>,
8    pub name: String,
9    pub description: String,
10    pub condition: PolicyCondition,
11    pub action: PolicyAction,
12    pub severity: PolicySeverity,
13    pub enabled: bool,
14    #[serde(default)]
15    pub scope: PolicyScope,
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
19#[serde(tag = "type")]
20pub enum PolicyCondition {
21    TraceCompleteness,
22    AiPercentageThreshold {
23        threshold: f32,
24    },
25    ModelAllowlist {
26        allowed_models: Vec<String>,
27    },
28    SensitivePathPattern {
29        patterns: Vec<String>,
30    },
31    RequiredToolCall {
32        tool_names: Vec<String>,
33        #[serde(default)]
34        must_succeed: bool,
35    },
36    TokenBudget {
37        max_tokens: Option<u64>,
38        max_cost_usd: Option<f64>,
39    },
40    ConditionalToolCall {
41        tool_name: String,
42        min_count: Option<u32>,
43        when_files_match: Option<Vec<String>>,
44        #[serde(default)]
45        must_succeed: bool,
46    },
47}
48
49/// Which evaluation phase this policy applies to.
50///
51/// The "verification phase" is the period after the agent declares it is
52/// done changing code (via `tracevault verify-start`) and is now running
53/// pre-push checks. Policies scoped to that phase evaluate only tool calls
54/// made inside it; policies scoped to `Session` evaluate the whole push.
55#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
56#[serde(rename_all = "snake_case")]
57pub enum PolicyScope {
58    /// Evaluated over the entire push (default).
59    #[default]
60    Session,
61    /// Evaluated only against events inside the current verification phase.
62    VerificationPhase,
63    /// Evaluated in both contexts.
64    Both,
65}
66
67#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
68#[serde(rename_all = "snake_case")]
69pub enum PolicyAction {
70    BlockPush,
71    Warn,
72    /// Tool is explicitly permitted inside the verification phase without
73    /// a count requirement. Prevents it from triggering the unknown-tool
74    /// gate.
75    Allow,
76}
77
78/// Org/repo-level setting controlling what happens when an unknown tool
79/// (not covered by any `verification_phase`-scoped policy) is called inside
80/// an active verification phase.
81#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
82#[serde(rename_all = "snake_case")]
83pub enum VerificationPhaseMode {
84    /// No verification-phase enforcement (default).
85    #[default]
86    Disabled,
87    /// Unknown tool call is flagged but the push still succeeds.
88    Warn,
89    /// Unknown tool call blocks the push.
90    Block,
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize)]
94#[serde(rename_all = "lowercase")]
95pub enum PolicySeverity {
96    Critical,
97    High,
98    Medium,
99    Low,
100}
101
102#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct PolicyEvaluation {
104    pub policy: PolicyRule,
105    pub result: EvalResult,
106    pub details: String,
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
110#[serde(rename_all = "lowercase")]
111pub enum EvalResult {
112    Pass,
113    Fail,
114    Warn,
115}