Inspiration

Every AI image becomes an orphan the moment someone screenshots it. Metadata provenance like C2PA and EXIF dies at the first crop, re-encode, or messaging app. And your generation history lives in someone's SaaS database that can be edited, purged, or shut down. We wanted the opposite: assets born with a verifiable record, stored somewhere that even the operator cannot rewrite, and recoverable even from a mangled copy. The insight that made it click: you do not need a blockchain for tamper-proof memory. A $6/TB storage bucket with Object Lock in compliance mode already refuses everyone, including us

What it does

Litmus is a generation studio where every asset gets a signed birth certificate at the moment it exists. A vision judge scores each generation against your prompt and retries with its own critique folded into the prompt; every attempt, including the rejected ones, becomes an Ed25519-signed, hash-chained receipt sealed into a Backblaze B2 bucket with Object Lock in compliance mode. Hourly Merkle anchors bind all new records into a single locked root. Anyone can drop a file on the public verify page: an exact SHA-256 match proves the original bit for bit, and a perceptual hash recovers the full history from cropped, resized, re-encoded copies. One click exports the entire vault as a signed archive with an offline verifier that needs nothing from us to prove everything

How we built it

FastAPI on Python 3.11, with Genblaze orchestrating the pipeline: its AgentLoop drives the generate, judge, retry cycle, and we wrote two custom Genblaze SyncProviders of our own, one for Pollinations' free keyless image endpoint and one for Alibaba DashScope's async image tasks. The judge is qwen-vl-plus and narration text is qwen3.6-flash through DashScope's OpenAI-compatible endpoint, with ElevenLabs speaking the placard line. B2 holds three buckets over the S3 API: media, resumable run state, and the compliance-locked vault. Fingerprints are SHA-256 plus multi-crop perceptual hashes in SQLite. The frontend is React with a design system we call Ledger: one accent color, hairline borders, no gradients, receipts rendered like a bank book. The browser re-verifies every signature and Merkle inclusion proof itself with WebCrypto and noble-ed25519, so you do not have to trust our server.

Challenges we ran into

Provider survival was the big one. The hackathon's GMI credits were gone by the time we registered, and Gemini's free tier turned out to have zero image quota, so we rebuilt the provider layer twice mid-build and ended on a free image path with a paid failover. Compliance mode has no undo, so a bug that writes garbage writes it for the whole retention period; we schema-validate and sign before every locked write. Cross-language canonical JSON bit us: Python serializes 1.0 where JavaScript writes 1, which would have broken every in-browser signature check, so integral floats are normalized on all three verifiers. A judge call once hung forever because the client had no HTTP timeout. And our first crop test failed: a 24 percent crop measured 30 bits of Hamming distance against a 10-bit threshold. Storing perceptual hashes of each original at several center-crop levels brought the same mangled copy down to distance 4.

Accomplishments that we're proud of

Everything the pitch claims is demonstrated on the deployed app, live. We sealed a receipt and then tried to delete it with our own credentials: B2 answered AccessDenied. We screenshotted an output, cropped a quarter of it away, recompressed it, and the verify page resurrected its full birth certificate at 94 percent similarity. We killed the server mid-run and watched it resume from state stored in B2, skipping the receipts it had already sealed. The export's offline verifier checked 67 of 67 records with plain Python on a machine that had never seen the app. And the judge genuinely works as an audit trail: one production run shows scores of 68, then 65, then 78, with the two discarded candidates kept in the lineage forever.

What we learned

Write-once storage changes how you write software: validation moves in front of the write, because there is no cleanup job for a compliance-locked mistake. Provenance that lives inside file metadata is dead on arrival; provenance that lives in fingerprints survives whatever users do to the bytes. Canonical serialization across languages is a real cryptographic contract, and one invisible float ruins it. Provider fallback is a product feature, since APIs fail on exactly the day you demo. And a judging loop becomes far more valuable when you keep what it rejected, because the discards are the evidence that the process was real.

What's next for Litmus

Per-user signing keys, already schema'd in every manifest, so records attest the creator and non-repudiation cuts both ways: the service cannot forge your history, and you cannot disown what you sealed. C2PA embedding so the certificate travels inside the file as well as the vault. A public transparency log of Merkle roots, so even the operator's anchoring is auditable from outside. Then style capsules, a video pipeline, and embedding-based nearest-neighbor verification to scale matching past what perceptual hashes can hold.

Built With

  • fastapi
Share this project:

Updates