Inspiration

Two regulations landed almost together: India's IT Rules Amendment 2026, which legally defines "synthetically generated information" and requires visible labeling plus embedded provenance metadata, and the EU AI Act's Article 50 marking obligations, in force from August 2, 2026. Neither generative tools nor object storage on their own answer the question a marketing lead, journalist, or compliance officer actually asks: is this exact file the one we approved, and can I prove it to someone else? We wanted a Genblaze + B2 project that produced a receipt for every asset, not just an asset

What it does

Notary generates AI images and video, and for every output it locks a tamper-evident provenance record in Backblaze B2 with Object Lock (provider, model, prompt, parameters, timestamp) so it can never be altered, not even by us.

On top of that record it adds three things neither Genblaze nor B2 give you out of the box: a Compliance Engine that scores every asset against India's IT Rules 2026 (5 checks) and EU AI Act Article 50 (4 checks) with concrete remediation, not a checkbox; AI Forensic Verification, where a hash mismatch triggers a Gemini Vision comparison against the canonical original that explains what changed instead of just saying "no match"; and a Public Verification Portal, a no-login link anyone can open and drag a file into, hashed client-side so nothing has to leave the browser unless verification fails.

Beyond that: a navigable remix/lineage DAG (every regeneration links to its parent via Genblaze's from_result()), a downloadable HTML provenance certificate, an embeddable SVG trust badge, a live dashboard tracking per-provider success rate and latency, and an admin tool that re-verifies every manifest across the whole B2 bucket on demand.

How we built it

FastAPI backend, React/Vite frontend. Every generation goes through Genblaze's Pipeline/Step/Run abstraction, writing through an ObjectStorageSink into a B2 bucket created with File Lock enabled at creation (the one B2 setting that can't be retrofitted, so it was step one).

Image generation runs a resilience cascade: Google Gemini (multi-key rotation) first, then NVIDIA NIM FLUX.1 Schnell, then a Hugging Face Space running FLUX.2-klein-4B, then Pollinations FLUX as a last resort. A dead key or rate limit on one provider never fails the request. Video runs through Veo on the same pipeline.

Image provenance needed a two-record chain, because embedding a manifest into a file changes the file's bytes, which changes its hash. We write M0 (the raw generation manifest) first, embed it into the image, then write M1, a locked receipt whose parent is M0 and whose hash covers the actual final bytes the user gets. Verification always checks against M1. Everything durable lives in B2; a SQLite cache is a disposable read-index, rebuildable from B2 on demand via genblaze index. B2, not the cache, is the source of truth.

Challenges we ran into

The manifest/hash paradox (embedding a record changes the hash it would need to describe) was the hardest design problem; we tried a couple of wrong approaches before landing on the M0/M1 chain, and wrote regression tests around a deliberately corrupted file to confirm a single-byte change after embedding always fails cleanly. Provider reliability during a live build is genuinely unpredictable: free-tier keys hit quota mid-test, a Hugging Face Space goes cold. The fallback cascade wasn't optional polish; it was required to have a working app at all. We were also careful not to overclaim: it would've been easy to imply C2PA-standard signing when we don't do that, so the compliance module reports gaps as gaps by default rather than silently passing.

Accomplishments that we're proud of

Every claim is enforced in code, not just described in a doc: a blocked policy prompt never reaches a provider or B2, a failed hash is never marked verified. The public verification portal needs no account at all; an outside stranger can independently confirm provenance on any asset we generate. We shipped meaningfully past our original plan: the lineage DAG, certificate export, trust badge, and dashboard weren't in scope originally, but B2 + Genblaze made them cheap to add once the core chain worked.

What we learned

How much a two-record manifest chain simplifies tamper-evidence once you accept that a file's hash and its own embedded provenance can never describe each other. That resilience against provider failure has to be designed in from day one: a generative app with a single provider is a demo, not a product. How much daylight there still is between "we stored a manifest" and "we're actually compliant," which is exactly the gap the Compliance Engine exists to make explicit.

What's next for Notary

