> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tallychannel.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Snapshots & Versioning

> How identity state is stored as an immutable, hash-linked ledger.

Every write to a subject's identity state creates a new **snapshot** — an immutable, versioned record of the full envelope at that point in time. Snapshots are never modified after creation.

## Snapshot anatomy

Each snapshot has:

| Field              | Description                                                      |
| ------------------ | ---------------------------------------------------------------- |
| `snapshot_id`      | Deterministic UUIDv5 derived from the subject and patch content. |
| `snapshot_version` | Monotonically increasing integer per subject, starting at 1.     |
| `generated_at`     | Deterministic timestamp.                                         |
| `envelope_hash`    | SHA-256 over the RFC 8785 (JCS) canonicalized envelope.          |
| `prev_hash`        | Hash of the preceding snapshot envelope — forms the chain.       |
| `envelope`         | The full `entityStateEnvelopeV1` payload.                        |

## Update flow

State changes use a two-step propose-and-apply flow:

```
Propose update → Store proposal → Apply proposal → New snapshot (version N+1)
```

**Propose** — submit RFC 6902 JSON Patch operations against the current state. The proposal is stored but not applied. You must supply the current `base_snapshot_version`; stale proposals are rejected with 409.

**Apply** — execute the proposal. The platform validates, applies the patch transactionally, computes the new hash and prev\_hash, and persists the snapshot. Concurrent applies are serialized — a second apply against a stale base is rejected.

Only `add`, `replace`, and `remove` operations are supported. `copy`, `move`, and `test` are not.

## Reading snapshots

| Endpoint                          | Use case                                                             |
| --------------------------------- | -------------------------------------------------------------------- |
| `GET .../snapshots/latest`        | Current state — most common read pattern.                            |
| `GET .../snapshots`               | Full history — paginated list of headers or full envelopes.          |
| `GET .../snapshots/{snapshot_id}` | Specific version by UUID. Requires `read_snapshot_by_id` scope.      |
| `GET .../snapshots/export`        | All snapshots in one bundle — for offline verification.              |
| `GET .../chain-proof`             | Ordered list of hash/prev\_hash values for independent verification. |
| `GET .../diff`                    | RFC 6902 diff between any two versions.                              |

The `view` parameter controls response size: `full` returns the complete envelope, `header` returns metadata only.

## Verification

Pass `verify=hash` on any snapshot read to have the server re-compute the RFC 8785 hash and compare it against the stored value. Pass `verify=chain` to validate the full prev\_hash chain back to the root.

See [Integrity Verification](/concepts/verification) for details.
