Policy
Policy Rules
Define governance rules in YAML with enforcement levels, severity, scopes, and time windows.
Rule Format
Rules are defined in YAML (or JSON) and loaded from .usertrust/policies/default.yml by default.
# Requires operator scope on the governor/config, e.g. scope: ["production/api"]
- name: block-expensive-models
effect: deny
enforcement: hard
severity: high
priority: 50
conditions:
- field: model
operator: in
value:
- claude-opus-4-6
- gpt-5.4
scopePatterns:
- "production/*"
timeWindows:
- daysOfWeek: [1, 2, 3, 4, 5]
startHour: 9
endHour: 17Rule Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| name | string | yes | — | Unique rule identifier |
| effect | "deny" or "warn" | yes | — | What happens when matched |
| enforcement | "hard" or "soft" | yes | — | Hard = block, Soft = allow with warnings |
| severity | "critical" | "high" | "medium" | "low" | "info" | no | — | Severity level |
| priority | number | no | 100 | Lower = higher priority |
| enabled | boolean | no | true | Toggle rule on/off |
| conditions | FieldCondition[] | yes | — | Conditions to match (ALL must match) |
| scopePatterns | string[] | no | — | Minimatch glob patterns |
| timeWindows | TimeWindow[] | no | — | Time-based restrictions |
Enforcement
- Hard — Returns
decision: "deny". The LLM call is blocked. - Soft — Returns
decision: "allow"withhasWarnings: true. The call proceeds but warnings are logged.
Scope Matching
Uses minimatch glob patterns against the operator-declared scope on the governor or usertrust.config.json — not request content, and not params.params.scope.
scopePatterns:
- "production/**" # matches production/api, production/chat/v2
- "staging/*" # matches staging/test but not staging/a/bIf the operator sets no scope, a rule with scopePatterns never matches. It does not "narrow a live rule". An absent scopePatterns still matches all calls.
Time Windows
Restrict when a rule is active:
timeWindows:
- daysOfWeek: [1, 2, 3, 4, 5] # Mon-Fri (0=Sun, 6=Sat)
startHour: 9 # 9 AM
endHour: 17 # 5 PMDefault Rules
Three rules ship by default:
- block-budget-overshoot — Deny when
budget_remaining_afterlt0 (hard) - block-budget-exhausted — Deny when
budget_remaininglte0 (hard) - warn-high-cost — Warn when
estimated_costgt1000 (soft)
PolicyResult
interface PolicyResult {
decision: "allow" | "deny";
hasWarnings: boolean;
matched: RuleMatch[];
hardViolations: RuleMatch[];
softViolations: RuleMatch[];
reasons: string[];
evaluatedAt: string;
}