CV Challenge is a lightweight interactive verification flow that feels more like a short user challenge than a traditional CAPTCHA. It is not designed to prevent volumetric attacks; it focuses on confirming a real user action with a short 3D visual task.
- @cv-challenge/server: server-side renderer, token manager, and Express adapter.
- @cv-challenge/react-plugin: React widget with a minimal overlay UX.
apps/demo: Vite demo app that consumes the React plugin.apps/server: Express server example for local development.
- The server renders 20 dense 3D objects with Lambertian shading and transparency.
- One static target object has more prominent motion cues (rotation/scale/morph).
- The client clicks the target; verification uses a single screen-space hitbox.
- Challenge tokens are encrypted; success tokens are encoded only and should be validated server-side.
- Challenge tokens expire after ~20 seconds; failed attempts are blacklisted until expiry.
- Successful verification returns a success token (60s by default).
onVerifiedcan override success token TTL/payload or return null to skip issuing it.validateSuccessTokencan tie success tokens to session or user data.- Success tokens are invalidated after 3 consecutive failed verifications tied to them.
- When the success token is sent back to
/challenge, the server skips the 5s cold-start delay. - Without a valid success token,
/challengeresponses are padded to ~5 seconds total. - The React plugin handles the success token and shows a countdown during cold start.
onChallengecan enforce one active challenge per requester (session/IP). When set, new/challengerequests return429withRetry-Afteruntil the prior challenge is verified or expires.- Per-key backoff on failed verifications can add cooldowns (default window 10 minutes, cap 75s); use
onChallengeto identify the requester. Unverified expired challenges count as failures within the window.
- Default video size: 180x60.
- Default duration: ~3 seconds, 20 objects (server defaults).
- The React widget and server defaults are aligned; override both if you customize size.
pnpm install
pnpm devThis starts the server on http://localhost:3000 and the Vite demo on http://localhost:5173.
Other useful commands:
pnpm dev:server
pnpm dev:demo
pnpm dev:pluginCHALLENGE_JWT_SECRET: encryption key for challenge tokens (required for production).PORT: overrides the server port (default:3000).
- The server depends on ffmpeg and OpenCV (opencv4nodejs).
- WebM alpha support depends on the browser. Chromium-based browsers work best.
- The demo logs verification responses in the console; remove these for production.
This repo uses Changesets for versioning:
pnpm changeset
pnpm version-packages
pnpm release