← Trust Layer
Open spec · v1

The Trust Receipt format.

A Trust Receipt is a signed statement about an AI tool, prompt, or piece of content. It is designed so anyone can verify it independently, offline, without trusting queldrex.com. The format is open and MIT-licensed on purpose: a trust claim you cannot check yourself is worthless.

Structure

A receipt is an object with a signed payload plus the signature and the public key needed to check it.

{
  "payload": {
    "id": "rcpt_<32 hex>",
    "version": 1,
    "issuer": "queldrex",
    "ruleset": { "id": "queldrex:baseline", "version": "2026.07.1" },
    "subject": { "kind": "mcp_tool|text|content", "name": "...", "hash": "<sha256>" },
    "verdict": "safe|unsafe|uncertain",
    "riskScore": 0,
    "confidence": "low|moderate|high",
    "reasonCodes": ["tool_poisoning.hidden_instruction", "..."],
    "detectors": ["mcp-tool@1", "model-judge@1", "..."],
    "issuedAt": "<ISO 8601>",
    "expiresAt": "<ISO 8601>"
  },
  "algorithm": "ed25519",
  "keyId": "<key id, for rotation>",
  "signature": "<base64 Ed25519 signature over the signing input; see Canonicalization>",
  "publicKey": "<base64 SPKI DER Ed25519 public key>",
  "canon": "jcs-1"
}

Canonicalization

Current receipts carry canon: "jcs-1". The signed bytes are the scheme tag jcs-1\n followed by the RFC 8785 (JCS) canonical JSON of the payload: object keys sorted recursively by UTF-16 code unit, array order preserved, numbers restricted to safe-range integers, and strings JSON-escaped with lone UTF-16 surrogates rejected. The tag binds the scheme into the signature, so the canon field cannot be silently downgraded. A receipt with no canon predates this scheme; verify it with the legacy form (top-level keys sorted, then JSON.stringify). The exact reference implementation is @queldrex/verify.

// canon "jcs-1": RFC 8785 JSON Canonicalization Scheme
function jcsStr(s) {                            // reject lone UTF-16 surrogates
  if (!s.isWellFormed()) throw new Error('lone surrogate')
  return JSON.stringify(s)
}
function jcs(v) {
  if (v === null) return 'null'
  if (typeof v === 'boolean') return v ? 'true' : 'false'
  if (typeof v === 'number') {                  // safe integers only
    if (!Number.isSafeInteger(v)) throw new Error('numbers must be safe integers')
    return String(v)
  }
  if (typeof v === 'string') return jcsStr(v)
  if (Array.isArray(v)) return '[' + v.map(jcs).join(',') + ']'
  const keys = Object.keys(v).sort()            // recursive, UTF-16 code-unit order
  return '{' + keys.map(k => jcsStr(k) + ':' + jcs(v[k])).join(',') + '}'
}
// signed bytes = scheme tag + JCS. Legacy receipts (no "canon") use the old
// top-level-only sort + JSON.stringify.
const input = receipt.canon === 'jcs-1' ? 'jcs-1\n' + jcs(receipt.payload) : legacy(receipt.payload)
// verify: Ed25519.verify(signature, input, publicKey)

Verify it yourself

Use the zero-dependency reference verifier, or the two lines above with any Ed25519 library.

npm i @queldrex/verify

import { verify } from '@queldrex/verify'
const res = await fetch('https://queldrex.com/api/trust/receipt/<id>').then(r => r.json())
const { valid, signatureValid, expired, issuerConfirmed } =
  await verify(res.receipt, { checkIssuer: true })

To confirm a receipt is genuinely ours (not just internally valid), compare its publicKey against our published key at /api/trust/pubkey. Bind to the publicKey only: keyId is a self-declared rotation hint the signature does not cover (and it is derived from the key), so trusting it would let a forger copy our published keyId while embedding their own key. Signed manifests (evidence bundles) use recursively-sorted-key JSON and verifyManifest.

Self-documentation (_verify)

So a file explains how to trust itself, artifacts carry a _verify block. In an evidence bundle it lives inside the signed manifest (tampering the instructions breaks the signature); in a receipt API response it lives in the envelope beside the untouched signed receipt. Either way it points to the same offline check.

"_verify": {
  "cli": "npx @queldrex/verify <this-file>.json",
  "spec": "https://queldrex.com/verify/spec",
  "publicKey": "https://queldrex.com/api/trust/pubkey",
  "algorithm": "ed25519"
}

If you adopt this format, follow the same convention so any holder of your receipts can verify them without reading your docs first.

Adopt the format

The spec and the verifier are open. Anyone can issue or check receipts in this format. Our aim is a common, verifiable receipt for AI trust decisions that outlives any one vendor, aligned with the DSSE / in-toto attestation envelope and the OpenID AuthZEN decision API. This is evidence, not a guarantee or legal advice.