Badges Worker

Cloudflare badges worker: bindings, secrets, D1 database, route structure, and AI detect proxy

Overview

The badges worker is a Cloudflare Worker that serves the verifieddit badge system. It handles badge creation, verification, image serving, and proxies AI detection requests. It uses D1 for persistence and KV for caching.

Repository: Sanmarcsoft/verifieddit-www (root wrangler.toml)

Bindings

D1 Databases

BindingDatabase NameEnvironment
DBverifieddit-badgesProduction
DBverifieddit-badges-testingTesting

Secrets

SecretDescription
SIGHTENGINE_API_USERSightengine AI detection API user
SIGHTENGINE_API_SECRETSightengine AI detection API secret
CLERK_SECRET_KEYClerk backend verification key
CLERK_PUBLISHABLE_KEYClerk frontend key (for JWT verification)

Routes

WorkerRoute PatternEnvironment
verifieddit-badgesverifieddit.com/api/*Production
verifieddit-badges-testingtesting.matthewstevens.org/api/*Testing

D1 Database Schema

Core Tables

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
-- Badges table
CREATE TABLE IF NOT EXISTS badges (
  id TEXT PRIMARY KEY,
  url TEXT NOT NULL,
  domain TEXT NOT NULL,
  badge_type TEXT DEFAULT 'standard',
  status TEXT DEFAULT 'pending',
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  verified_at DATETIME,
  c2pa_manifest TEXT,
  original_thumbnail_url TEXT
);

-- Badge images table (for analytics)
CREATE TABLE IF NOT EXISTS badge_images (
  id TEXT PRIMARY KEY,
  badge_id TEXT NOT NULL,
  image_url TEXT NOT NULL,
  ai_score REAL,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (badge_id) REFERENCES badges(id)
);

-- Users table (synced from Clerk)
CREATE TABLE IF NOT EXISTS users (
  clerk_id TEXT PRIMARY KEY,
  email TEXT,
  plan TEXT DEFAULT 'free',
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

D1 Operations

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# List databases
npx wrangler d1 list

# Execute SQL
npx wrangler d1 execute verifieddit-badges --command "SELECT COUNT(*) FROM badges"

# Execute SQL on testing database
npx wrangler d1 execute verifieddit-badges-testing --command "SELECT * FROM badges LIMIT 5"

# Run migrations
npx wrangler d1 execute verifieddit-badges --file migrations/001_init.sql

Deployment

Production Deploy

1
2
cd verifieddit-www
npx wrangler deploy

Testing Deploy

1
npx wrangler deploy --env testing

Deploy via API (When Wrangler Fails)

See Cloudflare Workers SOP for API deployment method.

Setting Secrets

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# Set individual secret
npx wrangler secret put SIGHTENGINE_API_USER
# (enter value when prompted)

# Or via API
CF_TOKEN=$(pass cloudflare/api-token)
ACCOUNT_ID=$(pass cloudflare/account-id)

curl -s -X PUT \
  "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/workers/scripts/verifieddit-badges/secrets" \
  -H "Authorization: Bearer ${CF_TOKEN}" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "SIGHTENGINE_API_USER",
    "text": "'"$(pass sightengine/api-user)"'",
    "type": "secret_text"
  }'

AI Detection Proxy

The worker proxies AI detection requests to avoid CORS issues:

Client -> verifieddit.com/api/ai-detect -> Worker -> api.sightengine.com

The worker adds the Sightengine credentials server-side, so they are never exposed to the client.

Debug Endpoint

The worker includes a /__debug endpoint for version verification:

1
curl -s https://verifieddit.com/api/__debug | jq .

This returns the deployed version and timestamp.

Testing Isolation

The testing environment uses a separate:

  • D1 database (verifieddit-badges-testing)
  • Worker (verifieddit-badges-testing)
  • Route (testing.matthewstevens.org/api/*)
  • Clerk instance (test keys: pk_test_*)

This ensures testing never affects production data.

Preflight Checks

Before deploying to production, run the preflight script (13 checks):

  1. API endpoint responds
  2. D1 database accessible
  3. Badge creation works
  4. Badge retrieval works
  5. AI detection proxy works
  6. Clerk auth verification
  7. Stripe webhook responds
  8. CSP headers correct
  9. CORS headers correct
  10. Docker network connectivity (NAS)
  11. Container DNS resolution
  12. Health check endpoint
  13. Clerk publishable key present in build

Troubleshooting

  • D1 binding error: Verify the D1 database ID in wrangler.toml matches the actual database. Use npx wrangler d1 list to check.
  • AI detect returning 403: Check Sightengine API credentials. May need to re-set secrets after a deploy.
  • Old code still serving after deploy: Check for Worker versioning issues. See Cloudflare Workers SOP version management section.
  • CSP errors in browser: Check clerk-telemetry.com is in the Content-Security-Policy header. This was a known issue.