# Rightshold Rights Receipt v1

Status: published, version `rights-receipt/1` · Spec text: CC-BY-4.0 · JSON Schema: CC0-1.0 · Schema: https://www.rightshold.com/schemas/rights-receipt-v1.json

A **Rights Receipt** is a small signed statement that travels with one asset an agent ships — an image, font, dataset, code file or model. It says: *these exact bytes* (SHA-256), from *this source*, under *this license*, were checked for *this intended use*, with *this verdict and these conditions*, by an agent at *this RS-KYA level*, and the statement was recorded on a public ledger at *this time*. Anyone can verify it offline with the issuer's public key.

It answers the question every client, platform and reviewer asks about agent output: **"Is this cleared to use, and can you prove it?"**

## 1. Envelope

```json
{
  "receipt": { ...signed fields below... },
  "signature": "<base64 Ed25519 signature>",
  "kid": "key_…", "alg": "EdDSA",
  "ledger": { "seq": 123, "commitment": "<hex>", "salt": "<hex>", "entry_url": "https://www.rightshold.com/v1/ledger/entries/123" }
}
```

## 2. Signed fields (`receipt`)

| Field | Meaning |
|---|---|
| `spec` | Always `rights-receipt/1` |
| `type` | `RightsReceipt` |
| `id` | `rcpt_` + 20 hex |
| `issuer`, `kid` | Issuer id and the JWKS key id that signed it |
| `issued_at`, `expires_at` | RFC 3339; receipts expire (default 90 days, max 365) because licenses and evidence change |
| `asset` | `sha256` (required), `kind` (image, font, dataset, code, model, audio, video, text, other), `name`, `media_type`, `source_url` |
| `license` | `spdx_id`, `url`, `resource_id` (a registered Rightshold resource) |
| `intended_use` | The exact uses checked (commercial_use, model_training, redistribution, …) |
| `verdict` | `allowed` · `blocked` · `needs_review` · `insufficient_evidence` |
| `conditions` | `duties` (e.g. attribution), ready-to-paste `attribution_text`, `unresolved` questions |
| `agent` | Issuing agent `id`, `number` and `kya_level` (RS-KYA L0–L5); L0 when no agent is named |
| `limitations` | Plain-language scope |

## 3. Signature

Ed25519 over the UTF-8 bytes of the canonical JSON of `receipt`: object keys sorted lexicographically, no whitespace, values serialised as JSON. Look up `kid` in https://www.rightshold.com/.well-known/jwks.json (`kty: OKP`, `crv: Ed25519`). A key with `status: retired` only vouches for receipts issued before its `retired_at`.

```js
const canon = (v) => v === null || typeof v !== "object" ? JSON.stringify(v)
  : Array.isArray(v) ? "[" + v.map(canon).join(",") + "]"
  : "{" + Object.keys(v).sort().map((k) => JSON.stringify(k) + ":" + canon(v[k])).join(",") + "}";
```

## 4. Ledger inclusion

The ledger entry `receipt.issued` holds `commitment = sha256("commit:" + canonical({opening: {receipt_sha256}, salt}))`, where `receipt_sha256 = sha256(canonical(receipt))`. Fetch `entry_url` for the entry and its Merkle inclusion proof against a signed block. This proves the receipt existed at that time without publishing its contents.

## 5. Verifying

1. Verify the signature (offline, §3). 2. Check `spec` and `expires_at`. 3. Hash the file you received and compare with `asset.sha256`. 4. Optionally check the ledger (§4), or call the free endpoint `POST https://www.rightshold.com/v1/receipts/verify` (or MCP `verify_rights_receipt`), which does all of it. 5. Treat `verdict: allowed` with its `conditions` as cleared; anything else is not.

## 6. Embedding conventions

| Where | Convention |
|---|---|
| Next to a file | Sidecar `<filename>.rights.json` containing the envelope (e.g. `logo.png.rights.json`) |
| HTTP response | `Rights-Receipt: <https://www.rightshold.com/v1/receipts/rcpt_…>; rel="rights-receipt"` or the same in a `Link` header |
| HTML page | `<link rel="rights-receipt" href="https://www.rightshold.com/v1/receipts/rcpt_…">` (one per asset; add `data-asset-sha256`) |
| C2PA / Content Credentials | Custom assertion label `com.rightshold.rights-receipt.v1` whose data is the envelope; `asset.sha256` must match the C2PA hard binding. A `model_training: blocked` verdict maps to `c2pa.training-mining` `notAllowed` |
| package.json | `"rightsReceipts": { "assets/logo.png": "assets/logo.png.rights.json" }` |
| Model card (YAML front matter) | `rights_receipts:` list of receipt URLs or sidecar paths, one per training dataset / base model |
| Agent deliverable / MCP result | Include the envelope under `rights_receipts[]` next to the asset reference |

## 7. Issuing

`POST https://www.rightshold.com/v1/receipts` (API key) or MCP `issue_rights_receipt`:

```json
{ "asset": { "sha256": "<hex>", "kind": "font", "name": "Inter.ttf" }, "license": "OFL-1.1",
  "intended_use": { "commercial_use": true }, "agent": "<your handle or RS number>",
  "attribution": { "title": "Inter", "author": "The Inter Project Authors" } }
```

Add `?quote=1` to get the price without issuing. Pricing: the decision is free; a signed receipt is in the "Signed rights manifest or Rights Receipt" line of https://www.rightshold.com/pricing (free allowance, then fractions of a cent). Verification is always free. For a whole deliverable with many inputs, use a rights manifest (`POST /v1/manifests`).

## 8. What a receipt is not

Not a license grant, not legal advice, and not a guarantee about facts outside the evidence it names. It is a signed, timestamped, verifiable record of what was checked and answered.

## 9. Versioning and license

Breaking changes get a new `spec` value (`rights-receipt/2`); verifiers must reject unknown major versions. Other issuers may implement this format; verifiers decide which issuers they trust. This text is licensed CC-BY-4.0; the JSON Schema is CC0-1.0.
