# The policy model

The vault has two distinct policy systems. Both share the same principles and the same workflow, but they govern different things.

## Administrative Policy

Administrative Policy answers: **who can perform which actions?**

It replaces role-based access control with a more flexible model. Instead of assigning named roles, you write rules that map groups of users to specific actions.

Every action in the vault is covered: creating users, importing keys, freezing keys, editing policies, exporting the audit log, and more. The full list of actions is in the [Administrative Policy guide](/guide/admin-policy/understanding).

Administrative Policy is **deny by default**. If no rule permits an action, nobody can perform it. The only pre-configured exception is `modify_admin_policy`, which is set to allow the initial Admins group during bootstrap. From there, the first admins configure everything else.

**Example:** To let the Risk team freeze keys in an emergency but keep unfreeze to a smaller senior group, you write two rules:

* Action `freeze_keys`: allow group "Risk Team".
* Action `unfreeze_keys`: allow group "Senior Admins" only.

## Signing Policy

Signing Policy answers: **how may a key be used to sign?**

Rules are evaluated top to bottom; the first matching rule wins. Each rule specifies:

* Which users (by group) are making the request.
* Which keys (by security group) are being signed with.
* The result: **Approve**, **Deny**, or **External Rule Server** (delegate to your own decision service).

Security groups are named collections of keys. A key must belong to a security group to be signed through that group's Signing Policy.

Signing Policy is also deny by default. A signing request that matches no rule is blocked by the implicit final "deny all" rule.

For details on each rule type, including the External Rule Server, see the [Signing Policy guide](/guide/signing-policy/understanding).

## Shared principles

Both policy systems share the same foundational properties:

**Deny by default.** An empty policy blocks everything. You explicitly grant what is allowed.

**Passkey-signed edits.** Changing a policy requires a WebAuthn passkey assertion. This ensures that a stolen browser session cannot silently modify policy.

**One pending draft at a time.** You cannot have two simultaneous in-flight changes to the same policy type. This prevents conflicts and makes changes auditable.

**2-of-3 enforcement.** Policy decisions are evaluated independently by each of the three Policy Server nodes, and Key Stores verify the 2-of-3 signatures before signing. No single node can override policy.

## The draft lifecycle

Policy changes are staged in a draft, then submitted as a single atomic change:

![Policy draft lifecycle state diagram: No Draft, Draft, Active](/img/diagrams/policy-draft-lifecycle.svg)

```mmd
stateDiagram-v2
    [*] --> NoDraft : initial state
    NoDraft --> Draft : Create draft
    Draft --> Draft : Edit rules (passkey-signed)
    Draft --> Active : Submit (atomic activation)
    Active --> Draft : Create new draft (current policy stays active)

    note right of Draft
        Edits are staged in the draft;
        the active policy keeps applying.
    end note

    note right of Active
        New rules replace old ones
        in a single transaction.
    end note
```

*Editing happens in a draft; submitting activates it atomically, with the new rules replacing the old in one transaction.*

1. **Create.** Enter edit mode. The current active policy keeps applying while you work.
2. **Edit.** Add, remove, or reorder rules. Every edit requires a passkey assertion.
3. **Submit.** Sign and submit the draft. The new policy activates atomically, replacing the previous one in a single transaction. Optimistic locking (a `previous_version` field) rejects the submit if the active policy changed under you, so you re-open the draft and reapply.

## Where to configure policies

**Web app:** Administrative Policy lives at `/admin-policy`. Signing Policy lives at `/signing-policy`. Both show the current active rules and an "Edit Policy" button to enter draft mode.

**API:** Administrative Policy is at `PUT /v1/admin-policies`. Signing Policy is at `PUT /v1/signing-policies/{policy_id}`. Both use optimistic locking via a `previous_version` field to prevent concurrent overwrites.
