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

# Verify

> What your change board can check without contacting Vexa — and exactly how.

**Every channel entry verifies offline** — the bundle carries its own trust material, and each entry ships these commands as a ready-to-run `VERIFY.md` with its own file names in. The chain: `channel.pub` reaches you out of band → it verifies `entry.json` → `entry.json` names the sha256 of every evidence file and every image digest, so one signature seals the bundle → the chart references those same digests → your Kyverno pins the same key at admission.

**1 — The entry is signed.** Steps 2–4 add no signatures; they recompute hashes against this sealed record.

```bash theme={null}
cosign verify-blob --key channel.pub \
  --bundle entry.json.sigstore.json --new-bundle-format entry.json
```

**2 — The evidence bundle is intact.** Recompute the sha256 of every file in `evidence/` and compare to `entry.json` — a nine-line script in `VERIFY.md`. A mismatch is a rejection.

**3 — The source provenance is real.** Proves the source archive was built from the stated public repository at the stated commit, attested by the build platform's identity, not Vexa's word.

```bash theme={null}
cosign verify-blob-attestation \
  --bundle evidence/source-provenance.sigstore.json --new-bundle-format \
  --type slsaprovenance1 \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com \
  --certificate-identity-regexp='^https://github.com/Vexa-ai/vexa/' \
  vexa-core-<version>.tar.gz
```

**4 — The digest set is the validated one.** The digest map's sha256 must equal the pin inside the delivery receipt from Vexa's own production run of this release.

**5 — The images carry the channel signature.** Same check your admission layer runs on every pod, same key; signatures live in the registry in the legacy format, with no transparency-log entry.

```bash theme={null}
COSIGN_REPOSITORY=channel.vexa.ai/vexa/channel/acme-stable/signatures \
cosign verify --key channel.pub --insecure-ignore-tlog=true \
  channel.vexa.ai/vexa/channel/acme-stable/<image>@sha256:<digest>
```

`COSIGN_REPOSITORY` is what points cosign at the signature repository instead of alongside the image; without it the command returns `no signatures found`. It is the same value your `install.sh --signature-repository` carries, and the entry's own `VERIFY.md` fills it in for you.

## On a PLATFORM ESTATE entry

An estate entry — one carrying an `estate` block, published from a running cluster rather than cut from a release tag — has no source archive, no SLSA provenance and no delivery receipt, so **steps 3 and 4 do not apply and `vexa-verify` says so out loud instead of skipping quietly.** Each absence is named in the signed document, so it is a statement you can hold us to:

```bash theme={null}
jq -r '.evidence_absent[] | "\(.kind): \(.reason)"' entry.json
```

What replaces them is a different claim, not a weaker one: the digest set is **captured from the running cluster**, per image, with its own receipt, and validated against a mandatory `validation_contract` named and hashed in the entry. **Your contract decides whether the absences are acceptable**, via `forbid_absent_evidence` — an estate-shaped contract lists `validation_contract` there, so an entry that declared *that* away is refused, and an OSS-shaped contract pointed at an estate refuses it correctly on its own terms. Annotated worked form: [`kit/verify/policy.example.yaml`](https://github.com/Vexa-ai/vexa-delivery/blob/main/kit/verify/policy.example.yaml).

## If step 1 fails on the bundle format

An entry signed by an older cosign carries a legacy bundle, rejected with `ecdsa: Invalid IEEE_P1363 encoded bytes` — a message that looks like a corrupt signature and is not one. Try:

```bash theme={null}
cosign verify-blob --key channel.pub --bundle entry.json.sigstore.json \
  --new-bundle-format=false --insecure-ignore-tlog=true entry.json
```

## Read before you accept

**`evidence_absent`** — kinds this release does not carry, each with a reason. **`break_glass`** — who authorised an incomplete chain, and why; a release with gaps and no break-glass record should be rejected by your verifier. **The delivery receipt** — which images served production traffic and which were validated in other harnesses; the claim is never rounded up.

Verification is digest- and signature-based, so it holds whichever registry served the bytes, your own mirror included. See [isolated networks](security#isolated-networks).

Next: [The station gate](station-gate) · [For your auditors](governance)
