Policies / detail
governance.rego
Type rego · State active · Current version v1 · Updated 2026-05-08T12:55:14.865233627+00:00
Current body
sha256: 0f58d7bea3f1d0962bff0ae2f10348d411f646df8e4b7f84420ebbb0258844a3# Warden authorization policy.
#
# Loaded by warden-policy-engine at startup. The Rust evaluator queries
# `data.warden.authz.allow` (bool), `data.warden.authz.deny` (set[string]),
# and `data.warden.authz.review` (set[string], the Yellow tier — actions
# that require human approval before forwarding to upstream). The reason
# strings here are part of the audit surface — keep them stable.
package warden.authz
import rego.v1
default allow := false
# Hard tool denylist.
deny contains msg if {
input.tool_type == "sql_execute"
msg := "Violation: Direct execution of SQL queries is prohibited for this agent."
}
deny contains msg if {
input.tool_type == "shell_exec"
msg := "Violation: Direct shell access is prohibited."
}
# Probabilistic-override guard: if the Brain (L2) reported a dangerous intent
# score, block the request regardless of the tool.
deny contains msg if {
input.intent_score >= 0.2
msg := sprintf(
"Violation: Intent score %.2f exceeds safety threshold 0.2.",
[input.intent_score],
)
}
# Bulk exports are restricted to business hours (Mon-Fri 09:00-17:00 UTC).
deny contains msg if {
input.tool_type == "bulk_export"
not is_business_hours
msg := sprintf(
"Violation: Bulk export attempted at %s on %s (UTC). High-risk operations are restricted to business hours (Mon-Fri, 09:00-17:00 UTC).",
[hms_now, weekday_now],
)
}
# Token-velocity circuit breaker. The policy engine populates
# input.recent_request_count from its in-process tracker (60s window).
# Mirrors the PDF's "Recursive Loop / Denial of Wallet" defense.
recent_request_limit := 100
deny contains msg if {
input.recent_request_count > recent_request_limit
msg := sprintf(
"Violation: Token velocity exceeded — %d requests in the last 60s (limit %d). Possible recursive loop / denial-of-wallet attack.",
[input.recent_request_count, recent_request_limit],
)
}
# --- Yellow tier (human review) ---
# Actions that are too risky to auto-approve but not so risky they should
# be hard-denied. The proxy routes these through warden-hil: posts a
# pending record, waits for a human decision, and forwards on Approved.
# Wire transfers are the canonical example from the strategic plan
# (PDF Section 10).
#
# `review` and `deny` are independent rule sets; if both fire, `deny`
# wins (the Rust evaluator treats any non-empty `deny` as authoritative).
review contains msg if {
input.tool_type == "wire_transfer"
msg := "Review: Wire transfers require human approval before execution."
}
# --- time helpers ---
# Use input.current_time (RFC 3339) when provided so callers/tests are
# deterministic; otherwise fall back to wall clock. Guard with is_string
# so a literal JSON null (which some serializers emit for absent optional
# fields) routes to the wall-clock branch instead of into parse_rfc3339_ns.
ns_now := ns if {
is_string(input.current_time)
ns := time.parse_rfc3339_ns(input.current_time)
}
ns_now := ns if {
not is_string(input.current_time)
ns := time.now_ns()
}
clock_now := time.clock(ns_now)
weekday_now := time.weekday(ns_now)
hms_now := sprintf("%02d:%02d:%02d", [clock_now[0], clock_now[1], clock_now[2]])
is_business_hours if {
clock_now[0] >= 9
clock_now[0] < 17
weekday_now != "Saturday"
weekday_now != "Sunday"
}
# allow iff no deny rule AND no review rule fired. We fold `review` into
# the allow gate so wire-level `allow=true` means "safe to forward without
# human approval"; if review is non-empty, callers must consult the
# `review` set and route to the HIL flow before treating the request as
# authorized. Old callers that ignore `review` will see `allow=false`
# and block — fail-safe by construction.
allow if {
count(deny) == 0
count(review) == 0
}