No description
Find a file
DJP 979087aada Fix softwareAgent [object Object] bug in C2PA actions
softwareAgent in c2pa.actions v1 must be a string (tstr), not an object.
Now shows the AI model name prominently, e.g. "Imagen 4 (via C2PA Stamping Tool/1.0.0)"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 08:21:51 -05:00
backend Fix softwareAgent [object Object] bug in C2PA actions 2026-02-25 08:21:51 -05:00
certs Initial commit: C2PA Stamping & Verification Tool 2026-02-24 23:05:51 -05:00
docker/postgres Initial commit: C2PA Stamping & Verification Tool 2026-02-24 23:05:51 -05:00
frontend Improve verification display and fix download auth 2026-02-25 08:03:53 -05:00
.env.example Initial commit: C2PA Stamping & Verification Tool 2026-02-24 23:05:51 -05:00
.gitignore Initial commit: C2PA Stamping & Verification Tool 2026-02-24 23:05:51 -05:00
docker-compose.yml Initial commit: C2PA Stamping & Verification Tool 2026-02-24 23:05:51 -05:00
package-lock.json Initial commit: C2PA Stamping & Verification Tool 2026-02-24 23:05:51 -05:00
package.json Initial commit: C2PA Stamping & Verification Tool 2026-02-24 23:05:51 -05:00
README.md Initial commit: C2PA Stamping & Verification Tool 2026-02-24 23:05:51 -05:00
tsconfig.base.json Initial commit: C2PA Stamping & Verification Tool 2026-02-24 23:05:51 -05:00

C2PA Stamping & Verification Tool

A full-stack web application for stamping files with C2PA (Coalition for Content Provenance and Authenticity) content credentials and verifying existing credentials. Built for Oliver Marketing Group (OMG) to manage provenance metadata on creative assets.

Features

  • C2PA Signing — Stamp files with C2PA content credentials using X.509 certificates (PS256, ES256, ES384, ES512, Ed25519)
  • C2PA Verification — Verify embedded content credentials and inspect manifest data
  • Custom OMG Metadata — Attach job numbers, platform, and AI model information to signed assets
  • Multi-format Support — JPEG, PNG, TIFF, WebP, AVIF, GIF, SVG, MP4, MOV, MP3, WAV, PDF
  • Certificate Management — Upload, manage, and rotate signing certificates with encrypted private key storage (AES-256-GCM)
  • Role-based Access — Three user roles: Viewer (verify only), Stamper (upload + sign), Admin (full access)
  • Admin Panel — Manage users, platforms, and AI models without code changes
  • File Preview — Image, video, and audio preview within the application
  • Headless API — All functionality accessible via REST API for integration with other systems
  • Dockerised — Full Docker Compose setup with PostgreSQL, Node.js backend, and React frontend

Tech Stack

Layer Technology
Frontend React 19, Vite 7, TypeScript, Tailwind CSS 4, Lucide Icons
Backend Node.js 22, Fastify 5, TypeScript
C2PA Engine @contentauth/c2pa-node (Rust bindings via NAPI)
ORM Drizzle ORM
Database PostgreSQL 16
Auth JWT with bcrypt password hashing
Containerisation Docker Compose v2

Quick Start

Prerequisites

  • Docker Desktop (or Docker Engine + Compose v2)
  • A C2PA signing certificate (X.509 cert + private key in PEM format)

1. Clone and configure

git clone git@bitbucket.org:zlalani/c2pa-2026.git
cd c2pa-2026
cp .env.example .env

Edit .env and set:

  • CERT_ENCRYPTION_KEY — Generate with openssl rand -hex 32
  • POSTGRES_PASSWORD — Database password (default works for dev)

2. Add your certificate

Place your signing certificate files in the certs/ directory:

certs/
├── ps256.pem    # Private key (PEM format)
└── ps256.pub    # X.509 certificate (PEM format)

The filename prefix determines the algorithm: ps256, es256, es384, es512, ed25519. Certificates are automatically imported on first startup.

3. Start all services

docker compose up --build -d

This starts three services:

Service URL Port
Frontend http://localhost:3050 3050
Backend API http://localhost:8050 8050
PostgreSQL 5470

