# OPL Overview

OPL, the Octet Policy Language, is how a Magistrate policy is written down. The studio writes it for you, and shows it in its code pane. Read this page to review a policy before you sign it off, or to understand a decision afterwards.

This documentation covers the part of OPL that the Magistrate studio and the Octet policy engine support today. [What's Next](/docs/magistrate/whats-next/) lists what comes later.

## A policy

```opl
policy p_3b41af1558a1448b8845fa2821871b5d {
  combine deny_overrides
  rule deny when outside(country("AT")) reason "E-304"
  default permit
  freshness 5m
}
```

In words: a device outside Austria gets `deny`. Every other device gets `permit`. If the proofs can't settle where the device is, the answer is `deny`. Proofs older than 5 minutes don't count.

## Policy structure

A policy is a name and a body in braces. The body is a list of clauses, in any order.

| Clause | Required | Description |
|---|---|---|
| `policy <name>` | Yes | The policy's name. Policies from the studio are named `p_` followed by a UUID. The studio shows a separate, human title |
| `rule` | Yes, one or more | An effect, `permit` or `deny`, and the condition under which it applies. See [Policy clauses](/docs/magistrate/opl/language/#policy-clauses) |
| `combine` | No | How the rules combine into one decision. These docs cover only `deny_overrides`, the default |
| `default` | No | The decision when no rule applies, `permit` or `deny`. Without it, no matching rule means `deny` |
| `on_indeterminate` | No | The decision when the proofs can't settle a rule. Defaults to `deny`, and these docs cover only `deny`. The studio doesn't write this clause |
| `freshness` | No | How old a proof may be and still count, for example `5m`. Without it, 300 seconds |
| `requires` | No | A minimum precision for the proofs, for example `requires proof_level >= country` |

## How a policy is decided

The engine verifies the device's proofs, then evaluates the rules:

```mermaid
%%{init: {"flowchart": {"nodeSpacing": 30, "rankSpacing": 40}}}%%
flowchart LR
    Q(Are the proofs precise<br/>enough for the policy?) -- yes --> D(Does a deny<br/>rule apply?)
    D -- no --> P(Does a permit<br/>rule apply?)
    P -- no --> DEF[the default<br/>answer]
    D -- yes --> DENY[deny]
    P -- yes --> PERMIT[permit]
    Q -- no --> U[UNKNOWN: the<br/>on_indeterminate answer]
    D -- can't tell --> U
    P -- can't tell --> U
```

1. **The proofs must be precise enough.** If the policy has a `requires` clause and the proofs don't meet it, the policy can't be decided and gets its `on_indeterminate` answer, with `cause` `other`. A proof older than `freshness` doesn't stop the decision. It only leaves the regions it would have settled unknown, so a deny rule that other proofs settle still wins.
2. **Deny wins.** If any `deny` rule applies, the decision is `deny`.
3. **A rule that can't be settled stops the decision.** If a `deny` rule might apply but the proofs can't tell, the decision is the `on_indeterminate` answer. For example, a device that proves only that it is in Ukraine can't settle a rule about Crimea.
4. **Then permit.** If a `permit` rule applies, the decision is `permit`.
5. **Then the default.** If no rule applies, the decision is `default`, or `deny` without one.

The engine returns only `permit` or `deny`. When the answer came from `on_indeterminate`, the decision also carries a `cause` saying why the location couldn't be settled. See [Decision Response](/docs/magistrate/reference/decision/).

## Defaults to know

- **No proof is not a pass.** A device with no current proof can't satisfy a rule, so the policy gives its `on_indeterminate` answer. Every policy the studio writes uses `deny`.
- **Countries follow ISO 3166 strictly.** `country("US")` doesn't include Puerto Rico or the other territories, which have their own codes. List them if you mean them.
- **No matching rule and no default is `deny`.**
- **A policy decides one question.** To check several at once, use `decideMany` in the Magistrate module.

## Next

- [Language](/docs/magistrate/opl/language/): every keyword, region and type.
- [Examples](/docs/magistrate/opl/examples/): complete policies to copy.
