> For the complete documentation index, see [llms.txt](https://docs.brain.fi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.brain.fi/protocol/policy-and-permissioning.md).

# Policy and Permissioning

Tenants describe policy in **plain English**. The Policy compiler converts each policy into a deterministic guard expression that is evaluated for every proposed action. Policies are versioned and signed by the tenant via EIP-712, with hashes anchored on-chain through `BrainPolicyRegistry`.

### Plain English in, Deterministic Guard Out

You write the policy in natural language. Brain compiles it. You sign the compiled form, not the prose.

```
Allow invoice payments under $5,000 to approved vendors,
require approval above $5,000,
and block payments to new counterparties without review.
```

Compiles to:

```json
{
  "subject": { "agent_capability": "pay_invoice" },
  "resource": { "counterparty.status": ["approved"] },
  "rules": [
    { "if": "amount < 5000 && counterparty.known", "then": "allow" },
    { "if": "amount >= 5000 && counterparty.known", "then": "confirm", "approvers": ["role:cfo"] },
    { "if": "!counterparty.known", "then": "reject", "reason": "new_counterparty_review_required" }
  ]
}
```

{% hint style="warning" %}
The compiler emits both the deterministic compiled policy **and** a human-readable explanation of what it will do. **Tenants sign the compiled form, not the prose.** This eliminates ambiguity at the moment of signing.
{% endhint %}

### The Five Elements of a Policy

Every policy has five elements.

| Element        | What It Defines                                                              |
| -------------- | ---------------------------------------------------------------------------- |
| **Subjects**   | Which agents, capabilities, or roles the policy applies to                   |
| **Resources**  | Which accounts, counterparties, asset classes, or jurisdictions are in scope |
| **Actions**    | What is permitted: read, propose, execute, approve                           |
| **Conditions** | Thresholds, time windows, frequency caps, required approvers                 |
| **Outcomes**   | `allow`, `reject`, or `confirm`                                              |

### The Three Outcomes

Every policy evaluation produces exactly one of three outcomes.

<table data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td><strong>✅ allow</strong></td><td>The action proceeds. A signed policy verdict is attached to the resulting session-key call via `executeViaSessionKey` or rail call.</td></tr><tr><td><strong>⚠️ confirm</strong></td><td>Human approval is required before the action can execute. The verdict names the required approvers (e.g. <code>role:cfo</code>).</td></tr><tr><td><strong>❌ reject</strong></td><td>The action is blocked. The verdict carries a structured reason (e.g. <code>new_counterparty_review_required</code>).</td></tr></tbody></table>

{% hint style="info" %}
**`confirm` is the default for unmatched conditions.** If the policy compiler cannot determine a clear `allow` or `reject` for a proposed action, the safe default is to require human review. Failure modes are explicit, not silent.
{% endhint %}

### Worked Example: the $7,800 Invoice

A walkthrough of the policy from the top of this page, applied to a real proposal:

| Step | What Happens                                                                                                                       |
| ---- | ---------------------------------------------------------------------------------------------------------------------------------- |
| 1    | Agent proposes: pay $7,800 invoice to Vendor X                                                                                     |
| 2    | Policy Layer evaluates against version `v3` of the tenant policy                                                                   |
| 3    | Counterparty Vendor X: known, status = approved                                                                                    |
| 4    | Amount $7,800: above $5,000 threshold                                                                                              |
| 5    | Outcome: `confirm`, approvers = `[role:cfo]`                                                                                       |
| 6    | CFO receives the request with Wiki context (vendor history, prior payments) and Ledger references (invoice, PO)                    |
| 7    | CFO approves. EIP-712 approval signature recorded                                                                                  |
| 8    | Action moves to executable. `BrainSmartAccount.executeViaSessionKey` dispatches the on-chain call OR a bank API call is dispatched |
| 9    | Audit Layer records: proposal, policy decision, approver identity, execution receipt, settlement confirmation, all linked by hash  |

### Versioning, Signing, and Anchoring

Every policy version has a lifecycle.

```
draft → compile → review → sign (EIP-712) → anchor on-chain → active
```

| Phase       | What Happens                                                        |
| ----------- | ------------------------------------------------------------------- |
| **Draft**   | Plain-English text written in the Console or via API                |
| **Compile** | Compiler produces deterministic JSON + a human-readable explanation |
| **Review**  | Tenant reviews the compiled form                                    |
| **Sign**    | Tenant signs the canonical hash via EIP-712 `PolicyRegistration`    |
| **Anchor**  | Hash is registered in `BrainPolicyRegistry` on Base L2              |
| **Active**  | The policy version is active until superseded or revoked            |

The signed structure:

```
PolicyRegistration(
  bytes32 tenantId,
  uint64  version,
  bytes32 policyHash,
  uint64  notBefore,
  uint64  notAfter,
  uint256 nonce
)
```

[**→ Smart contract reference**](/smart-contracts/overview.md)

### How Policy Enforcement Is Layered

Policy is enforced **twice** by design.

| Level                             | What It Catches                                                                                                                                                                                                                                                         |
| --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Off-chain** Brain Policy Engine | Most evaluations, fast feedback, dynamic conditions, rich error messages                                                                                                                                                                                                |
| **On-chain** `BrainSmartAccount`  | The session key is bound to the active `policyVersion` at grant time and its scope + spend caps are enforced inside `executeViaSessionKey`. Any action outside the granted key's bounds is rejected at the account level, regardless of what the off-chain engine said. |

{% hint style="success" %}
Belt and braces. Even if the off-chain engine were compromised, the on-chain account would still reject any call outside the granted session key's policyVersion-bound scope and spend caps.
{% endhint %}

Each session key is bound to the active `policyVersion` at grant time, and every `executeViaSessionKey` call carries a single-use replay nonce, so a call cannot be replayed against a different action.

### What's Next

<table data-view="cards"><thead><tr><th></th><th></th><th data-type="content-ref"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>🤖 Agents</strong></td><td>How agents propose actions and receive scope grants.</td><td><a href="/pages/t9xBO8sSjFElp8ecB6i5">/pages/t9xBO8sSjFElp8ecB6i5</a></td><td></td></tr><tr><td><strong>📜 Audit and Proof</strong></td><td>How every policy decision is captured.</td><td><a href="/pages/PIgNXssgtEUZDLnC4b4d">/pages/PIgNXssgtEUZDLnC4b4d</a></td><td></td></tr><tr><td><strong>📜 BrainPolicyRegistry</strong></td><td>The on-chain anchor.</td><td><a href="/pages/Qk74oUUATzrLis1xhGcb">/pages/Qk74oUUATzrLis1xhGcb</a></td><td></td></tr></tbody></table>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.brain.fi/protocol/policy-and-permissioning.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