4. Log in

Three default users are seeded on first startup:

Email Password Role
admin@omg.agency admin123 Admin (full access)
stamper@omg.agency stamp123 Stamper (upload + sign)
viewer@omg.agency view123 Viewer (verify only)

Architecture

C2PA-2026/
├── docker-compose.yml          # Orchestrates all services
├── .env / .env.example         # Environment configuration
├── certs/                      # Signing certificates (gitignored)
├── backend/
│   ├── Dockerfile
│   └── src/
│       ├── index.ts            # Entry point + seed runner
│       ├── app.ts              # Fastify app factory
│       ├── config.ts           # Zod-validated env config
│       ├── seed.ts             # Auto-seed certs, users, platforms, models
│       ├── db/
│       │   ├── schema.ts       # Drizzle table definitions
│       │   ├── connection.ts   # Database connection
│       │   ├── migrate.ts      # Migration runner
│       │   └── migrations/     # SQL migrations
│       ├── routes/
│       │   ├── files.ts        # Upload, sign, verify, download, delete
│       │   ├── certificates.ts # Certificate CRUD
│       │   ├── auth.ts         # Login, user management
│       │   ├── admin.ts        # Platforms + AI models CRUD
│       │   └── health.ts       # Health check
│       ├── services/
│       │   ├── c2pa.service.ts         # Sign + verify with c2pa-node
│       │   ├── file.service.ts         # File storage management
│       │   ├── certificate.service.ts  # Cert CRUD + encryption
│       │   ├── crypto.service.ts       # AES-256-GCM encryption
│       │   └── auth.service.ts         # JWT auth + user management
│       └── middleware/
│           ├── auth.ts                 # JWT auth + role guards
│           ├── error-handler.ts
│           └── file-validation.ts      # MIME + magic byte validation
└── frontend/
    ├── Dockerfile
    ├── nginx.conf              # Reverse proxy + SPA fallback
    └── src/
        ├── App.tsx             # Router + auth provider
        ├── api/                # API client + typed endpoints
        ├── contexts/           # Auth context (login, roles)
        ├── components/
        │   ├── layout/         # Sidebar + nav (role-aware)
        │   ├── files/          # FileUpload, FileList, SignDialog
        │   └── verification/   # ManifestTree, ValidationStatus
        └── pages/
            ├── DashboardPage   # Stats, quick upload
            ├── FilesPage       # File list + filters
            ├── FileDetailPage  # Preview, sign, verify, download
            ├── VerifyPage      # Upload-and-verify workflow
            ├── CertificatesPage
            ├── AdminUsersPage
            ├── AdminSettingsPage  # Platforms + AI models
            └── LoginPage

API Reference

All endpoints require JWT authentication via Authorization: Bearer <token> header (except login and health).

Authentication

Method Path Description Auth
POST /api/auth/login Login with email/password None
GET /api/auth/me Get current user Any

Files

Method Path Description Role
POST /api/files/upload Upload a file (multipart) Stamper, Admin
GET /api/files List files (paginated, filterable) Any
GET /api/files/:id File details + preview URLs Any
POST /api/files/:id/sign Sign with C2PA credentials Stamper, Admin
GET /api/files/:id/verify Verify C2PA manifest Any
POST /api/files/verify-upload Verify an uploaded file (no save) Any
GET /api/files/:id/download?version=signed|original Download file Any
DELETE /api/files/:id Delete file Admin

Sign request body

{
  "certificateId": "uuid (optional, uses default)",
  "title": "Asset title",
  "omgJobNumber": "OMG-2026-001",
  "platform": "OMG",
  "aiModel": "Imagen 4"
}

Certificates

Method Path Description Role
GET /api/certificates List certificates Any
GET /api/certificates/:id Certificate details Any
POST /api/certificates Upload cert + key pair (multipart) Admin
PUT /api/certificates/:id/default Set as default signing cert Admin
DELETE /api/certificates/:id Remove certificate Admin

Admin

