Portable, independently verifiable creator credit for images. ProofLens reports claim binding, creator signature validity, reviewed ProofLens identity trust, and C2PA Content Credential validity/trust as four separate facts — never collapsed into one verdict.
- Separate evidence, never merged — ProofLens claim binding, creator ES256 signature validity, reviewed/revoked/expired ProofLens identity trust, and independent C2PA Content Credential validity/trust are each reported on their own.
- C2PA does not authenticate the human creator — the C2PA Content
Credential is signed by the ProofLens Generator Product, not the creator.
A cryptographically valid credential is
valid-untrustedunless an ecosystem independently trusts it. - Exact-file integrity — detached envelopes bind the signed file's SHA-256 and byte length; embedded provenance binds through the C2PA manifest/claim instead of a recursive final-file digest.
apps/web/— the React/Vite app plus the read-focused/api/*registry Worker, deployed to isolated preview/production Cloudflare Workers with a D1-backed registry (seedocs/adr/0002-unified-cloudflare-worker-deployment.md)packages/—claim,identity,metadata,c2pa-node,verifier,react,cli,python: creator claims, identity/trust, metadata discovery, C2PA Generator Product signing, verification, theprooflensCLI, and Python interoperabilityfixtures/— deterministic JPEG/PNG/WebP generation used by testspublic/— the retired-site retirement notice Netlify actually serves (netlify.tomlpublishes only this directory), pointing visitors at the live production Worker abovedocs/— architecture decision records, planning (roadmap, sprint plan, implementation plan), and history (imported-repository and migration records)legacy/— frozen, read-only history:legacy/signerandlegacy/verify-widgetare the complete imported histories of the former standalone repositories;legacy/siteis the retired pre-Phase-0 static demo site, preserved but no longer served
Related repos
prooflens-signer and prooflens-verify-widget were migrated into this
monorepo with full history preserved and are being retired in favor of it
(archiving pending final authorization). Their final tagged states remain
reachable here:
- Signer history:
legacy/signer(final standalone commit20e248ac2de56bc49a60478c315ba6baf378fd4f, tagstandalone/signer/v0.1.0, rollback refrefs/tags/rollback/signer/final-standalone) - Verify-widget history:
legacy/verify-widget(final standalone commit46bb79519fddc925fee6f856b98e987f444d819e, tagstandalone/verify-widget/v0.1.0, rollback refrefs/tags/rollback/verify-widget/final-standalone)
Replacements in this monorepo:
- Signer CLI (Python) →
@prooflens/cliNode package (packages/cli), installed via the workspace and run asprooflens identity generate --out <dir>,prooflens identity sign --key <private.jwk.json> --asset <file> --kid <https-kid> --name <name> --credit <credit> --out <envelope.json>, andprooflens verify --asset <file> [--envelope <file>] [--registry <file>] [--html <file>] [--legacy <file>]. C2PA Generator Product signing moved toprooflens c2pa sign --asset <file> --claim <envelope-or-claim.json> --out <file>. - Verify widget (browser) →
packages/verifier's auto-attach bundle, built from source withpnpm --filter @prooflens/verifier build(outputspackages/verifier/dist/prooflens-verify.jsand.min.js), pluspackages/reactcomponent/hook bindings. Seedocs/history/standalone-imports.mdanddocs/history/phase7-migration.mdfor full migration detail.
From this workspace, using @prooflens/cli (see the CLI usage above for
the full flag reference):
prooflens identity generate --out ./keys
prooflens identity sign --key ./keys/creator.private.jwk.json --asset photo.jpg \
--kid https://your-registry.example/v1/keys/you --name "Your Name" \
--credit "Photo: Your Name" --out photo.jpg.envelope.json
# Detached: verify the creator-signed envelope against the exact original file
prooflens verify --asset photo.jpg --envelope photo.jpg.envelope.json
# Embedded: add a C2PA Generator Product credential, then verify the C2PA-signed file
prooflens c2pa sign --asset photo.jpg --claim photo.jpg.envelope.json --out photo.c2pa.jpg
prooflens verify --asset photo.c2pa.jpgBoth verify calls report state: "valid-untrusted" here because no
registry was configured; the second also reports that C2PA authenticates
the ProofLens Generator Product, not the human creator.
packages/react ships components/hooks for rendering
this verification in the browser; the live registry linked above is the
read-only public API these envelopes/claims resolve identities and
manifests against.
MIT