# Resolver Policy

> Every policy field: default, block, allow, mode, allow_sources, retention, and the separate bundles argument that carries category and geography rules.

*Source: https://www.whisper.security/docs/network/resolver/policy*

---
One policy per account. It applies to every agent and every device on the account, so there
is no per-agent copy to keep in step. Read the current policy back by passing no arguments:

```bash
whisper policy
```

```whisper-call
CALL whisper.agents({op: 'policy', args: {}})
```

The read returns `key` and `value` rows. Only the fields you send on a write are changed;
anything you leave out keeps the value it had.

## `default`

`allow` or `deny`. It decides what happens to a name that neither the graph nor your own
lists have an opinion about. `deny` turns the resolver into an allow-list for the names the
graph has not judged.

```bash
whisper policy --default deny
```

## `block`

Domain names, and nothing else. An entry covers the domain and every name under it, so
`evil.example` already covers `a.evil.example`. The `*.evil.example` spelling is accepted
and means the same rule.

```bash
whisper policy --block ads.example.com --block telemetry.example.net
```

Categories and geography are not list entries. An entry of `tor-exit` here blocks a domain
literally named `tor-exit` and nothing more. Those rules live in `bundles`, below.

## `allow`

Same shape as `block`, and an explicit allow wins over a block. It cannot reopen a name the
graph places in a top band: policy narrows a verdict and never widens it, as
[How Resolution Works](/docs/network/resolver/how-it-works) sets out.

```bash
whisper policy --allow api.example.com
```

## `mode`

How names are resolved once the verdict is in.

| Value | Behaviour |
|---|---|
| `hybrid` | Ask the graph, then fall through to ordinary recursive resolution for anything it has no opinion on. |
| `graph-only` | Answer from the graph alone, and return REFUSED with extended DNS error 17 when it has nothing. |
| `always-forward` | Forward the lookup to ordinary recursive resolution. |

```bash
whisper policy --mode hybrid
```

## `allow_sources`

Which source addresses or prefixes may use your account's dedicated resolver address on
port 53. With no list, any source may. A source that is not on the list gets the same answer
an address with no account would get, so adding the list is a narrowing change and worth
testing from one of your own hosts first. There is no CLI flag; send it on the call.

```whisper-call
CALL whisper.agents({op: 'policy', args: {allow_sources: ['203.0.113.0/24', '2001:db8:1::/48']}})
```

## `retention`

How long ordinary query logs are kept for the account, in days. Set it when you mint an
agent or a device, or change it later here.

```bash
whisper policy --retention <days>
```

## `bundles`

Category and geography rules travel in their own argument, with a fixed catalogue. The CLI
has no flag for them, so they are set on the control-plane call.

| Bundle | What it covers |
|---|---|
| `block:tor-exits` | names that resolve to anonymising exit infrastructure |
| `block:bulletproof` | names hosted in networks that will not act on abuse |
| `block:rpki-invalid` | names whose addresses are routed with an invalid origin authorisation |
| `block:sanctions` | names associated with sanctioned parties |
| `block:newly-registered` | names registered very recently |
| `geo:deny:<CC>,<CC>` | names resolving into the listed countries |
| `geo:allow:<CC>,<CC>` | names resolving only into the listed countries |

A deny wins over an allow when both could apply.

```whisper-call
CALL whisper.agents({op: 'policy', args: {bundles: ['block:tor-exits', 'block:sanctions', 'geo:allow:NL,DE']}})
```

## Writing it in one call

Everything above can go on a single write, which is the form to put in a deployment script:

```whisper-call
CALL whisper.agents({op: 'policy', args: {default: 'deny', block: ['ads.example.com'], allow: ['api.example.com'], mode: 'hybrid'}})
```

The envelope this returns, and the key that is allowed to send it, are on
[Set Policy](/docs/control-plane/operations/policy) and
[Keys and Scopes](/docs/control-plane/auth).
