Skip to main content

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}