usertrust
Concepts

Policy Engine

Rule-based governance with 12 field operators, scope globs, and time windows.

The policy engine evaluates every governed LLM call against a set of rules before the call is forwarded to the provider. Rules are defined in YAML or JSON and support field matching, scope globs, time windows, and priority ordering.

Enforcement Levels

Each rule specifies an enforcement level that determines what happens when the rule matches:

EnforcementEffect
hardDeny the request. Throws PolicyDeniedError.
softAllow the request with warnings. The governance receipt includes the matched rule and reason.

PolicyResult

Every policy evaluation returns a structured result:

interface PolicyResult {
  decision: "allow" | "deny";
  hasWarnings: boolean;
  matched: RuleMatch[];
  hardViolations: RuleMatch[];
  softViolations: RuleMatch[];
  reasons: string[];
  evaluatedAt: string;
}

Rule Structure

A policy rule specifies conditions, scope, enforcement, and optional time windows:

# .usertrust/policies/default.yml
rules:
  - name: block-expensive-models
    description: Deny requests to opus-class models in production
    enforcement: hard
    priority: 10
    scopes: ["production/*"]
    conditions:
      - field: model
        operator: contains
        value: "opus"
    timeWindow:
      daysOfWeek: [1, 2, 3, 4, 5]  # Mon-Fri
      startHour: 9
      endHour: 17

Operators

The policy engine supports 12 field operators for matching conditions. Each operator compares a field value (resolved via dot-notation) against the rule's expected value.

OperatorDescription
existsField is present
not_existsField is absent
eqEqual (strict)
neqNot equal
gtGreater than
gteGreater than or equal
ltLess than
lteLess than or equal
inValue is in array
not_inValue is not in array
containsString contains substring
regexMatches regular expression

See Policy Operators for detailed usage and examples of each operator.

Scope Matching

Scopes use minimatch glob patterns to target specific contexts:

scopes: ["production/*"]          # all production sub-scopes
scopes: ["development/**"]        # development and all nested scopes
scopes: ["*/billing"]             # billing scope in any environment

If a rule has no scopes field, it matches all scopes.

Time Windows

Rules can be restricted to specific days and hours:

timeWindow:
  daysOfWeek: [1, 2, 3, 4, 5]    # 0=Sunday, 6=Saturday
  startHour: 9                     # 24-hour format
  endHour: 17

A rule with a time window only matches during the specified period. Outside the window, the rule is skipped entirely.

Priority

Rules are evaluated in priority order. Lower numbers are evaluated first (higher priority):

PriorityConvention
1-10Critical safety rules
10-50Cost and budget rules
50-100Operational rules
100Default priority

If multiple rules match, all hard violations result in denial. Soft violations accumulate as warnings.

Default Rules

usertrust ships with three built-in rules:

  1. zero-budget -- Deny if the account has zero remaining budget (hard)
  2. high-cost -- Warn on requests estimated above a configurable threshold (soft)
  3. budget-exhausted -- Deny if estimated cost exceeds remaining budget (hard)

Further Reading