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}