Skip to main content

leviath_cli/config/
policy.rs

1//! How permissive a tool or script capability is, before any run-time layering.
2//!
3//! Three small enums that every other config section refers to, so they sit
4//! apart from the sections that use them rather than inside whichever one
5//! happened to need them first.
6
7use serde::{Deserialize, Serialize};
8
9/// Whether a tool call should execute automatically or require user approval.
10///
11/// The effective policy for a tool is resolved by narrowest scope first:
12/// launch-flag > stage > agent > global config > built-in default.
13#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
14#[serde(rename_all = "snake_case")]
15pub enum ToolPolicy {
16    /// Execute without prompting.
17    Allow,
18    /// Ask the user before each call (or once per session with `allow_session`).
19    #[default]
20    Ask,
21    /// Never execute - return a denied error to the model.
22    Deny,
23}
24
25// `TitleConfig` (plain data used by the engine's title generation) lives in
26// `leviath_core::config` so `leviath-runtime` can reference it without a CLI
27// dependency. Re-exported here so `crate::config::TitleConfig` paths resolve.
28pub use leviath_core::config::TitleConfig;
29
30// Same arrangement for the `[observability]` section: the plain data lives in
31// `leviath_core::config` (the telemetry sink crate reads it), re-exported here.
32pub use leviath_core::config::{ObservabilityConfig, TelemetryExporterKind};
33
34/// Permission for one Rhai *script-tool* host function (Layer 3 of the
35/// four-layer permission model). Gates what a registered script may *do*,
36/// independent of
37/// whether the tool itself is visible ([`available_tools`]) or approved at
38/// runtime ([`ToolPolicy`]).
39///
40/// [`available_tools`]: leviath_core::blueprint::Stage::available_tools
41#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
42#[serde(rename_all = "snake_case")]
43pub enum ScriptPermission {
44    /// The host function may run.
45    Allow,
46    /// The host function is blocked - the call returns a `[denied]` error.
47    Deny,
48    /// Defer to the agent's own `tool_permissions` for the equivalent built-in
49    /// (`read_file`/`shell`): permitted only when that resolves to
50    /// [`ToolPolicy::Allow`]. For the network/env functions (`http_get`,
51    /// `http_post`, `env_var`), which have no built-in equivalent, `Inherit`
52    /// permits the call (they're needed for tools to be useful, and the tool
53    /// itself is still gated by Layers 1/2/4).
54    #[default]
55    Inherit,
56}
57
58/// Per-host-function permissions for Rhai script tools (`[tool_script_permissions]`).
59///
60/// Every field defaults to [`ScriptPermission::Inherit`], so an unconfigured
61/// install lets network/env functions run while file/shell functions defer to
62/// the agent's own tool permissions.
63#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
64pub struct ScriptToolPermissions {
65    /// Permission for `http_get`.
66    #[serde(default)]
67    pub http_get: ScriptPermission,
68    /// Permission for `http_post`.
69    #[serde(default)]
70    pub http_post: ScriptPermission,
71    /// Permission for `shell`.
72    #[serde(default)]
73    pub shell: ScriptPermission,
74    /// Permission for `read_file`.
75    #[serde(default)]
76    pub read_file: ScriptPermission,
77    /// Permission for `write_file`.
78    #[serde(default)]
79    pub write_file: ScriptPermission,
80    /// Permission for `env_var`.
81    #[serde(default)]
82    pub env_var: ScriptPermission,
83}