Normandy.Behaviours.PolicyEngine.Ruleset
(normandy v2.2.0)
View Source
PolicyEngine that evaluates an ordered list of in-memory rules, first match
wins, with a configurable default action. The ruleset is supplied as a
keyword list on ctx.opts (the opts half of the bundle's
{module, opts} ref — always a keyword list by construction):
:rules(required) — list of%{match, action, rule_id, rationale}maps.match(required) is a tool-name glob:"*"(matches all),"prefix_*"(trailing*only — prefix match), or an exact name.action(required) is:allow | :deny | :require_approval.:default_action(required) — action when no rule matches. There is no implicit:allow: a policy states what an unmatched call gets.
A rule sees the tool's name only. An MCP server or a remote A2A agent chooses its own
tools' names, so match those on the prefix you gave them ("srv__*", see
Normandy.MCP.ToolWrapper's "Tool names and policy rules"), never on a name such as
"read_*" that a server can choose to match.
A malformed ruleset raises ArgumentError: when the agent is built
(validate_opts!/1), and again in check/2, which the dispatch chokepoint
turns into a denial. It never fails open.
A YAML-file loader is intentionally deferred — YAML is only a serialization of this in-memory shape.