> ## Documentation Index
> Fetch the complete documentation index at: https://memproof.kyberon.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Policy Authoring

> Write YAML policy files that control which memory operations are allowed, denied, or require approval.

Memproof policies are declarative YAML files that define how the system handles every memory operation. The policy engine evaluates rules in priority order -- the first matching rule wins.

## Policy File Structure

Every policy file has five top-level keys:

```yaml theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
version: 0.1.0          # Semantic version of your policy
mode: enforce            # "enforce" applies rules; "audit" logs but does not block
defaults:                # Fallback behaviors
  on_policy_miss: deny
  on_adapter_error: quarantine
  require_idempotency: true
risk_thresholds:         # Score boundaries for risk levels
  low_max: 0.30
  medium_max: 0.60
  high_max: 0.80
  critical_max: 1.00
rules: []                # Ordered list of policy rules
```

## Rule Anatomy

Each rule is a dictionary with the following fields:

```yaml theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
- id: approve_high_risk_mutations        # Unique identifier
  description: Require approval for high risk mutations.
  enabled: true                          # Toggle without removing
  priority: 200                          # Lower number fires first
  action: require_approval               # allow | deny | require_approval | quarantine
  reason_codes: [HIGH_RISK_MUTATION]     # Machine-readable codes for audit trail
  match: all                             # "all" = AND, "any" = OR
  when:                                  # List of conditions
    - field: operation_type
      operator: in
      value: [remember, update, forget]
    - field: risk_level
      operator: in
      value: [high, critical]
```

<Note>
  Rules are sorted by `priority` at load time. A rule with priority `50` is evaluated before priority `200`. The first match short-circuits evaluation.
</Note>

## Available Fields

Conditions can reference these fields from the evaluation context:

| Field                     | Type   | Example Values                                  |
| ------------------------- | ------ | ----------------------------------------------- |
| `operation_type`          | string | `remember`, `update`, `forget`, `search`, `get` |
| `risk_level`              | string | `low`, `medium`, `high`, `critical`             |
| `risk_score`              | float  | `0.0` - `1.0`                                   |
| `scope.tenant_id`         | string | `"acme-corp"`                                   |
| `scope.project_id`        | string | `"proj-123"`                                    |
| `scope.agent_id`          | string | `"agent-alpha"`                                 |
| `scope.subject_id`        | string | `"user-456"`                                    |
| `context.source`          | string | `"langgraph"`, `"mcp"`, `"api"`                 |
| `content.contains_pii`    | bool   | `true`, `false`                                 |
| `content.contains_secret` | bool   | `true`, `false`                                 |
| `content.length`          | int    | `0` - N                                         |

## Condition Operators

The policy engine supports 10 operators:

| Operator   | Description              | Example                                                             |
| ---------- | ------------------------ | ------------------------------------------------------------------- |
| `eq`       | Equals                   | `{ field: risk_level, operator: eq, value: critical }`              |
| `neq`      | Not equals               | `{ field: context.source, operator: neq, value: api }`              |
| `in`       | Value is in list         | `{ field: operation_type, operator: in, value: [search, get] }`     |
| `nin`      | Value not in list        | `{ field: context.source, operator: nin, value: [langgraph, mcp] }` |
| `gt`       | Greater than             | `{ field: risk_score, operator: gt, value: 0.8 }`                   |
| `gte`      | Greater than or equal    | `{ field: content.length, operator: gte, value: 1000 }`             |
| `lt`       | Less than                | `{ field: risk_score, operator: lt, value: 0.3 }`                   |
| `lte`      | Less than or equal       | `{ field: content.length, operator: lte, value: 500 }`              |
| `contains` | Substring match          | `{ field: scope.tenant_id, operator: contains, value: acme }`       |
| `regex`    | Regular expression match | `{ field: scope.agent_id, operator: regex, value: "^agent-.*" }`    |

## Match Modes

* **`all`** (default) -- Every condition must be true (logical AND).
* **`any`** -- At least one condition must be true (logical OR).

## Default Behaviors

| Key                | Values                                            | Purpose                               |
| ------------------ | ------------------------------------------------- | ------------------------------------- |
| `on_policy_miss`   | `allow`, `deny`, `quarantine`, `require_approval` | Action when no rule matches           |
| `on_adapter_error` | `quarantine`, `deny`                              | Action when the backend adapter fails |

<Warning>
  Setting `on_policy_miss: allow` means any operation not explicitly matched by a rule will be permitted. In production, `deny` is the safer default.
</Warning>

## Common Patterns

### Allow Trusted Reads

```yaml theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
- id: allow_safe_search
  description: Allow read/search from trusted runtimes.
  priority: 100
  action: allow
  reason_codes: [SAFE_READ_PATH]
  match: all
  when:
    - field: operation_type
      operator: in
      value: [search, get]
    - field: context.source
      operator: in
      value: [langgraph, openai_sessions, mcp]
```

### Block Cross-Tenant Operations

```yaml theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
- id: deny_cross_tenant_ops
  description: Deny operations with missing tenant scope.
  priority: 50
  action: deny
  reason_codes: [CROSS_TENANT_SCOPE_MISMATCH]
  match: any
  when:
    - field: scope.tenant_id
      operator: eq
      value: ""
```

### Require Approval for High Risk

```yaml theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
- id: approve_high_risk
  description: Require human approval for high/critical mutations.
  priority: 200
  action: require_approval
  reason_codes: [HIGH_RISK_MUTATION]
  match: all
  when:
    - field: operation_type
      operator: in
      value: [remember, update, forget]
    - field: risk_level
      operator: in
      value: [high, critical]
```

### Quarantine PII from Untrusted Sources

```yaml theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
- id: quarantine_pii
  description: Quarantine writes with PII from untrusted sources.
  priority: 160
  action: quarantine
  reason_codes: [SENSITIVE_UNTRUSTED_SOURCE]
  match: all
  when:
    - field: operation_type
      operator: in
      value: [remember, update]
    - field: context.source
      operator: nin
      value: [langgraph, openai_sessions, mcp]
    - field: content.contains_pii
      operator: eq
      value: true
```

<Tip>
  Start with the example policy at `examples/memproof.yaml` and customize it for your threat model. Keep cross-tenant denial at the lowest priority number so it fires before anything else.
</Tip>
