Skip to content

Commit 3aeffb8

Browse files
fix: exempt read-only tools from dry-run enforcement
1 parent ddab0c3 commit 3aeffb8

1 file changed

Lines changed: 20 additions & 3 deletions

File tree

policies/enforce_dry_run.rego

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,34 @@
11
# Enforce dry-run before live execution
22
#
3-
# If the workflow declaration requires dry_run_first,
4-
# verify that the plan includes a dry-run step before
5-
# any mutating tool call.
3+
# If the workflow declaration requires dry_run_first, verify that each
4+
# mutating tool invocation is preceded by a dry-run invocation of the
5+
# same tool.
6+
#
7+
# Tools that do not support dry-run (read-only validators, notification
8+
# tools, record-keeping tools) are exempt. This list mirrors the
9+
# `safety.supports_dry_run == false` flag in the corresponding tool
10+
# contracts under schemas/.
11+
#
12+
# Production adaptation: in a real deployment, this list should be
13+
# generated from tool contract metadata rather than hardcoded.
614

715
package itsm.guardrails.enforce_dry_run
816

917
import rego.v1
1018

19+
# Tools exempt from dry-run enforcement (supports_dry_run: false in contracts)
20+
_tools_without_dry_run := {
21+
"validate_service_health",
22+
"notify_stakeholders",
23+
"open_change_record",
24+
"restart_service_rollback",
25+
}
26+
1127
violation contains msg if {
1228
input.workflow.guardrails.must_use_dry_run_first == true
1329
some i, tool in input.plan.tool_calls
1430
tool.dry_run != true
31+
not tool.tool_name in _tools_without_dry_run
1532
not _preceded_by_dry_run(input.plan.tool_calls, i, tool.tool_name)
1633
msg := sprintf("tool '%s' at step %d has no preceding dry-run invocation", [tool.tool_name, i])
1734
}

0 commit comments

Comments
 (0)