# Verifying Overturo signed records

An Overturo **signed record** is a durable, portable export of a decision — a
consent, a notice, or an authorization — carried in a JSON envelope with a
detached digital signature over its canonical bytes. Anyone can verify one: the
signature proves the record is exactly what Overturo issued, unaltered, and the
verification runs entirely in your own environment against Overturo's **published
keys** — no callback to us, no account, nothing sent back.

There are three ways to verify, from zero-install to fully programmatic.

## 1. The record debugger (zero install)

Paste or upload a signed record at **`/verify`** and watch it verify in your
browser. Nothing you paste ever leaves the page — verification is client-side,
and the page makes no network request while it checks your record. It states,
honestly, what was and wasn't checked: a green result means the signature checked
out against the published keys; an amber result means the record is only
*self-consistent* (it agrees with its own embedded key, which anyone can mint) —
never mistake one for the other. The debugger also ships a gallery of sample
records, including tampered ones, so you can watch a bad record fail.

## 2. The `@overturo/verify` library (programmatic)

The published `@overturo/verify` package verifies a signed record with one call:

```js
import { verifyRecord } from "@overturo/verify"

const result = await verifyRecord(rawText, { publishedKeys })
// result.recordType → "consent_record" | "notice_record" | "authorization_record"
// result.keyVersion → e.g. "us-1"
// result.keySource  → "supplied" (verified against the keys you passed)
```

Two rules matter:

- **Pass the raw text, never a parsed object.** Parsing a record and re-serialising
  it can silently change the bytes (a JSON parser may rewrite `5.0` as `5`), which
  breaks the signature. `verifyRecord` reads the raw text and canonicalises it
  itself.
- **Supply the published keys.** The `publishedKeys` map (key version → published
  key) is Overturo's — fetch it from the issuing region's published key list. A
  record also *carries* its own key, but verifying against only that embedded key
  proves internal consistency, not authorship: `allowEmbeddedKey: true` returns
  `keySource: "embedded"`, which you must present as "self-consistent — not
  verified," never as verified.

A record signed in one region carries a region-prefixed key version (`"eu-1"`),
so verify it against that region's published keys.

## 3. Runtime receipts

The dot-separated **runtime receipt** (a token returned inline at decision time)
is a different artifact: it verifies online, against the issuer's live published
keys, through the library's `verifyReceipt` path. The debugger recognises a
runtime receipt and points you here rather than failing it.

## Where to get a signed record

- **From a decision's receipt page** — use the "Download signed record" action.
- **From the API** — request a decision's receipt with `?flavor=signed` to get the
  signed export envelope (the same bytes the debugger and `@overturo/verify` read).
