← PRODUCT
PRODUCT · PROVE

GateAttestthe published anchor

A daily Merkle root over every Decision Receipt, published and never changed — so a receipt cannot be backdated.

DECISION RECEIPTinput hasha1b2…9flist snapshotsha256:2b44…coverage9 dimensionspolicybroker-v1.1decisionREVIEWed25519signatureanyoneverifiesintegrity you can prove — not a screenshot
On this page

What it does

Once a day, every Decision Receipt written so far is hashed into an RFC 6962 Merkle tree and the root — a single 32-byte number — is published at /attestations, where it is never rewritten. Each receipt becomes one leaf of that tree.

Anyone holding a receipt can ask /api/public/attestations/{receiptId} for its inclusion proof: the sibling hashes that fold the receipt up to the published root. No API key, because the party being audited should not control whether the check can run, and no tenant data, because a leaf is the SHA-256 of a receipt and a sibling is the SHA-256 of somebody else's.

The receipt verifier runs the whole thing in the browser: it recomputes the leaf from the pasted receipt, folds the proof, and shows the root it reaches so it can be compared with the published list.

Why a broker needs it

A signature proves the content of a record; it cannot prove the date, because the party holding the signing key can sign anything at any time and put an earlier timestamp inside it. That is the first objection a competent examiner raises about any vendor's "tamper-proof" evidence, and it is usually met with a shrug. A published root answers it arithmetically: the number went out before the deposit in question was ever made, and no key can make a receipt written afterwards fold up to it.

How it works

The leaf is SHA-256(0x00 || "kytgate.receipt.v1\n" || the canonical receipt JSON without its signature || "\n" || the signature); inner nodes are SHA-256(0x01 || left || right). That is RFC 6962 — the Certificate Transparency construction — chosen over the Bitcoin-style tree because the latter duplicates the last node on odd levels and therefore has a known root collision. Batches span every tenant on purpose: one shared public number leaks nothing about volumes and is the thing that can be pinned externally.

A receipt missed by one run is picked up by the next: membership is determined by whether a leaf already exists for it, not by a time window, so nothing falls through a gap.

Try it without an account: Published anchors (live) · Decision Receipt verifier (in-browser, no account).

What it does not do

An anchor proves a receipt existed by the time its root was published and has not changed since. It does not prove the decision was right, and it says nothing about receipts that are NOT in a batch — a root proves what is in it, never what is missing. A root published only by KYTGate is a tamper-evident log, not third-party proof: the useful thing an auditor does with it is record today's root somewhere KYTGate does not control. External pinning (a chain transaction, a timestamping authority) is reported per batch when present and is not claimed when absent.

API

GET /api/public/attestations
{ "algorithm": "rfc6962-sha256", "batches": [
  { "period": "2026-09-11", "seq": 0, "root": "5dc9da79…", "leafCount": 1284, "coversTo": "…" } ] }

GET /api/public/attestations/{receiptId}
{ "anchored": true, "leafIndex": 417, "leafHash": "…",
  "proof": [ "…", "…" ], "batch": { "root": "5dc9da79…", "leafCount": 1284, … } }

Full reference: /docs#attest · OpenAPI 3.1

Try the sandboxRead the API docsRequest early access