Method Path Description Role
GET /api/admin/users List all users Admin
POST /api/admin/users Create user Admin
PUT /api/admin/users/:id/role Update user role Admin
DELETE /api/admin/users/:id Delete user Admin
GET /api/platforms List active platforms Any
GET /api/models List active AI models Any
GET /api/admin/platforms List all platforms Admin
POST /api/admin/platforms Create platform Admin
DELETE /api/admin/platforms/:id Delete platform Admin
GET /api/admin/models List all models Admin
POST /api/admin/models Create AI model Admin
PUT /api/admin/models/:id Update model Admin
DELETE /api/admin/models/:id Delete model Admin

Health

Method Path Description Auth
GET /api/health Service status None

Headless API Usage (curl examples)

# Login
TOKEN=$(curl -s http://localhost:8050/api/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"email":"stamper@omg.agency","password":"stamp123"}' \
  | jq -r '.token')

# Upload
FILE_ID=$(curl -s http://localhost:8050/api/files/upload \
  -H "Authorization: Bearer $TOKEN" \
  -F "file=@photo.jpg" | jq -r '.id')

# Sign with OMG metadata
curl -s http://localhost:8050/api/files/$FILE_ID/sign \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Campaign Photo",
    "omgJobNumber": "OMG-2026-042",
    "platform": "OMG",
    "aiModel": "Imagen 4"
  }'

# Verify
curl -s http://localhost:8050/api/files/$FILE_ID/verify \
  -H "Authorization: Bearer $TOKEN"

# Download signed file
curl -O http://localhost:8050/api/files/$FILE_ID/download?version=signed \
  -H "Authorization: Bearer $TOKEN"

C2PA Metadata

When signing, the following C2PA standard fields are set:

  • Claim Generator: C2PA Stamping Tool v1.0.0
  • Action: c2pa.created with trainedAlgorithmicMedia digital source type
  • Manifest Metadata: OMG custom fields stored as key-value pairs (omg:jobNumber, omg:platform, omg:aiModel, omg:stampedBy, omg:stampedAt)

The signed files can be verified at verify.contentauthenticity.org.

Security

  • Private keys encrypted at rest with AES-256-GCM (key from environment variable)
  • File MIME validation + magic byte verification to prevent spoofing
  • Configurable file size limit (default 100MB)
  • JWT authentication with 24-hour token expiry
  • Role-based access control on all endpoints
  • CORS restricted to frontend origin
  • Rate limiting (100 requests/minute)
  • No private key data exposed via API responses
  • UUID-based file paths (no user input in paths)

User Roles

Role Upload Sign Verify Download Manage Certs Manage Users Manage Settings
Viewer - - Yes - - - -
Stamper Yes Yes Yes Yes - - -
Admin Yes Yes Yes Yes Yes Yes Yes

Development

Local development (without Docker)

# Start PostgreSQL (or use Docker just for the DB)
docker compose up -d postgres

# Backend
cd backend
cp ../.env.example ../.env  # configure env
npm install
npm run db:generate
npm run db:migrate
npm run dev                  # http://localhost:8050

# Frontend
cd frontend
npm install
npm run dev                  # http://localhost:5173

Database management

# Generate migration after schema changes
cd backend && DATABASE_URL=... npx drizzle-kit generate

# Run migrations
cd backend && DATABASE_URL=... npx tsx src/db/migrate.ts

# Open Drizzle Studio
cd backend && DATABASE_URL=... npx drizzle-kit studio

Seeded Data

On first startup, the application seeds:

  • 3 users: admin, stamper, viewer (see login table above)
  • Certificates: Auto-imported from certs/ directory
  • 2 platforms: OMG, Pencil
  • 29 AI models: Google (Imagen 3/4, Veo 2/3, Gemini), OpenAI (DALL-E 3, GPT-4o, Sora), Stability AI, Adobe Firefly, Midjourney, Anthropic Claude, Meta, Black Forest Labs FLUX, Runway, Pika, Kuaishou Kling

All platforms and models are manageable through the Admin > Settings page without code changes.

Colour Scheme

  • Primary: Black (#000000)
  • Accent: Gold (#FFC407)
  • Font: Montserrat (Google Fonts)

License

Proprietary — Oliver Marketing Group