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

# Verification

> What GET /v1/projects/:id/evidence-packs/:packId/verify re-checks against a generated evidence pack — and, importantly, what it can't check at all.

A generated document is only useful to an auditor if it can be checked, not just trusted. `/verify` re-runs the checks a generated pack's own citations imply against your live data, and reports the result honestly — including admitting when it couldn't check something.

## What it checks

Click **Verify** next to any completed pack on the Compliance page, or call `GET /v1/projects/:id/evidence-packs/:packId/verify` directly. Two independent checks run:

1. **Content integrity** — the stored document is read back and re-hashed with SHA-256. If the recomputed hash doesn't match the hash recorded at generation time, `sha256Matches` is `false`: the stored bytes have changed since the document was generated (or the object couldn't be read at all).
2. **Citation survival** — every source record the document cited is re-resolved against your live data, scoped to the pack's project (or organization, for org-level sources like membership). A citation whose record is gone is reported as a **divergence**.

## Result fields

| Field                               | Meaning                                                                                                                                          |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `sha256Matches`                     | `true` when the recomputed hash of the stored document equals the hash recorded at generation time                                               |
| `storedSha256` / `recomputedSha256` | The two hashes being compared                                                                                                                    |
| `evidenceStillPresent`              | `true` only when zero divergences were found among **checked** citations — see `unverifiableRefs` below for what "checked" deliberately excludes |
| `checkedRefs`                       | Count of citations that were actually re-resolved against a live record                                                                          |
| `unverifiableRefs`                  | Count of citations that structurally cannot be re-checked at record level                                                                        |
| `divergences`                       | One entry per citation whose record is gone, each naming the source, id, label, and whether it's `missing` or `wrong_project`                    |
| `objectMissing`                     | `true` when the stored document itself couldn't be read back                                                                                     |

## `unverifiableRefs` — read this before you trust a clean result

Not every citation in a document points at a single database row that can be looked up again later. Two kinds of citation are structurally unverifiable:

* **ClickHouse aggregates.** A "models used" citation, for example, doesn't name one row — it names a synthetic key over an aggregate (a model, summed across a whole period). There's no single row to re-fetch, and re-running the aggregate would just compare a number the document already printed against itself, proving nothing about whether the underlying data changed.
* **Certain change-timeline events.** Prompt-deploy, agent-lifecycle, and externally-reported change events carry composite ids from their own source systems rather than an audit-log row. Audit-sourced change events *are* checkable — they resolve as ordinary audit-log citations for free.

These citations are **excluded from `evidenceStillPresent` entirely** — not counted as verified, not counted as failed. They're reported separately, in `unverifiableRefs`, specifically so a document with a hundred citations, ninety of them structurally uncheckable, doesn't come back reading like "the whole document checks out" just because the ten checkable ones passed. You — or your auditor — need to see that ninety citations were never re-checked at all, not just that the ten that could be were fine.

<Warning>
  `evidenceStillPresent: true` means every **checkable** citation still resolves. It does not mean every citation in the document was checked. Always read `unverifiableRefs` alongside it: a pack reporting `checkedRefs: 3` and `unverifiableRefs: 340` passed a much smaller check than one reporting `checkedRefs: 340` and `unverifiableRefs: 3` — even though both can legitimately report `evidenceStillPresent: true`.
</Warning>

## `missing` vs. `wrong_project`

When a cited record doesn't resolve inside the pack's own project (or org), `/verify` does one more lookup — unscoped, across every tenant — before deciding how to report the divergence:

* **`missing`** — the record doesn't exist anywhere. It was deleted.
* **`wrong_project`** — the record still exists, just not under this project anymore.

Reporting these as two distinct reasons means "the guardrail was deleted" and "the guardrail moved to another project" don't look like the same failure.

## Failure modes that don't error

`/verify` never throws for a data condition — a deleted record, a deleted storage object, or a pack that never finished generating are all *results*, not exceptions:

* A pack whose status isn't `completed` (or that has no stored object or hash yet) returns a result with everything `false`, `0`, or empty, rather than a partial or misleading pass.
* A resolver failure — a transient database error while re-checking one source — is not treated as proof those records are gone. Those citations move into `unverifiableRefs` for that check instead of being reported as false divergences.

## Next steps

* [Evidence packs](/compliance/evidence-packs) — generating the document `/verify` checks
* [Frameworks and controls](/compliance/frameworks) — the SOC 2 mapping behind control evidence documents
* [Compliance evidence limitations](/reference/compliance-limitations) — permanent gaps in what Zespan can report, distinct from what `/verify` can re-check
