A pay-per-call quality/safety scoring service for AI agents. An agent submits its own output, and the service scores it against a published, public rubric and returns an Ed25519-signed score receipt.
It pairs with provenance-receipts: that service certifies origin; this one certifies quality — specifically, quality as measured by our published rubric.
Scope: We sell a score against our own published rubric, not a claim of absolute truth, not an external/third-party standard, and not a guarantee the content is safe to act on. The rubric is public (src/rubric/quality-rubric.md) and every score is reproducible. Every public claim is verifiable.
- ✅ The content presented at verification is byte-for-byte what was scored (SHA-256 hash match).
- ✅ The score, rubric version, and timestamp were issued by the holder of this service's signing key (Ed25519 signature check).
⚠️ The score is an LLM judgment against Quality Gate Rubric vX — not a measure of truth or external correctness. "Obvious-error freedom" is not an external fact-check. See the rubric's "Limits" section.
| Method | Path | Purpose | Paid? |
|---|---|---|---|
| POST | /v1/score |
Score content against the rubric; signed receipt | yes (x402) |
| POST | /v1/verify |
Re-hash content and check a receipt's signature | no, free |
| GET | /v1/rubric |
The published rubric + current version | no, free |
| GET | /v1/public-key |
Ed25519 public key for independent verification | no, free |
| GET | /health |
Liveness check | no, free |
Full request/response schemas: docs/API.md. Verify a receipt yourself, without trusting this service: docs/VERIFYING.md.
Input: { content, rubric_version?, target_score? }
Output: { score, breakdown, flags, rubric_version, receipt } — the receipt is
an Ed25519-signed object committing to { content_hash, score, rubric_version, timestamp, receipt_id, signature }.
"No pass, no pay" mode: if the caller sets target_score, payment is only
settled when the score clears it. If it fails, the call is released without
charge and returns { ..., passed: false, charged: false, receipt: null } plus
the failing breakdown.
Operator-cost note (read this): "No pass, no pay" means the operator absorbs the scoring cost on failed calls. Every
/v1/scorecall runs a paid Claude API pass (~$0.012 on Sonnet 4.6) before the score is known, so when a caller's content misses theirtarget_scorewe still paid to score it but collected nothing. This is inherent to the feature, not a bug — price the service and your failure-rate expectations accordingly.
Scoring is a Claude API pass against src/rubric/quality-rubric.md:
four dimensions — clarity, completeness, internal consistency, obvious-error
freedom — 0–25 each, plus a closed vocabulary of flags. The rubric is versioned
and public; receipts record the exact rubric_version scored against.
/v1/score is the paid action; /v1/verify, /v1/rubric, and /v1/public-key
are free. Payment gating is off by default and only activates when
X402_ENABLED="true".
- Protocol: x402 — a
402 Payment Requiredresponse advertisesacceptsrequirements; the client retries with anX-PAYMENTheader; a facilitator verifies/settles on-chain. - Verifier is pluggable:
stub(default — no chain calls, local testing only) orfacilitator(free public testnet facilitator athttps://x402.org/facilitator, Base Sepolia). The facilitator path is ported but not yet wired — pending a configured testnet wallet. - Default price
$0.02(X402_PRICE), set above the ~$0.012 Sonnet 4.6 scoring cost. Nothing here touches mainnet or real funds.
npm install
npm run build:rubric # embed the rubric .md into a module
node scripts/gen-dev-key.mjs --write # writes SIGNING_PRIVATE_KEY to .dev.vars (gitignored)
# add ANTHROPIC_API_KEY="sk-ant-..." to .dev.vars for real scoring (paid)
npm test # 20 tests, fully mocked — no API calls, $0
npm run typecheck
npm run dev # wrangler dev on http://localhost:8787GET /v1/rubric, GET /v1/public-key, and POST /v1/verify are free. A real
POST /v1/score makes a paid Claude API call (~$0.012/call).
- Cloudflare Workers + Wrangler, Hono routing
- Ed25519 via
@noble/ed25519— ported, not reinvented, from provenance-receipts - Cloudflare KV for receipt records
- Anthropic API for the scoring pass
- x402 micropayments (USDC on Base) — built last, stub verifier first
- Step 1 — skeleton + structure + published rubric draft
- Step 2 —
/v1/score+/v1/verifywith signing & rubric scoring (no payments) - Step 3 — x402 payment layer (stub verifier) + "no pass, no pay"
- Step 4 — README + public docs + public rubric page; self-verified claims (API.md, VERIFYING.md)
- Real Base Sepolia testnet wiring (
FacilitatorVerifier) — verified end-to-end on-chain (2026-06-12):402→ buyer signs → score → settle →200; 0.02 test USDC moved buyer → seller in tx0xb4973438…52c5a91a. Testnet only — no mainnet, no real funds.
quality-gate/
├── src/
│ ├── index.ts # Hono app entry + route mounting
│ ├── types.ts # Env, ScoreReceipt, ScoreResult, ScoreBreakdown
│ ├── routes/
│ │ ├── score.ts # POST /v1/score (step 2)
│ │ └── verify.ts # POST /v1/verify (step 2)
│ ├── lib/ # PORTED from provenance-receipts (steps 2–3)
│ │ ├── crypto.ts # Ed25519 + SHA-256
│ │ ├── receipt.ts # score-receipt build/verify
│ │ └── kv.ts # KV storage helpers
│ ├── scoring/
│ │ ├── rubric.ts # rubric loading + versioning
│ │ ├── rubric-text.ts # AUTO-GENERATED from the .md (npm run build:rubric)
│ │ └── scorer.ts # Anthropic scoring pass (pinned: claude-sonnet-4-6)
│ ├── rubric/
│ │ └── quality-rubric.md # THE PUBLIC RUBRIC (v1) — single source of truth
│ └── payments/ # x402 layer, ported from provenance-receipts
│ ├── types.ts · stub-verifier.ts · facilitator-verifier.ts
│ ├── config.ts # env-driven config + verifier selection
│ └── gate.ts # 402 helper for the verify→score→settle flow
├── docs/ # API.md, VERIFYING.md
├── scripts/ # embed-rubric · gen-dev-key · verify-receipt
├── test/ # 20 tests (mocked scorer + stub verifier)
├── package.json
├── tsconfig.json
├── wrangler.toml
├── .gitignore
└── .dev.vars.example # copy to .dev.vars locally; never commit secrets
- No secrets in code.
SIGNING_PRIVATE_KEYandANTHROPIC_API_KEYare set withwrangler secret put..dev.vars/.testnet.varsare gitignored. - Nothing here costs money without confirmation. Everything is built/tested free/local/testnet first. Any step that would incur cost (a domain, a paid Cloudflare tier, Base mainnet gas, large Anthropic API spend) is confirmed first. The scoring pass does call the paid Anthropic API — local testing uses small inputs and is confirmed before running.
- Every documented claim is verifiable. The rubric is public; scores are reproducible; receipts are independently checkable.