Embed a real C2PA content credential inside the file itself, closing the one gap we currently report honestly as partial. Batch/API access for teams notarizing AI media at pipeline scale. Webhook alerts when a public verification fails, so a brand finds out about a tampered asset before their audience does.

Built With

  • aiosqlite
  • axios
  • backblaze-b2
  • fastapi
  • flux
  • genblaze
  • google-gemini
  • google-veo
  • httpx
  • hugging-face
  • nvidia-nim
  • pollinations
  • pydantic
  • python
  • react
  • react-router-dom
  • sqlite
  • uvicorn
  • vite
Share this project:

Updates

posted an update

Major Milestone Update: Delivered C2PA Signing, Ed25519 Trust Anchors, COMPLIANCE Lock & Developer Hub

Since our initial submission, we didn't just polish the project — we shipped the exact features listed under "What's Next for Notary", taking Notary from an already strong prototype to a production-grade, enterprise-ready media provenance platform.

Here is what we engineered and shipped in the latest codebase update:

1. Full C2PA Content Credentials Signing & Claim Inspector (Delivered "What's Next" Gap!)

In our original submission, we noted that C2PA embedding was our biggest open target. It is now 100% delivered and verified in code.

  • JUMBF Metadata Injection: Built c2pa_signer.py using c2pa-python to inject standard C2PA JUMBF metadata headers into watermarked assets backed by an X.509 ES256 leaf + root CA certificate chain (es256_certs.pem + c2pa_root_ca.pem).
  • EU AI Act Article 50: Fully satisfies requirement EU-ART50-02 (Machine-readable marking), bringing our compliance engine to a 100% pass score (9/9 checks) across EU AI Act Art. 50 and India IT Rules 2026.
  • C2PA Claim Inspector UI: Built a real-time C2PA claim inspector component into both the internal Asset page and the Public Verification Portal.

2. Ed25519 Independent Digital Signatures & Open Trust Anchor

To protect against unauthorized B2 bucket tampers or compromised storage credentials, we added an independent cryptographic layer in signing.py:

  • Ed25519 Keypair Signing: Every manifest is signed with a high-security Ed25519 private key before B2 write.
  • Open Public Key Endpoint: Public keys are served via GET /.well-known/notary-public-key.pem so third-party auditors can independently verify signature authenticity offline.

3. Steganographic & Visual Watermarking

  • Built watermark.py using Pillow to automatically overlay a pill-shaped visual disclosure badge onto generated images prior to M0 manifest embedding.
  • Fulfills India IT Rules 2026 requirement IN-SGI-02 (Visible labeling) directly in the pixel pipeline.

4. Upgraded Storage Security: B2 COMPLIANCE Mode Lock

  • Upgraded Backblaze B2 Object Lock from GOVERNANCE to COMPLIANCE mode.
  • WORM (Write Once Read Many) immutability is strictly enforced — manifests and assets cannot be deleted or modified during their retention period by anyone, including root storage keys.

5. "Cinematic Developer Noir" Landing Page

  • Built a high-impact landing page at / featuring a 3D WebGL background animation (spinning silver icosahedron with a glowing pulsating orange core).
  • Custom glassmorphism card hover interactions, Lucide React icon integration, and fluid responsive layouts.

6. Interactive Documentation Hub (/docs)

  • Added a full-featured documentation reader at /docs backed directly by our technical specification.
  • Includes a live text search filter, sticky table of contents with scroll-spy, and one-click copy-to-clipboard API cURL code blocks.

Summary of What Judges Can Test Live Now:

  1. Live App: https://notary-swart.vercel.app/
  2. Interactive Docs Hub: https://notary-swart.vercel.app/docs
  3. Public Ed25519 Key Endpoint: https://notary-swart.vercel.app/.well-known/notary-public-key.pem
  4. GitHub Repo: https://github.com/Ksalgotra1/Notary

Note: The deployment links will be available in some time, however the code changes are already in place and testing is underway.

Log in or sign up for Devpost to join the conversation.