Inspiration
Monday morning. Legal blocks the summer launch hero.
You have the PNG. You don't have the proof - no prompt on record, no model name, no approver, no sidecar. Friday night was three browser tabs, the same brief pasted three times, forty dollars gone, and a Slack thread that ends with "Which model won?"
That's the gap we kept hitting: generation tools are excellent at output and terrible at accountability. Sponsors asked for reactive multi-provider pipelines with failover, streaming progress, and cryptographic provenance - not another single-model tab. EU AI Act Article 50 pushes machine-readable synthetic media marking into production timelines.
We built ProvLedger because campaigns need a ledger, not another generator.
What it does
ProvLedger is a provenance-aware AI media production ledger for creative teams and agencies.
The story in four beats
| Beat | What happens |
|---|---|
| Make | Generate across GMI Cloud and Google through Genblaze - single-step failover, image→video chains, video fan-out, image tournament (Seedream + Gemini + FLUX in parallel) |
| Compare | Every run is a branch in a version tree - prompt, model, cost, provider chain, parent lineage |
| Approve | Human review workflow - approve with a required reason stored as an immutable B2 decision sidecar |
| Prove | Public /verify/{content_hash}, embeddable badge, live tamper demo, C2PA + SHA-256 manifests |
Also built for real production
- Pre-spend dedup - identical bytes skip B2 re-upload; near-duplicate prompts suggest reuse before spend
- Semantic search over version embeddings
- Multi-workspace RBAC - team invites, scoped service keys, Postgres RLS
- Spend governance - budget gates before generation
- Compliance export - portable sidecar + EU AI Act disclosure fields
Problem intro for video
Record /demo-story first (~40s, 11 slides) - proof-first narrative before the live demo.
How we built it
Stack
| Layer | Technology |
|---|---|
| Frontend | Next.js 14 · TypeScript · App Router |
| API | Python 3.12 · FastAPI |
| Worker | RQ on Redis |
| Database | PostgreSQL (Supabase) + RLS |
| Auth | Supabase JWT (ES256 JWKS) |
| Storage | Backblaze B2 (S3-compatible, boto3 CAS) |
| Orchestration | Genblaze SDK (genblaze[gmicloud,google,…]) |
Architecture (one paragraph)
Browser talks to FastAPI with JWT + workspace header. Heavy generation runs in an RQ worker via pipeline/orchestrate.py. Postgres holds the version graph and governance; B2 holds bytes and immutable proof artifacts. Genblaze Pipeline.stream() publishes SSE events through Redis to GET /jobs/{id}/events.
Visual diagrams: open docs/diagrams/index.html - architecture, user flow, B2 layout, Genblaze modes, trust layers.
flowchart LR
Make[Make · Genblaze] --> Compare[Compare · Tournament]
Compare --> Approve[Approve · B2 sidecar]
Approve --> Prove[Prove · /verify]
Genblaze integration
- Curated provider catalog with preset chains (
fast/balanced/premium) Pipeline(max_concurrency=3)for image tournament and video fan-outstream_bridge.py→ Redis → SSE for live UI progress- Hybrid storage: CAS
assets/{sha256}+ GenblazeObjectStorageSinkdual-write toruns/ Manifest.verify()surfaced on public verify page- Agent QC loop (
agent_qc) retries until eval threshold (single-step path) - Chaos failover toggle for resilience demo
B2 integration
| Artifact | Key pattern | Notes |
|---|---|---|
| Media (CAS) | assets/{aa}/{sha256}.ext |
Dedup skip on existing hash |
| Manifest | manifests/{sha256}.json |
Object Lock (governance) |
| Decision packet | decisions/{sha256}.json |
Human approval evidence |
| Sidecars | portable/, genblaze/manifests/ |
Export + SDK verify |
| Run logs | logs/{version_id}.json |
Provider chain diagnostics |
Also: lifecycle rules, event notification webhook, presigned private access.
Trust surface
- Authenticated verify on asset provenance panel
- Public
GET /public/verify/{hash}- no login - Tamper demo corrupts bytes in-memory; B2 audit record survives
- Embeddable badge:
GET /public/badge/{hash}.js
Built with
backblaze-b2 · genblaze · fastapi · next.js · python · typescript · postgresql · redis · c2pa · object-lock · server-sent-events · docker · pytest · supabase · gmi-cloud · google-gemini
Providers & models
| Modality | Provider | Models used in demo |
|---|---|---|
| Image | GMI Cloud | seedream-5.0-lite, flux-kontext-pro |
| Image | gemini-2.5-flash-image, Imagen family |
|
| Video | GMI Cloud | Seedance, Kling i2v, Wan i2v, PixVerse |
| Video | Veo 3.x | |
| Audio | ElevenLabs / GMI | TTS via catalog |
| QC | Eval gate | OpenCLIP similarity + optional Gemini judge |
List dynamically at runtime: GET /providers
Demo walkthrough (what to click)
See DEMO-SEED-CHECKLIST.md for exact prompts.
/demo-story- 40s animated problem (optional in video)- Dashboard → asset Summer launch hero
- Generate → Pipeline: Image tournament
- Watch SSE progress - three models concurrent
- Tournament compare → pick winner → Request review
- Approve with reason: "Best brand fit; tournament winner matches summer launch brief."
- Copy hash →
/verify/{hash}→ Tamper demo - Export compliance bundle (optional)
Challenges we ran into
- Hybrid ledger vs Genblaze samples - Sponsor repos use hierarchical
runs/keys; we needed CAS dedup across workspaces. Solution: dual-write manifests + Genblaze sidecar pattern (genblaze_sidecar.py). - Windows + Upstash Redis - SSL cert verification required certifi bundle in
redis_client.py. - Failover visibility - Judges need to see recovery - we added chaos toggle and provider chain UI.
- Approval as evidence - Approving without a reason felt like theater - we require decision text and store it on B2 with Object Lock.
- Provider quota limits during demo prep - Tournament degrades gracefully when one model 429s; at least one variant still lands for verify path.
Accomplishments we're proud of
- Deepest version tree + dedup + search + spend governance in the hackathon field
- Image tournament + video fan-out in one product with live SSE
- Public verify + tamper demo + embed badge - no login required
- Real B2 CAS savings (reuse skips re-upload)
- 11-slide proof-first story at
/demo-storyfor video intro - 30+ automated tests including public verify and approval gates
- Judge-ready HTML architecture diagrams in
docs/diagrams/
What we learned
Judges optimize for a 60-second click path, not architecture essays. We learned to lead with tournament → approve → verify, and keep platform breadth for follow-up questions.
Genblaze's manifest model is the right atomic unit for provenance - our job was connecting it to team workflows (review, budgets, reuse) and B2 durability.
The story that lands: "Had the PNG. No proof to ship." - then show the verify link.
What's next
- Full ObjectStorageSink migration path (documented in GENBLAZE-FEEDBACK-ISSUE.md)
- Trusted C2PA production certificate chain
- Identity-anchor reuse for episodic campaigns
- Campaign replay across assets for agency workflows
Built With
- backblaze-b2
- c2pa
- docker
- fastapi
- genblaze
- gmi-cloud
- google-gemini
- next.js
- object-lock
- postgresql
- pytest
- python
- redis
- server-sent-events
- supabase
- typescript

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