systemprompt_models/profile/governance.rs
1//! Governance configuration for the gateway + MCP authorization hook.
2//!
3//! Authz is **fail-closed** with an explicit-opt-in surface. Four modes:
4//!
5//! - `webhook` — production. Core POSTs every request to the configured URL;
6//! any transport error, non-2xx, or decode failure denies the request.
7//! - `extension` — production. The hook is supplied at bootstrap by the binary
8//! via `AppContextBuilder::with_authz_hook(...)`. Bootstrap errors if no hook
9//! is supplied. See `internal/guides/authz.md`.
10//! - `disabled` — denies every request via `DenyAllHook`. Use when authz is
11//! intentionally inactive but you want the surface installed.
12//! - `unrestricted` — TEST/DEV ONLY. Allows every request via `AllowAllHook`.
13//! Requires `acknowledgement` to equal the literal sentence `"I understand
14//! this disables all authorization"`. Bootstrap errors otherwise.
15//!
16//! Absent `governance` block, absent `authz`, or any unparseable config →
17//! bootstrap installs `DenyAllHook` (everything denied) so misconfiguration
18//! never silently grants access.
19//!
20//! Example:
21//!
22//! ```yaml
23//! governance:
24//! authz:
25//! hook:
26//! mode: webhook
27//! url: http://localhost:8080/api/public/govern/authz
28//! timeout_ms: 500
29//! ```
30
31use serde::{Deserialize, Serialize};
32
33pub const UNRESTRICTED_ACKNOWLEDGEMENT: &str = "I understand this disables all authorization";
34
35#[derive(Debug, Clone, Default, Serialize, Deserialize, schemars::JsonSchema)]
36#[serde(deny_unknown_fields)]
37pub struct GovernanceConfig {
38 #[serde(default)]
39 pub authz: Option<AuthzConfig>,
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
43#[serde(deny_unknown_fields)]
44pub struct AuthzConfig {
45 pub hook: AuthzHookConfig,
46}
47
48#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
49#[serde(rename_all = "lowercase")]
50pub enum AuthzMode {
51 Webhook,
52 Extension,
53 Disabled,
54 Unrestricted,
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
58#[serde(deny_unknown_fields)]
59pub struct AuthzHookConfig {
60 pub mode: AuthzMode,
61 #[serde(default)]
62 pub url: Option<String>,
63 #[serde(default = "default_timeout_ms")]
64 pub timeout_ms: u64,
65 #[serde(default)]
66 pub acknowledgement: Option<String>,
67}
68
69const fn default_timeout_ms() -> u64 {
70 500
71}