# Configuration versions

> Every change to a zone creates a numbered version with its author, reason, action and a full snapshot of the configuration.

Each zone has a version counter that starts at 1 when the zone is added. Every write that changes the zone's configuration, applied by a person, an API token or OpenWAF itself, increases it by one and stores the new version. The zone's current version is the one its edge nodes must serve.

## What a version records

| Field | Meaning |
|---|---|
| `version` | The number, consecutive per zone. |
| `created_at` | When the change was committed. |
| `actor` | Who made it: `user:<id>` for a person signed in to the dashboard, `token:<id>` for an API token (CLI, SDK, scripts, MCP clients), `system:<name>` for automatic changes such as certificate issuance (`system:acme`). |
| `action` | What kind of change it was, such as `record.create`, `zone.edge.update` or `zone.revert`. See [Version actions](https://developers.openwaf.dev/change-control/version-actions/). |
| `reason` | The reason given with the change, 1–500 characters. |
| `restored_from` | For a revert, the version whose configuration was restored; otherwise `null`. |
| `channel` | `mcp` when the change came through the MCP server; absent otherwise. |
| `snapshot_sha256` | SHA-256 of the canonical snapshot. Two versions with the same hash hold the same configuration. |
| `snapshot` | The full configuration of the zone at that version (only when you read a single version). |

## What the snapshot contains

The snapshot is canonical JSON: keys sorted and lists ordered by a stable identity, so the same configuration always produces the same bytes and the same hash. It contains:

- the zone's identity: id, name and DNS mode (delegated or external);
- its edge settings, including the settings of individual names and their rate limiting rules, cache, redirects, real user monitoring and AI agents settings;
- its edge rules (IP, country, WAF exceptions, rate limits), with their ids;
- its DNS records, with their ids, comments and tags;
- the groups of edge nodes that serve it;
- a reference to each certificate: hostname, source (ACME or manual), SHA-256 fingerprint and expiry date.

> **Note: No secrets**
>
> Certificate material and private keys, API tokens and other secrets are never stored in a version. Certificates appear by reference only, which is why a revert does not restore them (see [Revert a zone](https://developers.openwaf.dev/change-control/revert-a-zone/#certificates)).


## What is not versioned

Some changes are not zone configuration, so they create no version. They are still recorded in the [audit log](https://developers.openwaf.dev/change-control/audit-log/):

- the zone's status (pending, active, disabled), which follows the delegation or ownership check;
- cache purges (a revert never brings purged content back);
- origin certificates issued by the OpenWAF Origin CA, and their revocation;
- organisation-level changes: members, invitations, API tokens, clients, brand and white-label settings.

## Writes that change nothing

If a write leaves the configuration exactly as it was (same snapshot hash), no version is created. Its simulation reports the same `from_version` and `to_version` with an empty diff, and the audit entry is marked `"unchanged": true`.

## Deleted zones

Deleting a zone creates one last version with action `zone.delete`: the zone's identity with no settings and empty lists. The history outlives the zone, and your organisation can still read it by zone id:

```sh
openwaf-cloud ctl zones history 3f1c2a9e-0000-4000-8000-000000000000
```

## Read versions

| Interface | List | One version with its snapshot | Diff |
|---|---|---|---|
| Dashboard | **Changes → History** | **Snapshot** on a row | **Compare versions** |
| CLI | `zones history <zone>` | `zones history <zone> <version>` | `zones diff <zone> <from> [<to>]` |
| API | `GET /v1/orgs/{org}/zones/{zone}/versions` | `GET …/versions/{version}` | `GET …/diff?from=N&to=M` |
| MCP | `zone_history` | — | `zone_diff` |

Any role can read the history of the zones it can see. Step-by-step: [View history and compare versions](https://developers.openwaf.dev/change-control/view-history/).
