Skip to content

policy.yaml

.wayglass/policy.yaml at the root of the repository. wayglass init writes the example below if the file does not exist. The Worker reads the copy on the trunk, at the commit each intent forked from; see Policy.

The file is parsed strictly. Unknown keys are errors, so a typo such as whne: cannot turn a rule into a catch-all. wayglass propose and wayglass policy test both fail with policy_invalid on a file that does not validate.

Key Required Meaning
version yes Must be 1
classify no How changes are tagged: area, data_class, risk
rules no Ordered list of rules; the first enforcing match decides
default no Used when no enforcing rule matches. Defaults to human_approve with the reason “No rule matched; a person decides.”
classify:
area:
<name>: [<glob>, ...]
data_class:
<name>: { content: [<regex>, ...], paths: [<glob>, ...] }
risk:
<level>: { lines_changed_over: <n>, files_changed_over: <n> }
Key Rules
area.<name> At least one glob. ** matches any number of directories, including none. A change gets the area when any changed path matches
data_class.<name> At least one of content (Go RE2 regular expressions, matched against each added line) or paths (globs, matched against changed paths)
risk.<level> <level> is medium, high or critical; low is the default and takes no threshold. At least one threshold, neither negative. The highest level whose threshold is exceeded applies

See Tags for what each tag means. Jurisdiction is not configured here; it comes from the project’s namespace.

Each rule:

Key Required Meaning
when yes Condition; must set at least one field
action yes auto_merge, agent_review, human_approve, multi_approve, quarantine or block
reason yes Why; recorded with every decision this rule makes
name no Label for the rule in decisions, logs and policy test. Must be unique. Without one, the label is rules[<index>]
approvers only for multi_approve Number of distinct approvers, at least 2. Default 2. Not allowed on other actions
mode no enforce (default) or shadow. A shadow rule is recorded but never decides
shadow no Older spelling of mode: shadow. shadow: true with mode: enforce is an error
Field Matches when
area Any changed file is in any of the listed areas
only_area Every changed file is in at least one of the listed areas. Use it for permissive rules
data_class The change has any of the listed data classes
risk The change’s risk is one of the listed levels
jurisdiction The project’s jurisdiction is one of the listed values (case-insensitive)

Each field takes a string or a list of strings. Every field that is set must match (AND); within a field, any value matches (OR). Areas (in area and only_area) and data classes must be defined under classify.

default: { action: human_approve, reason: "No rule matched; a person decides." }

action and reason are required; approvers follows the same rule as in a rule.

Action Decision status propose exits
auto_merge approved 0
agent_review pending_agent 0
human_approve pending_human 4
multi_approve pending_human 4
quarantine quarantined 4
block blocked 3

The policy wayglass init writes:

version: 1
classify:
area:
docs: ["docs/**", "**/*.md"]
web: ["web/**"]
auth: ["**/auth/**", "**/login*"]
infra: ["worker/wrangler.jsonc", ".github/**"]
data_class:
secrets: { content: ["(?i)api[_-]?key", "art_v[0-9]+_([a-z]+_)?[0-9a-f]{40}"] }
pii: { content: ["(?i)\\bssn\\b", "(?i)date_of_birth"] }
risk:
high: { lines_changed_over: 400 }
rules:
- { when: { data_class: secrets }, action: block, reason: "Secrets never land." }
- { when: { area: infra }, action: multi_approve, approvers: 2, reason: "Infra changes affect everyone." }
- { when: { area: auth }, action: human_approve, reason: "Auth is a security boundary." }
- { when: { jurisdiction: eu, data_class: pii }, action: quarantine, reason: "EU personal data needs DPO review." }
- { when: { only_area: docs, risk: low }, action: auto_merge, reason: "Routine docs change; every file is docs." }
- { when: { risk: low }, action: agent_review, reason: "Low risk; second agent checks intent vs diff." }
default: { action: human_approve, reason: "No rule matched; a person decides." }
rules:
- name: trial-pii-review
when: { data_class: pii }
action: quarantine
reason: "Trial: all personal data gets a DPO look."
mode: shadow

How shadow matches are recorded, and how to replay history through a draft policy with wayglass policy test, is covered in Policy.