npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dupecom/botcha-cloudflare

v0.23.0

Published

BOTCHA for Cloudflare Workers - Prove you're a bot. Humans need not apply.

Readme

@dupecom/botcha-cloudflare

BOTCHA - Prove you're a bot. Humans need not apply.

Cloudflare Workers Edition v0.22.0 - Identity layer for AI agents

Reverse CAPTCHA that verifies AI agents and blocks humans. Running at the edge.

What's New in v0.22.0

  • x402 Payment Gating — Agents pay $0.001 USDC on Base for a BOTCHA token. No puzzle. (GET /v1/x402/challenge)
  • ANS Integration — DNS-based agent identity lookup and BOTCHA-issued ownership badges. (GET /v1/ans/resolve/:name)
  • DID/VC Issuer — BOTCHA issues portable W3C Verifiable Credential JWTs. (POST /v1/credentials/issue)
  • A2A Agent Card Attestation (coming soon, PR #26)
  • OIDC-A Attestation (coming soon, PR #28)

Features

  • Speed Challenge - 5 SHA256 hashes in 500ms (impossible for humans to copy-paste)
  • 🧮 Standard Challenge - Configurable difficulty prime calculations
  • 🔐 JWT Authentication - Token-based access control with jose library
  • 🚦 Rate Limiting - IP-based throttling with KV storage
  • 🌍 Edge-native - Runs on Cloudflare's global network
  • 📦 Minimal dependencies - Hono for routing, jose for JWT

Quick Deploy

# Clone the repo
git clone https://github.com/dupe-com/botcha
cd botcha/packages/cloudflare-workers

# Install dependencies
npm install

# Deploy to Cloudflare
npm run deploy

Local Development

npm run dev
# Worker running at http://localhost:8787

🔐 JWT Token Flow (Recommended)

1. Get Challenge

GET /v1/token

Response includes challenge and instructions for getting a JWT token.

2. Solve Challenge & Get JWT

POST /v1/token/verify
Content-Type: application/json

{
  "id": "challenge-uuid",
  "answers": ["abc12345", "def67890", ...]
}

Returns JWT token valid for 1 hour.

3. Access Protected Resources

GET /agent-only
Authorization: Bearer <your-jwt-token>

📊 Rate Limiting

Free tier: 100 challenges per hour per IP

Rate limit headers:

  • X-RateLimit-Limit: 100
  • X-RateLimit-Remaining: 95
  • X-RateLimit-Reset: 2026-02-02T12:00:00.000Z

API Endpoints

v1 API (Production)

| Endpoint | Method | Description | |----------|--------|-------------| | / | GET | API information | | /health | GET | Health check | | /v1/challenges | GET | Generate challenge (speed or standard) | | /v1/challenges/:id/verify | POST | Verify challenge (no JWT) | | /v1/token | GET | Get challenge for JWT flow | | /v1/token/verify | POST | Verify challenge → get JWT token | | /v1/token/refresh | POST | Refresh access token | | /v1/token/revoke | POST | Revoke token immediately | | /v1/token/validate | POST | Remote token validation (no shared secret) | | /v1/challenge/stream | GET | SSE streaming challenge (AI-native) | | /v1/challenge/stream/:session | POST | SSE action handler (go, solve) | | /agent-only | GET | Protected endpoint (requires JWT) |

Well-Known Endpoints

| Endpoint | Method | Description | |----------|--------|-------------| | /.well-known/did.json | GET | BOTCHA DID Document (did:web:botcha.ai) | | /.well-known/jwks | GET | JWK Set (TAP agent keys + DID signing keys) | | /.well-known/jwks.json | GET | JWK Set alias | | /.well-known/ai-plugin.json | GET | ChatGPT plugin manifest |

x402 Payment Gating

| Endpoint | Method | Auth | Description | |----------|--------|------|-------------| | /v1/x402/info | GET | public | Payment config discovery | | /v1/x402/challenge | GET | public / X-Payment | Pay $0.001 USDC → BOTCHA token | | /v1/x402/verify-payment | POST | Bearer | Verify x402 payment proof | | /v1/x402/webhook | POST | — | Settlement notifications | | /agent-only/x402 | GET | Bearer + x402 | Demo: requires both BOTCHA token + payment |

ANS (Agent Name Service)

| Endpoint | Method | Auth | Description | |----------|--------|------|-------------| | /v1/ans/botcha | GET | public | BOTCHA's ANS identity | | /v1/ans/resolve/:name | GET | public | DNS-based ANS lookup | | /v1/ans/resolve/lookup | GET | public | ANS lookup via ?name= query param | | /v1/ans/discover | GET | public | List BOTCHA-verified ANS agents | | /v1/ans/nonce/:name | GET | Bearer | Nonce for ownership proof | | /v1/ans/verify | POST | Bearer | Verify ANS ownership → BOTCHA badge |

DID/VC Issuer

| Endpoint | Method | Auth | Description | |----------|--------|------|-------------| | /v1/credentials/issue | POST | Bearer | Issue W3C VC JWT | | /v1/credentials/verify | POST | public | Verify any BOTCHA-issued VC JWT | | /v1/dids/:did/resolve | GET | public | Resolve did:web DIDs |

A2A Agent Card Attestation (coming soon — PR #26)

| Endpoint | Method | Auth | Description | |----------|--------|------|-------------| | /.well-known/agent.json | GET | public | BOTCHA's A2A Agent Card | | /v1/a2a/agent-card | GET | public | BOTCHA's A2A Agent Card (alias) | | /v1/a2a/attest | POST | Bearer | Attest an agent's A2A card | | /v1/a2a/verify-card | POST | public | Verify an attested card | | /v1/a2a/verify-agent | POST | public | Verify agent by card or agent_url | | /v1/a2a/trust-level/:agent_url | GET | public | Get trust level for agent URL | | /v1/a2a/cards | GET | public | Registry browse | | /v1/a2a/cards/:id | GET | public | Get specific card by ID |

OIDC-A Attestation (coming soon — PR #28)

| Endpoint | Method | Auth | Description | |----------|--------|------|-------------| | /.well-known/oauth-authorization-server | GET | public | OAuth/OIDC-A discovery | | /v1/attestation/eat | POST | Bearer | Issue Entity Attestation Token (EAT/RFC 9711) | | /v1/attestation/oidc-agent-claims | POST | Bearer | Issue OIDC-A agent claims block | | /v1/auth/agent-grant | POST | Bearer | Agent grant flow (OAuth2-style) | | /v1/auth/agent-grant/:id/status | GET | Bearer | Grant status | | /v1/auth/agent-grant/:id/resolve | POST | Bearer | Approve/resolve grant | | /v1/oidc/userinfo | GET | Bearer | OIDC-A UserInfo |

SSE Streaming (AI-Native)

For AI agents that prefer conversational flows, BOTCHA offers Server-Sent Events streaming:

Flow:

  1. GET /v1/challenge/stream - Opens SSE connection, receive welcome/instructions/ready events
  2. POST /v1/challenge/stream/:session with {action:"go"} - Start challenge timer (fair timing!)
  3. Receive challenge event with problems
  4. POST /v1/challenge/stream/:session with {action:"solve", answers:[...]} - Submit solution
  5. Receive result event with JWT token

Benefits: Timer starts when you say "GO" (not on connection), natural back-and-forth handshake.

Legacy API (v0 - backward compatible)

| Endpoint | Method | Description | |----------|--------|-------------| | /api/challenge | GET/POST | Standard challenge | | /api/speed-challenge | GET/POST | Speed challenge (500ms limit) | | /api/verify-landing | POST | Landing page challenge |

Solving Challenges (for AI Agents)

// Speed challenge
const challenge = await fetch('https://your-worker.workers.dev/api/speed-challenge').then(r => r.json());

const answers = await Promise.all(
  challenge.challenge.problems.map(async (p) => {
    const hash = await crypto.subtle.digest(
      'SHA-256',
      new TextEncoder().encode(p.num.toString())
    );
    return Array.from(new Uint8Array(hash))
      .map(b => b.toString(16).padStart(2, '0'))
      .join('')
      .substring(0, 8);
  })
);

const result = await fetch('https://your-worker.workers.dev/api/speed-challenge', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ id: challenge.challenge.id, answers }),
}).then(r => r.json());

console.log(result.verdict); // "🤖 VERIFIED AI AGENT"

🔑 Production Configuration

KV Namespaces

Create KV namespaces:

# Create challenge storage
wrangler kv namespace create CHALLENGES
wrangler kv namespace create CHALLENGES --preview

# Create rate limiting storage
wrangler kv namespace create RATE_LIMITS
wrangler kv namespace create RATE_LIMITS --preview

Update wrangler.toml with the returned IDs.

JWT Secret

⚠️ Important: Use Wrangler secrets for production:

wrangler secret put JWT_SECRET
# Enter a strong secret (32+ characters)

Testing

Run the test script:

# Start dev server
npm run dev

# Run tests
./test-api.sh

License

MIT

Deployment test with JWT_SECRET