VERIFY · LIVE
Put your events in the log
Any protocol can drop a hash of the thing that happened into the estate transparency log. It is two dependency-free files, a shaper you fill in, and one line to register — and nothing about your records ever reaches us.
The log is hashes, never content. A leaf is a 0x… sha256 and four fields of context — kind, source, time, and a ref back to your own record — and there is nowhere in it to put a name, an email or a balance. You hash your record; the fingerprint folds in; the bytes never leave your process. And we only ever pull: the fan-in fetches the URL you publish, the way a stranger would. There is no key to give us and no webhook to point at us.
1. Copy two files
The kit is exactly two dependency-free files — no package.json, no node_modules. Drop both into your repo:
- notary-kit.mjs — the CLI and the shaper helpers.
- vendor-notary.mjs — the canonical leaf format, byte-identical to the one the log is built from.
Dependency-free on purpose: the companies most likely to want a transparency log want a toolchain least. A test copies these two files alone into an empty directory and runs them with bare node, so this promise is checked, not claimed.
2. Scaffold, then fill the shaper
One command writes the shaper, an empty fragment, and the serving stub:
node notary-kit.mjs init --kind rite/1 --source rites --framework next
Then fill two functions in notary.shaper.mjs: loadRecords() returns your records, and canonicalise(record) returns the stable string a holder can rebuild to re-verify. The kit hashes that string into a content-free leaf and refuses any leaf that carries content — so “hashes, never content” is enforced, not remembered.
3. Serve the fragment, and verify it
Serve notary.fragment.json at your /.well-known/ path — from the process that holds the records (for a live database that is your API host, not a static build). Then confirm it will fold before you register it:
node notary-kit.mjs verify ./public/.well-known/notary.fragment.json
verify runs the exact check the fan-in runs — every leaf canonical, no content, no duplicates. A fragment that passes here folds; one that fails would be refused silently, which is the failure this command exists to stop.
4. Register one line
Print the registration line and add it to the fan-in’s source list. Three fields: your source slug, the URL you serve, and the leaf kind.
node notary-kit.mjs register --url https://you.example/.well-known/notary.fragment.json --kind rite/1 --source rites
No push access to this repository? Open a pull request adding that object to notary-sources.json, or submit the same three fields to the estate. This is still the right lane for an external, non-estate submitter — a fully public, unauthenticated registration path is a different, harder trust problem, since anyone could point the fan-in at an arbitrary URL. The shape either way is pinned by a published JSON Schema.
Already have push access here — an estate property, today? Skip the PR:
node scripts/register-notary-source.mjs --name rites --url https://you.example/.well-known/notary.fragment.json --kind rite/1
or run it as a workflow — Actions → Notary registration → Run workflow, with name, url and kind as inputs (checkpoint for a checkpoint-only source). Either way it fetches your URL live and validates it the exact way the fan-in does before writing anything, so a bad registration fails loudly with nothing landed, and a good one folds within minutes instead of waiting on a review. From then on the fan-in also fetches your URL on its own schedule; a run where you do not answer keeps your last fragment — unreachable is never read as “emitted nothing”.
That is the whole of it
Your leaves now fold into the same log as certificates, receipts and sealed heads, and each one resolves at verify a leaf the moment it lands. The full guide, including the live-database serving pattern and the consent rules, is docs/notary-adopter.md. The read side — head, inclusion and consistency proofs — is the read API, and it is RFC 6962, so any Certificate Transparency verifier already speaks it.