chio_kernel_core/guard.rs
1//! Sync guard trait for portable evaluation.
2//!
3//! The surface matches `chio_kernel::Guard` byte-for-byte so the same
4//! guard implementations run in both crates with no behavioural change:
5//!
6//! ```ignore
7//! pub trait Guard: Send + Sync {
8//! fn name(&self) -> &str;
9//! fn evaluate(&self, ctx: &GuardContext) -> Result<Verdict, KernelCoreError>;
10//! }
11//! ```
12//!
13//! The error type is [`crate::evaluate::KernelCoreError`] instead of
14//! `chio_kernel::KernelError` because the full error enum carries
15//! std/tokio/sqlite-flavoured variants that are not portable. The
16//! adapter in `chio-kernel::kernel` bridges the two.
17
18use alloc::string::String;
19
20use chio_core_types::capability::scope::ChioScope;
21
22use crate::Verdict;
23
24/// Sync guard trait. Signature-for-signature compatible with
25/// `chio_kernel::Guard`.
26pub trait Guard: Send + Sync {
27 /// Human-readable guard name (e.g. `forbidden-path`).
28 fn name(&self) -> &str;
29
30 /// Evaluate this guard against a tool-call context.
31 ///
32 /// Returns `Ok(Verdict::Allow)` to pass, `Ok(Verdict::Deny)` to block,
33 /// or `Err(KernelCoreError)` to signal an internal guard failure (which
34 /// the kernel core treats as a fail-closed deny).
35 fn evaluate(&self, ctx: &GuardContext<'_>) -> Result<Verdict, crate::KernelCoreError>;
36}
37
38/// Inputs a guard sees when it runs inside the core evaluate pipeline.
39///
40/// Mirrors `chio_kernel::GuardContext` with two deliberate restrictions:
41///
42/// - `request` carries only the portable shape (no `dpop_proof`,
43/// `governed_intent`, `approval_token`, or `model_metadata` -- those are
44/// full-kernel concerns). The adapter in `chio-kernel` builds a
45/// temporary [`PortableToolCallRequest`] when it runs the core evaluate
46/// pipeline.
47/// - `session_filesystem_roots` stays in the portable surface so the
48/// filesystem-roots guard (today the only session-aware guard) can run
49/// unchanged on every platform.
50pub struct GuardContext<'a> {
51 /// The tool call request being evaluated.
52 pub request: &'a PortableToolCallRequest,
53 /// The verified capability scope.
54 pub scope: &'a ChioScope,
55 /// The agent making the request.
56 pub agent_id: &'a str,
57 /// The target server.
58 pub server_id: &'a str,
59 /// Session-scoped enforceable filesystem roots, when the request is being
60 /// evaluated through the supported session-backed runtime path.
61 pub session_filesystem_roots: Option<&'a [String]>,
62 /// Index of the matched grant in the capability's scope, populated by
63 /// [`crate::evaluate`] before guards run.
64 pub matched_grant_index: Option<usize>,
65}
66
67/// Portable projection of an `chio_kernel::runtime::ToolCallRequest`.
68///
69/// Contains only the fields the sync core evaluate pipeline needs. Guards
70/// that want DPoP/governed/approval inputs must stay in `chio-kernel`.
71#[derive(Debug, Clone)]
72pub struct PortableToolCallRequest {
73 /// Unique request identifier.
74 pub request_id: String,
75 /// The tool to invoke.
76 pub tool_name: String,
77 /// The server hosting the tool.
78 pub server_id: String,
79 /// The calling agent's identifier (hex-encoded public key).
80 pub agent_id: String,
81 /// Tool arguments as canonical JSON.
82 pub arguments: serde_json::Value,
83}