Keepsake protocol
Open specification for portable process provenance. Anyone can check offline — no account, no API key, no permission.
← Developers · Online verify · Offline HTML verifier
What a Keepsake documents
A Keepsake documents that process events and final delivery fingerprints were sealed through Yubikiri — either a completed commission room (claimType: commission.process) or solo work (claimType: session.process). It is process provenance. The full limits are set out in Disclaimers.
Versions
yubikiri.keepsake.v1— sealed commission or session manifestyubikiri.activity.v1— per-event hash-chain body (genesis stringyubikiri.activity.v1.genesis)yubikiri.log.v1— daily transparency-log Merkle commitmentyubikiri.inclusion.v1— archive inclusion-proof envelope
Canonical JSON
All signed payloads use deep key-sorted JSON: recursively sort object keys, then JSON.stringify with no extra whitespace. Arrays keep order. This is identical to stableStringify in the open-source cores.
Signed Keepsake manifest
Document shape: { claim, alg, signature, keyId?, signatures? }. Primary signature is Ed25519 over the canonical claim. An optional HS256 HMAC may also be attached for platform checks; offline verifiers only need Ed25519.
Public keys: /.well-known/yubikiri-keys.json. Signature encoding is unpadded base64url. Verify with the SPKI public key matching keyId.
claim.claimType = "commission.process"
claim.id = "yk_ks_…"
claim.tipEventHash / tipChainIndex / eventCount / chainRoot
claim.finalAssets[] = { assetId, sha256, contentCredentialId, fileName }
claim.verifyUrl = https://yubikiri.art/verify?keepsake=yk_ks_…
claim.disclaimer = process-provenance disclaimer (verbatim)Activity hash chain
Each activity event commits to the previous tip. Event hash = SHA-256 of the canonical body:
{
"v": 1,
"actorId": string | null,
"chainIndex": number,
"commissionId": string,
"message": string,
"meta": unknown | null,
"prevEventHash": string, // genesis for index 0
"type": string
}chainRoot = SHA-256 of the newline-joined ordered list of event hashes (hex). The sealed tip is the chain state at mint time; later KEEPSAKE_SEALED activity may extend the live chain without invalidating the sealed tip.
Transparency log (Merkle)
Daily trees use RFC 6962-style domain separation: leaf nodes hash 0x00 || documentHash; internal nodes hash 0x01 || left || right (raw bytes). Odd levels duplicate the last node. Document hash = SHA-256 of the canonical signed keepsake document (keepsakeDocumentHash).
Directory: /.well-known/yubikiri-log.json. Day records: GET /api/keepsake-log/YYYY-MM-DD and /api/keepsake-log/latest. Entries are { logIndex, keepsakeId, leafHash } — hashes only, no client PII.
Room archive proof bundle
keepsake/manifest.json # signed keepsake keepsake/activity-chain.json # sealed tip + event fields keepsake/inclusion-proof.json # anchored path or pending_anchor keepsake/verify.html # single-file offline verifier
Online APIs (free)
GET /api/verify/keepsake/yk_ks_…GET /api/verify/credential/yk_cc_…GET /api/verify/{sha256}— delivery fingerprint
Keepsake Seal embeds
Artists copy one HTML snippet under any posted final. The SVG lives at /api/embed/seal/yk_cc_… and should link to /verify?credential=yk_cc_…. Every seal on Carrd, X, or VGen is a crawlable backlink. The off-platform name is “Yubikiri Keepsake Seal.” No client names, prices, or file bytes.
<a href="https://yubikiri.art/verify?credential=yk_cc_..."> <img src="https://yubikiri.art/api/embed/seal/yk_cc_..." width="320" height="72" alt="Yubikiri Keepsake Seal" /> </a>
Keepsake records export
Authenticated GET /api/kept-passport returns yubikiri.kept.v1 JSON with asArtist and asClient sealed rooms (Keepsake ids, final-file ids, making-of URLs when consented). The API name is retained for compatibility; the UI calls this “Keepsake records.”
Offline tools
Open /keepsake-verify.html and drop a room archive ZIP or the keepsake/ JSON files. Or from a checkout of this repo:
npm run keepsake:verify -- ./path/to/room-archive.zip npm run keepsake:verify -- ./path/to/keepsake-dir --keys https://yubikiri.art/.well-known/yubikiri-keys.json
Claims discipline
Verification being free is permanent product policy. Never put Keepsake lookup behind a paywall. Monetization belongs around the record (workspace, payments, studio tools) — not on checking the math.