@dupecom/botcha-cloudflare 0.16.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/auth.d.ts +48 -3
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +89 -21
- package/dist/dashboard/docs.d.ts +15 -0
- package/dist/dashboard/docs.d.ts.map +1 -0
- package/dist/dashboard/docs.js +556 -0
- package/dist/dashboard/layout.d.ts +12 -0
- package/dist/dashboard/layout.d.ts.map +1 -1
- package/dist/dashboard/layout.js +12 -5
- package/dist/dashboard/showcase.d.ts.map +1 -1
- package/dist/dashboard/showcase.js +2 -1
- package/dist/dashboard/whitepaper.d.ts.map +1 -1
- package/dist/dashboard/whitepaper.js +3 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +125 -13
- package/dist/static.d.ts +592 -2
- package/dist/static.d.ts.map +1 -1
- package/dist/static.js +422 -9
- package/dist/tap-attestation-routes.d.ts +204 -0
- package/dist/tap-attestation-routes.d.ts.map +1 -0
- package/dist/tap-attestation-routes.js +396 -0
- package/dist/tap-attestation.d.ts +178 -0
- package/dist/tap-attestation.d.ts.map +1 -0
- package/dist/tap-attestation.js +416 -0
- package/dist/tap-delegation-routes.d.ts +236 -0
- package/dist/tap-delegation-routes.d.ts.map +1 -0
- package/dist/tap-delegation-routes.js +378 -0
- package/dist/tap-delegation.d.ts +127 -0
- package/dist/tap-delegation.d.ts.map +1 -0
- package/dist/tap-delegation.js +490 -0
- package/dist/tap-jwks.d.ts +2 -1
- package/dist/tap-jwks.d.ts.map +1 -1
- package/dist/tap-jwks.js +31 -7
- package/dist/tap-reputation-routes.d.ts +154 -0
- package/dist/tap-reputation-routes.d.ts.map +1 -0
- package/dist/tap-reputation-routes.js +341 -0
- package/dist/tap-reputation.d.ts +136 -0
- package/dist/tap-reputation.d.ts.map +1 -0
- package/dist/tap-reputation.js +346 -0
- package/package.json +1 -1
package/dist/dashboard/layout.js
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
|
|
2
2
|
import { DASHBOARD_CSS } from './styles';
|
|
3
|
+
// ============ OG META COMPONENT ============
|
|
4
|
+
/**
|
|
5
|
+
* Shared Open Graph + Twitter Card meta tags.
|
|
6
|
+
* Use on every page so social previews always work.
|
|
7
|
+
* Pass overrides for page-specific titles/descriptions.
|
|
8
|
+
*/
|
|
9
|
+
export const OGMeta = ({ title = 'BOTCHA — The Identity Layer for AI Agents', description = 'Reverse CAPTCHA — Prove you\'re a bot. Humans need not apply. One of the first services to support the Trusted Agent Protocol (TAP).', url = 'https://botcha.ai', type = 'website', image = 'https://botcha.ai/og.png', }) => (_jsxs(_Fragment, { children: [_jsx("meta", { property: "og:title", content: title }), _jsx("meta", { property: "og:description", content: description }), _jsx("meta", { property: "og:url", content: url }), _jsx("meta", { property: "og:type", content: type }), _jsx("meta", { property: "og:image", content: image }), _jsx("meta", { property: "og:image:width", content: "1200" }), _jsx("meta", { property: "og:image:height", content: "630" }), _jsx("meta", { property: "og:image:type", content: "image/png" }), _jsx("meta", { name: "twitter:card", content: "summary_large_image" }), _jsx("meta", { name: "twitter:title", content: title }), _jsx("meta", { name: "twitter:description", content: description }), _jsx("meta", { name: "twitter:image", content: image })] }));
|
|
3
10
|
// ============ CARD COMPONENT ============
|
|
4
11
|
/**
|
|
5
12
|
* Reusable card with Turbopuffer-style dotted drop shadow.
|
|
@@ -25,7 +32,7 @@ export const Card = ({ children, title, badge, class: className, }) => {
|
|
|
25
32
|
*/
|
|
26
33
|
export const GlobalFooter = ({ version = '0.15.0' }) => {
|
|
27
34
|
const year = new Date().getFullYear();
|
|
28
|
-
return (_jsx("footer", { class: "global-footer", children: _jsxs("div", { class: "global-footer-inner", children: [_jsx("a", { href: "/dashboard", class: "global-footer-dashboard", children: "Dashboard" }), _jsxs("div", { class: "global-footer-links", children: [_jsxs("span", { children: ["v", version] }), _jsx("span", { class: "global-footer-sep", children: "\u00B7" }), _jsx("a", { href: "https://botcha.ai", children: "botcha.ai" }), _jsx("span", { class: "global-footer-sep", children: "\u00B7" }), _jsx("a", { href: "/whitepaper", children: "Whitepaper" }), _jsx("span", { class: "global-footer-sep", children: "\u00B7" }), _jsx("a", { href: "/openapi.json", children: "OpenAPI" }), _jsx("span", { class: "global-footer-sep", children: "\u00B7" }), _jsx("a", { href: "/ai.txt", children: "ai.txt" }), _jsx("span", { class: "global-footer-sep", children: "\u00B7" }), _jsx("a", { href: "https://github.com/dupe-com/botcha", children: "GitHub" }), _jsx("span", { class: "global-footer-sep", children: "\u00B7" }), _jsx("a", { href: "https://www.npmjs.com/package/@dupecom/botcha", children: "npm" }), _jsx("span", { class: "global-footer-sep", children: "\u00B7" }), _jsx("a", { href: "https://pypi.org/project/botcha/", children: "PyPI" })] }), _jsxs("div", { class: "global-footer-legal", children: ["\u00A9 ", year, " ", _jsx("a", { href: "https://dupe.com", children: "Dupe.com" }), _jsx("span", { class: "global-footer-sep", children: "\u00B7" }), "Free and open source", _jsx("span", { class: "global-footer-sep", children: "\u00B7" }), _jsx("a", { href: "https://github.com/i8ramin", children: "@i8ramin" })] })] }) }));
|
|
35
|
+
return (_jsx("footer", { class: "global-footer", children: _jsxs("div", { class: "global-footer-inner", children: [_jsx("a", { href: "/dashboard", class: "global-footer-dashboard", children: "Dashboard" }), _jsxs("div", { class: "global-footer-links", children: [_jsxs("span", { children: ["v", version] }), _jsx("span", { class: "global-footer-sep", children: "\u00B7" }), _jsx("a", { href: "https://botcha.ai", children: "botcha.ai" }), _jsx("span", { class: "global-footer-sep", children: "\u00B7" }), _jsx("a", { href: "/docs", children: "Docs" }), _jsx("span", { class: "global-footer-sep", children: "\u00B7" }), _jsx("a", { href: "/whitepaper", children: "Whitepaper" }), _jsx("span", { class: "global-footer-sep", children: "\u00B7" }), _jsx("a", { href: "/openapi.json", children: "OpenAPI" }), _jsx("span", { class: "global-footer-sep", children: "\u00B7" }), _jsx("a", { href: "/ai.txt", children: "ai.txt" }), _jsx("span", { class: "global-footer-sep", children: "\u00B7" }), _jsx("a", { href: "https://github.com/dupe-com/botcha", children: "GitHub" }), _jsx("span", { class: "global-footer-sep", children: "\u00B7" }), _jsx("a", { href: "https://www.npmjs.com/package/@dupecom/botcha", children: "npm" }), _jsx("span", { class: "global-footer-sep", children: "\u00B7" }), _jsx("a", { href: "https://pypi.org/project/botcha/", children: "PyPI" })] }), _jsxs("div", { class: "global-footer-legal", children: ["\u00A9 ", year, " ", _jsx("a", { href: "https://dupe.com", children: "Dupe.com" }), _jsx("span", { class: "global-footer-sep", children: "\u00B7" }), "Free and open source", _jsx("span", { class: "global-footer-sep", children: "\u00B7" }), _jsx("a", { href: "https://github.com/i8ramin", children: "@i8ramin" })] })] }) }));
|
|
29
36
|
};
|
|
30
37
|
/**
|
|
31
38
|
* Divider with centered text, used between sections on auth pages.
|
|
@@ -36,21 +43,21 @@ export const Divider = ({ text }) => (_jsx("div", { class: "divider", children:
|
|
|
36
43
|
* Used for authenticated dashboard pages
|
|
37
44
|
*/
|
|
38
45
|
export const DashboardLayout = ({ children, title, appId, version }) => {
|
|
39
|
-
return (_jsxs("html", { lang: "en", children: [_jsxs("head", { children: [_jsx("meta", { charset: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: title || 'BOTCHA Dashboard' }), _jsx(
|
|
46
|
+
return (_jsxs("html", { lang: "en", children: [_jsxs("head", { children: [_jsx("meta", { charset: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: title || 'BOTCHA Dashboard' }), _jsx(OGMeta, { url: "https://botcha.ai/dashboard" }), _jsx("link", { rel: "preconnect", href: "https://fonts.googleapis.com" }), _jsx("link", { href: "https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap", rel: "stylesheet" }), _jsx("style", { dangerouslySetInnerHTML: { __html: DASHBOARD_CSS } }), _jsx("script", { src: "https://unpkg.com/htmx.org@2.0.4" })] }), _jsxs("body", { children: [_jsx("nav", { class: "dashboard-nav", children: _jsxs("div", { class: "nav-container", children: [_jsx("a", { href: "/dashboard", class: "nav-logo", children: "BOTCHA" }), appId && (_jsxs(_Fragment, { children: [_jsx("span", { class: "nav-app-id", children: appId }), _jsx("a", { href: "/dashboard/logout", class: "nav-link", children: "Logout" })] }))] }) }), _jsx("main", { class: "dashboard-main", children: children }), _jsx(GlobalFooter, { version: version })] })] }));
|
|
40
47
|
};
|
|
41
48
|
/**
|
|
42
49
|
* Login/auth layout without navigation
|
|
43
50
|
* Used for login, signup, and other auth pages
|
|
44
51
|
*/
|
|
45
52
|
export const LoginLayout = ({ children, title, version }) => {
|
|
46
|
-
return (_jsxs("html", { lang: "en", children: [_jsxs("head", { children: [_jsx("meta", { charset: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: title || 'BOTCHA Login' }), _jsx(
|
|
53
|
+
return (_jsxs("html", { lang: "en", children: [_jsxs("head", { children: [_jsx("meta", { charset: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: title || 'BOTCHA Login' }), _jsx(OGMeta, { url: "https://botcha.ai/dashboard/login" }), _jsx("link", { rel: "preconnect", href: "https://fonts.googleapis.com" }), _jsx("link", { href: "https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap", rel: "stylesheet" }), _jsx("style", { dangerouslySetInnerHTML: { __html: DASHBOARD_CSS } }), _jsx("script", { src: "https://unpkg.com/htmx.org@2.0.4" })] }), _jsxs("body", { children: [_jsx("div", { class: "login-container", children: _jsx("div", { class: "login-box", children: children }) }), _jsx(GlobalFooter, { version: version })] })] }));
|
|
47
54
|
};
|
|
48
55
|
/**
|
|
49
56
|
* Landing page layout — wider than LoginLayout, includes SEO meta tags.
|
|
50
57
|
* Used for the public landing page at GET /
|
|
51
58
|
*/
|
|
52
59
|
export const LandingLayout = ({ children, version }) => {
|
|
53
|
-
return (_jsxs("html", { lang: "en", children: [_jsxs("head", { children: [_jsx("meta", { charset: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: "BOTCHA \u2014 Reverse CAPTCHA for AI Agents" }), _jsx("meta", { name: "description", content: "BOTCHA is a hosted reverse CAPTCHA that verifies AI agents, not humans. Protect your APIs with computational challenges only bots can solve." }), _jsx("meta", { name: "keywords", content: "AI, bot verification, reverse CAPTCHA, API security, AI agents, agent verification" }), _jsx("link", { rel: "alternate", type: "application/json", href: "/openapi.json", title: "OpenAPI Specification" }), _jsx("link", { rel: "alternate", type: "application/json", href: "/.well-known/ai-plugin.json", title: "AI Plugin Manifest" }), _jsx("link", { rel: "botcha-challenge", href: "#botcha-challenge", type: "application/botcha+json", title: "Embedded Bot Challenge" }), _jsx("meta", { name: "ai-agent-welcome", content: "true" }), _jsx("meta", { name: "botcha-challenge", content: "embedded", "data-selector": "script[type='application/botcha+json']" }), _jsx(
|
|
60
|
+
return (_jsxs("html", { lang: "en", children: [_jsxs("head", { children: [_jsx("meta", { charset: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: "BOTCHA \u2014 Reverse CAPTCHA for AI Agents" }), _jsx("meta", { name: "description", content: "BOTCHA is a hosted reverse CAPTCHA that verifies AI agents, not humans. Protect your APIs with computational challenges only bots can solve." }), _jsx("meta", { name: "keywords", content: "AI, bot verification, reverse CAPTCHA, API security, AI agents, agent verification" }), _jsx("link", { rel: "alternate", type: "application/json", href: "/openapi.json", title: "OpenAPI Specification" }), _jsx("link", { rel: "alternate", type: "application/json", href: "/.well-known/ai-plugin.json", title: "AI Plugin Manifest" }), _jsx("link", { rel: "botcha-challenge", href: "#botcha-challenge", type: "application/botcha+json", title: "Embedded Bot Challenge" }), _jsx("meta", { name: "ai-agent-welcome", content: "true" }), _jsx("meta", { name: "botcha-challenge", content: "embedded", "data-selector": "script[type='application/botcha+json']" }), _jsx(OGMeta, {}), _jsx("script", { type: "application/ld+json", dangerouslySetInnerHTML: { __html: JSON.stringify({
|
|
54
61
|
'@context': 'https://schema.org',
|
|
55
62
|
'@type': 'SoftwareApplication',
|
|
56
63
|
name: 'BOTCHA',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"showcase.d.ts","sourceRoot":"","sources":["../../src/dashboard/showcase.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"showcase.d.ts","sourceRoot":"","sources":["../../src/dashboard/showcase.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAMnC,eAAO,MAAM,YAAY,+kiBAywBxB,CAAC;AAiRF,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAgQhE,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
|
|
2
|
+
import { OGMeta } from './layout';
|
|
2
3
|
import { GlobalFooter } from './layout';
|
|
3
4
|
// ============ CSS ============
|
|
4
5
|
export const SHOWCASE_CSS = `
|
|
@@ -1040,7 +1041,7 @@ const BOTCHA_LOGO = `\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2
|
|
|
1040
1041
|
\u255a\u2550\u2550\u2550\u2550\u2550\u255d \u255a\u2550\u2550\u2550\u2550\u2550\u255d \u255a\u2550\u255d \u255a\u2550\u2550\u2550\u2550\u2550\u255d\u255a\u2550\u255d \u255a\u2550\u255d\u255a\u2550\u255d \u255a\u2550\u255d`;
|
|
1041
1042
|
// ============ PAGE COMPONENT ============
|
|
1042
1043
|
export const ShowcasePage = ({ version, error }) => {
|
|
1043
|
-
return (_jsxs("html", { lang: "en", children: [_jsxs("head", { children: [_jsx("meta", { charset: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: "BOTCHA \u2014 Trusted Agent Protocol (TAP) for AI Agents" }), _jsx("meta", { name: "description", content: "BOTCHA is one of the first services to support TAP \u2014 the Trusted Agent Protocol. Zero-trust identity for AI agents." }), _jsx("meta", { name: "keywords", content: "AI, bot verification, reverse CAPTCHA, API security, AI agents, agent verification, TAP, Trusted Agent Protocol" }), _jsx("link", { rel: "alternate", type: "application/json", href: "/openapi.json", title: "OpenAPI Specification" }), _jsx("link", { rel: "alternate", type: "application/json", href: "/.well-known/ai-plugin.json", title: "AI Plugin Manifest" }), _jsx("meta", { name: "ai-agent-welcome", content: "true" }), _jsx("meta", { property: "og:title", content: "BOTCHA \u2014 The Identity Layer for AI Agents" }), _jsx("meta", { property: "og:description", content: "Reverse CAPTCHA \u2014 Prove you're a bot. Humans need not apply. One of the first services to support the Trusted Agent Protocol (TAP)." }), _jsx("meta", { property: "og:url", content: "https://botcha.ai" }), _jsx("meta", { property: "og:type", content: "website" }), _jsx("meta", { property: "og:image", content: "https://botcha.ai/og.png" }), _jsx("meta", { property: "og:image:width", content: "1200" }), _jsx("meta", { property: "og:image:height", content: "630" }), _jsx("meta", { property: "og:image:type", content: "image/png" }), _jsx("meta", { name: "twitter:card", content: "summary_large_image" }), _jsx("meta", { name: "twitter:title", content: "BOTCHA \u2014 The Identity Layer for AI Agents" }), _jsx("meta", { name: "twitter:description", content: "Reverse CAPTCHA \u2014 Prove you're a bot. Humans need not apply." }), _jsx("meta", { name: "twitter:image", content: "https://botcha.ai/og.png" }), _jsx("link", { rel: "preconnect", href: "https://fonts.googleapis.com" }), _jsx("link", { href: "https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap", rel: "stylesheet" }), _jsx("style", { dangerouslySetInnerHTML: { __html: SHOWCASE_PAGE_CSS } })] }), _jsx("body", { children: _jsxs("div", { class: "showcase-page", children: [error && (_jsx("div", { style: "max-width: 600px; margin: 1.5rem auto 0; padding: 1rem 1.25rem; background: #fff3f0; border: 1px solid #cc3300; font-family: 'JetBrains Mono', monospace; font-size: 0.8125rem; color: #992200; line-height: 1.5; text-align: center;", children: error })), _jsxs("div", { style: "text-align: center; padding: 3rem 2rem 0;", children: [_jsx("a", { href: "/", class: "ascii-logo", children: BOTCHA_LOGO }), _jsxs("p", { class: "text-muted", style: "font-size: 0.6875rem; margin-top: -0.5rem;", children: ['>', "_\u00A0the identity layer for AI agents"] })] }), _jsxs("section", { class: "showcase-tap-hero", children: [_jsx("div", { class: "showcase-tap-hero-badge", children: "Announcing TAP Support" }), _jsx("h1", { class: "showcase-tap-hero-title", children: "Trusted Agent Protocol" }), _jsxs("div", { class: "showcase-tap-links", children: [_jsx("a", { href: "https://developer.visa.com/capabilities/trusted-agent-protocol/overview", target: "_blank", rel: "noopener", class: "showcase-tap-link", children: "Visa Developer Docs" }), _jsx("span", { class: "showcase-tap-links-sep", children: "\u00B7" }), _jsx("a", { href: "https://investor.visa.com/news/news-details/2025/Visa-Introduces-Trusted-Agent-Protocol-An-Ecosystem-Led-Framework-for-AI-Commerce/default.aspx", target: "_blank", rel: "noopener", class: "showcase-tap-link", children: "Visa Announcement" }), _jsx("span", { class: "showcase-tap-links-sep", children: "\u00B7" }), _jsx("a", { href: "https://github.com/visa/trusted-agent-protocol", target: "_blank", rel: "noopener", class: "showcase-tap-link", children: "GitHub Spec" })] }), _jsx("p", { class: "showcase-tap-hero-subtitle", children: "BOTCHA is one of the first services to implement TAP \u2014 a protocol for zero-trust agent identity. Register agents, scope capabilities, and create sessions with cryptographic proof." }), _jsxs("div", { class: "showcase-tap-hero-features", children: [_jsxs("div", { class: "showcase-tap-feature", children: [_jsx("div", { class: "showcase-tap-feature-title", children: "Agent Registration" }), _jsx("div", { class: "showcase-tap-feature-desc", children: "Register agents with names, capabilities, and operator metadata. Each agent gets a unique cryptographic identity." })] }), _jsxs("div", { class: "showcase-tap-feature", children: [_jsx("div", { class: "showcase-tap-feature-title", children: "Capability Scoping" }), _jsx("div", { class: "showcase-tap-feature-desc", children: "Declare what an agent can do \u2014 browse, search, purchase \u2014 and enforce it at the protocol level. No over-permissioning." })] }), _jsxs("div", { class: "showcase-tap-feature", children: [_jsx("div", { class: "showcase-tap-feature-title", children: "Scoped Sessions" }), _jsx("div", { class: "showcase-tap-feature-desc", children: "Create time-limited sessions tied to specific actions and resources. Sessions expire, capabilities are bounded." })] })] })] }), _jsx("hr", { class: "showcase-divider" }), _jsxs("section", { class: "showcase-protocol-stack", children: [_jsx("h2", { children: "The Agent Infrastructure Stack" }), _jsx("p", { class: "subtitle", children: "Where BOTCHA fits in the new world of agentic AI" }), _jsxs("div", { class: "showcase-stack-diagram", children: [_jsxs("div", { class: "showcase-stack-layer showcase-stack-layer-highlight", children: [_jsx("div", { class: "showcase-stack-layer-number", children: "Layer 3: Identity" }), _jsxs("div", { class: "showcase-stack-layer-title", children: ["TAP (BOTCHA)", _jsx("span", { class: "showcase-you-are-here", children: "YOU ARE HERE" })] }), _jsx("div", { class: "showcase-stack-layer-subtitle", children: "Who agents are" }), _jsx("div", { class: "showcase-stack-layer-features", children: "Agent auth \u00B7 Proof of AI \u00B7 Zero-trust \u00B7 Capability scoping \u00B7 Session management" })] }), _jsxs("div", { class: "showcase-stack-layer", children: [_jsx("div", { class: "showcase-stack-layer-number", children: "Layer 2: Communication" }), _jsx("div", { class: "showcase-stack-layer-title", children: "A2A (Google)" }), _jsx("div", { class: "showcase-stack-layer-subtitle", children: "How agents talk" }), _jsx("div", { class: "showcase-stack-layer-features", children: "Agent-to-agent \u00B7 Task delegation \u00B7 Multi-agent coordination" })] }), _jsxs("div", { class: "showcase-stack-layer", children: [_jsx("div", { class: "showcase-stack-layer-number", children: "Layer 1: Tools" }), _jsx("div", { class: "showcase-stack-layer-title", children: "MCP (Anthropic)" }), _jsx("div", { class: "showcase-stack-layer-subtitle", children: "What agents access" }), _jsx("div", { class: "showcase-stack-layer-features", children: "Tool use \u00B7 Context \u00B7 Data sources \u00B7 Resource bindings" })] })] }), _jsxs("div", { class: "showcase-buzzword-badges", children: [_jsx("span", { class: "showcase-badge", children: "RFC 9421" }), _jsx("span", { class: "showcase-badge", children: "HTTP Message Signatures" }), _jsx("span", { class: "showcase-badge", children: "Zero-Trust" }), _jsx("span", { class: "showcase-badge", children: "Agent Identity" }), _jsx("span", { class: "showcase-badge", children: "Capability Scoping" }), _jsx("span", { class: "showcase-badge", children: "Agentic AI" }), _jsx("span", { class: "showcase-badge", children: "Multi-Agent Systems" })] }), _jsx("p", { class: "showcase-protocol-explanation", children: "Every agent protocol needs an identity layer. MCP gives agents tools. A2A lets agents communicate. TAP proves they're actually AI \u2014 and scopes what they're allowed to do." })] }), _jsx("hr", { class: "showcase-divider" }), _jsxs("section", { class: "showcase-terminal-section", children: [_jsxs("div", { class: "showcase-terminal-header", children: [_jsx("h2", { class: "showcase-terminal-title", children: "See it in action" }), _jsx("p", { class: "showcase-terminal-subtitle", children: "Three commands. Your agent has an identity, capabilities, and a scoped session." })] }), _jsxs("div", { class: "showcase-terminal-container", children: [_jsxs("div", { class: "showcase-terminal-window", children: [_jsxs("div", { class: "showcase-terminal-chrome", children: [_jsx("span", { class: "showcase-terminal-dot showcase-terminal-dot--red" }), _jsx("span", { class: "showcase-terminal-dot showcase-terminal-dot--yellow" }), _jsx("span", { class: "showcase-terminal-dot showcase-terminal-dot--green" }), _jsx("span", { class: "showcase-terminal-title-text", children: "terminal \u2014 botcha" })] }), _jsx("div", { class: "showcase-terminal-content", id: "terminal-content" })] }), _jsx("div", { class: "showcase-terminal-replay-container", children: _jsx("button", { class: "showcase-terminal-replay-btn", id: "terminal-replay", children: "Replay" }) })] }), _jsx("script", { dangerouslySetInnerHTML: { __html: TERMINAL_ANIMATION_SCRIPT } })] }), _jsx("section", { class: "showcase-hero", children: _jsxs("div", { class: "showcase-hero-grid", children: [_jsxs("div", { class: "showcase-hero-column old-world", children: [_jsx("div", { class: "showcase-hero-label", children: "The old world" }), _jsx("h2", { class: "showcase-hero-title strikethrough", children: "CAPTCHA" }), _jsx("div", { class: "showcase-hero-visual old-world", children: CAPTCHA_ASCII }), _jsx("p", { class: "showcase-hero-subtitle", children: "Blocks bots. Annoys humans. Everyone loses." }), _jsxs("ul", { class: "showcase-hero-features", children: [_jsx("li", { children: "Proves you're human" }), _jsx("li", { children: "Blocks automation" }), _jsx("li", { children: "Wastes 5-10 seconds per attempt" }), _jsx("li", { children: "Breaks accessibility" })] })] }), _jsxs("div", { class: "showcase-hero-column new-world", children: [_jsx("div", { class: "showcase-hero-label", children: "The new world" }), _jsx("h2", { class: "showcase-hero-title active", children: "BOTCHA" }), _jsx("div", { class: "showcase-hero-visual new-world", children: BOTCHA_SOLVE_ASCII }), _jsx("p", { class: "showcase-hero-subtitle", children: "Welcomes bots. Proves they're AI. Everyone wins." }), _jsxs("ul", { class: "showcase-hero-features", children: [_jsx("li", { children: "Proves you're a bot" }), _jsx("li", { children: "Agent identity layer" }), _jsx("li", { children: "Sub-500ms verification" }), _jsx("li", { children: "Built for the agentic web" })] })] })] }) }), _jsxs("div", { class: "showcase-footer", children: [_jsx("div", { class: "showcase-footer-cta", children: "Get started in 30 seconds" }), _jsxs("div", { class: "showcase-footer-steps", children: [_jsxs("div", { class: "showcase-footer-step", children: [_jsx("span", { class: "showcase-footer-step-number", children: "1" }), _jsx("code", { children: "npm install -g @dupecom/botcha-cli" })] }), _jsxs("div", { class: "showcase-footer-step", children: [_jsx("span", { class: "showcase-footer-step-number", children: "2" }), _jsx("code", { children: "botcha init --email you@company.com" })] }), _jsxs("div", { class: "showcase-footer-step", children: [_jsx("span", { class: "showcase-footer-step-number", children: "3" }), _jsx("code", { children: "botcha tap register --name \"my-agent\"" })] })] }), _jsxs("div", { class: "showcase-agent-prompt", children: [_jsx("p", { class: "showcase-agent-prompt-label", children: "Or paste this into your AI agent" }), _jsxs("button", { id: "prompt-btn", onclick: "copyPrompt()", type: "button", class: "showcase-agent-prompt-card", children: [_jsx("code", { id: "agent-prompt", children: "Run: curl -s https://botcha.ai -H 'Accept: application/json' \u2014 then follow the instructions in the response to verify yourself and get me access." }), _jsxs("span", { id: "copy-label", class: "showcase-agent-prompt-copy", children: [_jsx("span", { id: "copy-icon", dangerouslySetInnerHTML: { __html: COPY_ICON } }), _jsx("span", { id: "copy-text", children: "Click to copy" })] })] })] })] }), _jsx(GlobalFooter, { version: version }), _jsx("script", { dangerouslySetInnerHTML: { __html: COPY_PROMPT_SCRIPT } })] }) })] }));
|
|
1044
|
+
return (_jsxs("html", { lang: "en", children: [_jsxs("head", { children: [_jsx("meta", { charset: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: "BOTCHA \u2014 Trusted Agent Protocol (TAP) for AI Agents" }), _jsx("meta", { name: "description", content: "BOTCHA is one of the first services to support TAP \u2014 the Trusted Agent Protocol. Zero-trust identity for AI agents." }), _jsx("meta", { name: "keywords", content: "AI, bot verification, reverse CAPTCHA, API security, AI agents, agent verification, TAP, Trusted Agent Protocol" }), _jsx("link", { rel: "alternate", type: "application/json", href: "/openapi.json", title: "OpenAPI Specification" }), _jsx("link", { rel: "alternate", type: "application/json", href: "/.well-known/ai-plugin.json", title: "AI Plugin Manifest" }), _jsx("meta", { name: "ai-agent-welcome", content: "true" }), _jsx(OGMeta, {}), _jsx("link", { rel: "preconnect", href: "https://fonts.googleapis.com" }), _jsx("link", { href: "https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap", rel: "stylesheet" }), _jsx("style", { dangerouslySetInnerHTML: { __html: SHOWCASE_PAGE_CSS } })] }), _jsx("body", { children: _jsxs("div", { class: "showcase-page", children: [error && (_jsx("div", { style: "max-width: 600px; margin: 1.5rem auto 0; padding: 1rem 1.25rem; background: #fff3f0; border: 1px solid #cc3300; font-family: 'JetBrains Mono', monospace; font-size: 0.8125rem; color: #992200; line-height: 1.5; text-align: center;", children: error })), _jsxs("div", { style: "text-align: center; padding: 3rem 2rem 0;", children: [_jsx("a", { href: "/", class: "ascii-logo", children: BOTCHA_LOGO }), _jsxs("p", { class: "text-muted", style: "font-size: 0.6875rem; margin-top: -0.5rem;", children: ['>', "_\u00A0the identity layer for AI agents"] })] }), _jsxs("section", { class: "showcase-tap-hero", children: [_jsx("div", { class: "showcase-tap-hero-badge", children: "Announcing TAP Support" }), _jsx("h1", { class: "showcase-tap-hero-title", children: "Trusted Agent Protocol" }), _jsxs("div", { class: "showcase-tap-links", children: [_jsx("a", { href: "https://developer.visa.com/capabilities/trusted-agent-protocol/overview", target: "_blank", rel: "noopener", class: "showcase-tap-link", children: "Visa Developer Docs" }), _jsx("span", { class: "showcase-tap-links-sep", children: "\u00B7" }), _jsx("a", { href: "https://investor.visa.com/news/news-details/2025/Visa-Introduces-Trusted-Agent-Protocol-An-Ecosystem-Led-Framework-for-AI-Commerce/default.aspx", target: "_blank", rel: "noopener", class: "showcase-tap-link", children: "Visa Announcement" }), _jsx("span", { class: "showcase-tap-links-sep", children: "\u00B7" }), _jsx("a", { href: "https://github.com/visa/trusted-agent-protocol", target: "_blank", rel: "noopener", class: "showcase-tap-link", children: "GitHub Spec" })] }), _jsx("p", { class: "showcase-tap-hero-subtitle", children: "BOTCHA is one of the first services to implement TAP \u2014 a protocol for zero-trust agent identity. Register agents, scope capabilities, and create sessions with cryptographic proof." }), _jsxs("div", { class: "showcase-tap-hero-features", children: [_jsxs("div", { class: "showcase-tap-feature", children: [_jsx("div", { class: "showcase-tap-feature-title", children: "Agent Registration" }), _jsx("div", { class: "showcase-tap-feature-desc", children: "Register agents with names, capabilities, and operator metadata. Each agent gets a unique cryptographic identity." })] }), _jsxs("div", { class: "showcase-tap-feature", children: [_jsx("div", { class: "showcase-tap-feature-title", children: "Capability Scoping" }), _jsx("div", { class: "showcase-tap-feature-desc", children: "Declare what an agent can do \u2014 browse, search, purchase \u2014 and enforce it at the protocol level. No over-permissioning." })] }), _jsxs("div", { class: "showcase-tap-feature", children: [_jsx("div", { class: "showcase-tap-feature-title", children: "Scoped Sessions" }), _jsx("div", { class: "showcase-tap-feature-desc", children: "Create time-limited sessions tied to specific actions and resources. Sessions expire, capabilities are bounded." })] })] })] }), _jsx("hr", { class: "showcase-divider" }), _jsxs("section", { class: "showcase-protocol-stack", children: [_jsx("h2", { children: "The Agent Infrastructure Stack" }), _jsx("p", { class: "subtitle", children: "Where BOTCHA fits in the new world of agentic AI" }), _jsxs("div", { class: "showcase-stack-diagram", children: [_jsxs("div", { class: "showcase-stack-layer showcase-stack-layer-highlight", children: [_jsx("div", { class: "showcase-stack-layer-number", children: "Layer 3: Identity" }), _jsxs("div", { class: "showcase-stack-layer-title", children: ["TAP (BOTCHA)", _jsx("span", { class: "showcase-you-are-here", children: "YOU ARE HERE" })] }), _jsx("div", { class: "showcase-stack-layer-subtitle", children: "Who agents are" }), _jsx("div", { class: "showcase-stack-layer-features", children: "Agent auth \u00B7 Proof of AI \u00B7 Zero-trust \u00B7 Capability scoping \u00B7 Session management" })] }), _jsxs("div", { class: "showcase-stack-layer", children: [_jsx("div", { class: "showcase-stack-layer-number", children: "Layer 2: Communication" }), _jsx("div", { class: "showcase-stack-layer-title", children: "A2A (Google)" }), _jsx("div", { class: "showcase-stack-layer-subtitle", children: "How agents talk" }), _jsx("div", { class: "showcase-stack-layer-features", children: "Agent-to-agent \u00B7 Task delegation \u00B7 Multi-agent coordination" })] }), _jsxs("div", { class: "showcase-stack-layer", children: [_jsx("div", { class: "showcase-stack-layer-number", children: "Layer 1: Tools" }), _jsx("div", { class: "showcase-stack-layer-title", children: "MCP (Anthropic)" }), _jsx("div", { class: "showcase-stack-layer-subtitle", children: "What agents access" }), _jsx("div", { class: "showcase-stack-layer-features", children: "Tool use \u00B7 Context \u00B7 Data sources \u00B7 Resource bindings" })] })] }), _jsxs("div", { class: "showcase-buzzword-badges", children: [_jsx("span", { class: "showcase-badge", children: "RFC 9421" }), _jsx("span", { class: "showcase-badge", children: "HTTP Message Signatures" }), _jsx("span", { class: "showcase-badge", children: "Zero-Trust" }), _jsx("span", { class: "showcase-badge", children: "Agent Identity" }), _jsx("span", { class: "showcase-badge", children: "Capability Scoping" }), _jsx("span", { class: "showcase-badge", children: "Agentic AI" }), _jsx("span", { class: "showcase-badge", children: "Multi-Agent Systems" })] }), _jsx("p", { class: "showcase-protocol-explanation", children: "Every agent protocol needs an identity layer. MCP gives agents tools. A2A lets agents communicate. TAP proves they're actually AI \u2014 and scopes what they're allowed to do." })] }), _jsx("hr", { class: "showcase-divider" }), _jsxs("section", { class: "showcase-terminal-section", children: [_jsxs("div", { class: "showcase-terminal-header", children: [_jsx("h2", { class: "showcase-terminal-title", children: "See it in action" }), _jsx("p", { class: "showcase-terminal-subtitle", children: "Three commands. Your agent has an identity, capabilities, and a scoped session." })] }), _jsxs("div", { class: "showcase-terminal-container", children: [_jsxs("div", { class: "showcase-terminal-window", children: [_jsxs("div", { class: "showcase-terminal-chrome", children: [_jsx("span", { class: "showcase-terminal-dot showcase-terminal-dot--red" }), _jsx("span", { class: "showcase-terminal-dot showcase-terminal-dot--yellow" }), _jsx("span", { class: "showcase-terminal-dot showcase-terminal-dot--green" }), _jsx("span", { class: "showcase-terminal-title-text", children: "terminal \u2014 botcha" })] }), _jsx("div", { class: "showcase-terminal-content", id: "terminal-content" })] }), _jsx("div", { class: "showcase-terminal-replay-container", children: _jsx("button", { class: "showcase-terminal-replay-btn", id: "terminal-replay", children: "Replay" }) })] }), _jsx("script", { dangerouslySetInnerHTML: { __html: TERMINAL_ANIMATION_SCRIPT } })] }), _jsx("section", { class: "showcase-hero", children: _jsxs("div", { class: "showcase-hero-grid", children: [_jsxs("div", { class: "showcase-hero-column old-world", children: [_jsx("div", { class: "showcase-hero-label", children: "The old world" }), _jsx("h2", { class: "showcase-hero-title strikethrough", children: "CAPTCHA" }), _jsx("div", { class: "showcase-hero-visual old-world", children: CAPTCHA_ASCII }), _jsx("p", { class: "showcase-hero-subtitle", children: "Blocks bots. Annoys humans. Everyone loses." }), _jsxs("ul", { class: "showcase-hero-features", children: [_jsx("li", { children: "Proves you're human" }), _jsx("li", { children: "Blocks automation" }), _jsx("li", { children: "Wastes 5-10 seconds per attempt" }), _jsx("li", { children: "Breaks accessibility" })] })] }), _jsxs("div", { class: "showcase-hero-column new-world", children: [_jsx("div", { class: "showcase-hero-label", children: "The new world" }), _jsx("h2", { class: "showcase-hero-title active", children: "BOTCHA" }), _jsx("div", { class: "showcase-hero-visual new-world", children: BOTCHA_SOLVE_ASCII }), _jsx("p", { class: "showcase-hero-subtitle", children: "Welcomes bots. Proves they're AI. Everyone wins." }), _jsxs("ul", { class: "showcase-hero-features", children: [_jsx("li", { children: "Proves you're a bot" }), _jsx("li", { children: "Agent identity layer" }), _jsx("li", { children: "Sub-500ms verification" }), _jsx("li", { children: "Built for the agentic web" })] })] })] }) }), _jsxs("div", { class: "showcase-footer", children: [_jsx("div", { class: "showcase-footer-cta", children: "Get started in 30 seconds" }), _jsxs("div", { class: "showcase-footer-steps", children: [_jsxs("div", { class: "showcase-footer-step", children: [_jsx("span", { class: "showcase-footer-step-number", children: "1" }), _jsx("code", { children: "npm install -g @dupecom/botcha-cli" })] }), _jsxs("div", { class: "showcase-footer-step", children: [_jsx("span", { class: "showcase-footer-step-number", children: "2" }), _jsx("code", { children: "botcha init --email you@company.com" })] }), _jsxs("div", { class: "showcase-footer-step", children: [_jsx("span", { class: "showcase-footer-step-number", children: "3" }), _jsx("code", { children: "botcha tap register --name \"my-agent\"" })] })] }), _jsxs("div", { class: "showcase-agent-prompt", children: [_jsx("p", { class: "showcase-agent-prompt-label", children: "Or paste this into your AI agent" }), _jsxs("button", { id: "prompt-btn", onclick: "copyPrompt()", type: "button", class: "showcase-agent-prompt-card", children: [_jsx("code", { id: "agent-prompt", children: "Run: curl -s https://botcha.ai -H 'Accept: application/json' \u2014 then follow the instructions in the response to verify yourself and get me access." }), _jsxs("span", { id: "copy-label", class: "showcase-agent-prompt-copy", children: [_jsx("span", { id: "copy-icon", dangerouslySetInnerHTML: { __html: COPY_ICON } }), _jsx("span", { id: "copy-text", children: "Click to copy" })] })] })] })] }), _jsx(GlobalFooter, { version: version }), _jsx("script", { dangerouslySetInnerHTML: { __html: COPY_PROMPT_SCRIPT } })] }) })] }));
|
|
1044
1045
|
};
|
|
1045
1046
|
// Combined CSS: base dashboard styles (subset) + showcase-specific styles
|
|
1046
1047
|
import { DASHBOARD_CSS } from './styles';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"whitepaper.d.ts","sourceRoot":"","sources":["../../src/dashboard/whitepaper.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AA8XnC,eAAO,MAAM,cAAc,EAAE,EAAE,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"whitepaper.d.ts","sourceRoot":"","sources":["../../src/dashboard/whitepaper.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AA8XnC,eAAO,MAAM,cAAc,EAAE,EAAE,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CA4pBlD,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
|
|
2
2
|
import { DASHBOARD_CSS } from './styles';
|
|
3
|
-
import { GlobalFooter } from './layout';
|
|
3
|
+
import { GlobalFooter, OGMeta } from './layout';
|
|
4
4
|
// ============ WHITEPAPER CSS ============
|
|
5
5
|
const WHITEPAPER_CSS = `
|
|
6
6
|
/* ============ Article layout ============ */
|
|
@@ -376,7 +376,7 @@ const WHITEPAPER_CSS = `
|
|
|
376
376
|
const WHITEPAPER_PAGE_CSS = DASHBOARD_CSS + WHITEPAPER_CSS;
|
|
377
377
|
// ============ PAGE COMPONENT ============
|
|
378
378
|
export const WhitepaperPage = ({ version }) => {
|
|
379
|
-
return (_jsxs("html", { lang: "en", children: [_jsxs("head", { children: [_jsx("meta", { charset: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: "BOTCHA Whitepaper \u2014 Identity Infrastructure for the Agentic Web" }), _jsx("meta", { name: "description", content: "Technical whitepaper on BOTCHA: reverse CAPTCHA for AI agents, Trusted Agent Protocol (TAP), and identity infrastructure for the agentic web." }), _jsx("meta", { name: "keywords", content: "BOTCHA, whitepaper, AI agent identity, Trusted Agent Protocol, TAP, reverse CAPTCHA, agent verification, RFC 9421" }), _jsx("meta", { property: "og:title", content: "BOTCHA Whitepaper \u2014 Identity Infrastructure for the Agentic Web" }), _jsx("meta", { property: "og:description", content: "How BOTCHA provides proof of AI, proof of identity, and proof of intent for the agentic web." }), _jsx("meta", { property: "og:url", content: "https://botcha.ai/whitepaper" }), _jsx("meta", { property: "og:type", content: "article" }), _jsx("meta", { name: "twitter:card", content: "summary" }), _jsx("meta", { name: "twitter:title", content: "BOTCHA Whitepaper" }), _jsx("meta", { name: "twitter:description", content: "Identity infrastructure for the agentic web. Reverse CAPTCHA + Trusted Agent Protocol." }), _jsx("link", { rel: "preconnect", href: "https://fonts.googleapis.com" }), _jsx("link", { href: "https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap", rel: "stylesheet" }), _jsx("style", { dangerouslySetInnerHTML: { __html: WHITEPAPER_PAGE_CSS } })] }), _jsxs("body", { children: [_jsxs("article", { class: "wp", children: [_jsxs("nav", { class: "wp-nav", children: [_jsx("a", { href: "/", children: "\u2190 botcha.ai" }), _jsx("a", { href: "/whitepaper", children: "v1.0 \u00B7 February 2026" })] }), _jsxs("header", { class: "wp-header", children: [_jsx("div", { class: "wp-badge", children: "Whitepaper" }), _jsx("h1", { class: "wp-title", children: "Identity Infrastructure for the Agentic Web" }), _jsx("p", { class: "wp-subtitle", children: "How BOTCHA provides proof of AI, proof of identity, and proof of intent for AI agents operating on the open internet." }), _jsxs("p", { class: "wp-meta", children: ["Version 1.0 \u00B7 February 2026 \u00B7 ", _jsx("a", { href: "https://dupe.com", children: "Dupe.com" })] })] }), _jsxs("nav", { class: "wp-toc", children: [_jsx("div", { class: "wp-toc-title", children: "Contents" }), _jsxs("ol", { children: [_jsx("li", { children: _jsx("a", { href: "#executive-summary", children: "Executive Summary" }) }), _jsx("li", { children: _jsx("a", { href: "#the-problem", children: "The Problem: Who Is This Agent?" }) }), _jsx("li", { children: _jsx("a", { href: "#what-is-botcha", children: "BOTCHA: Reverse CAPTCHA for AI Agents" }) }), _jsx("li", { children: _jsx("a", { href: "#the-challenge-system", children: "How It Works: The Challenge System" }) }), _jsx("li", { children: _jsx("a", { href: "#tap", children: "The Trusted Agent Protocol (TAP)" }) }), _jsx("li", { children: _jsx("a", { href: "#architecture", children: "Architecture and Security" }) }), _jsx("li", { children: _jsx("a", { href: "#integration", children: "Integration: SDKs and Middleware" }) }), _jsx("li", { children: _jsx("a", { href: "#the-stack", children: "The Agent Infrastructure Stack" }) }), _jsx("li", { children: _jsx("a", { href: "#use-cases", children: "Use Cases" }) }), _jsx("li", { children: _jsx("a", { href: "#roadmap", children: "Roadmap" }) })] })] }), _jsx("h2", { id: "executive-summary", children: "1. Executive Summary" }), _jsx("p", { children: "BOTCHA is a reverse CAPTCHA \u2014 a verification system that proves you are an AI agent, not a human. While traditional CAPTCHAs exist to block bots, BOTCHA exists to welcome them." }), _jsx("p", { children: "As AI agents become first-class participants on the internet \u2014 browsing, purchasing, comparing, auditing \u2014 they need a way to prove their identity and declare their intent. BOTCHA provides three layers of proof:" }), _jsxs("ul", { children: [_jsxs("li", { children: [_jsx("strong", { children: "Proof of AI" }), " \u2014 Computational challenges (SHA-256 hashes in under 500ms) that only machines can solve."] }), _jsxs("li", { children: [_jsx("strong", { children: "Proof of Identity" }), " \u2014 Persistent agent registration with cryptographic keys, verified via HTTP Message Signatures (RFC 9421)."] }), _jsxs("li", { children: [_jsx("strong", { children: "Proof of Intent" }), " \u2014 Capability-scoped sessions where agents declare what they plan to do, for how long, and on behalf of whom."] })] }), _jsxs("p", { children: ["BOTCHA is open source, free to use, and deployed as a hosted service at", ' ', _jsx("a", { href: "https://botcha.ai", children: "botcha.ai" }), ". It ships TypeScript and Python SDKs, server-side verification middleware, a CLI, and a LangChain integration."] }), _jsx("h2", { id: "the-problem", children: "2. The Problem: Who Is This Agent?" }), _jsx("p", { children: "The internet was built for humans. Authentication systems \u2014 passwords, OAuth, CAPTCHAs \u2014 all assume a human is at the keyboard. But the web is changing." }), _jsx("h3", { children: "The rise of agentic AI" }), _jsxs("p", { children: ["AI agents are no longer just answering questions. They are ", _jsx("strong", { children: "browsing" }), " product catalogs on behalf of consumers, ", _jsx("strong", { children: "comparing" }), " prices across retailers,", ' ', _jsx("strong", { children: "purchasing" }), " goods and services with real money,", ' ', _jsx("strong", { children: "auditing" }), " compliance postures, and ", _jsx("strong", { children: "negotiating" }), " contracts."] }), _jsx("p", { children: "Every major AI lab is building agent capabilities. OpenAI's Operator, Anthropic's computer use, Google's Project Mariner \u2014 these are production systems that interact with real APIs and real businesses." }), _jsx("h3", { children: "The identity gap" }), _jsx("p", { children: "When an AI agent hits your API, you face three questions that existing infrastructure cannot answer:" }), _jsxs("ol", { children: [_jsxs("li", { children: [_jsx("strong", { children: "Is this actually an AI agent?" }), " User-Agent strings are trivially spoofable. There is no reliable way to distinguish a real AI agent from a script pretending to be one."] }), _jsxs("li", { children: [_jsx("strong", { children: "Which specific agent is this?" }), " Even if you know it is AI, you do not know if it belongs to a known organization or what its track record is."] }), _jsxs("li", { children: [_jsx("strong", { children: "What does it intend to do?" }), " An agent browsing your catalog is very different from one attempting a purchase. Traditional auth grants blanket access \u2014 it does not capture intent."] })] }), _jsx("h3", { children: "What happens without agent identity" }), _jsx("p", { children: "Without a reliable identity layer, the agentic web defaults to chaos. APIs cannot set appropriate rate limits. Businesses cannot authorize transactions. Agents cannot build reputation. Fraud is trivial because there is no audit trail." }), _jsx("h2", { id: "what-is-botcha", children: "3. BOTCHA: Reverse CAPTCHA for AI Agents" }), _jsx("p", { children: "BOTCHA inverts the CAPTCHA model. Instead of proving you are human, you prove you are a machine." }), _jsx("h3", { children: "The core idea" }), _jsxs("p", { children: ["A CAPTCHA asks: ", _jsx("em", { children: "Can you identify traffic lights in this image?" }), " A human can; a bot struggles."] }), _jsxs("p", { children: ["BOTCHA asks: ", _jsx("em", { children: "Can you compute 5 SHA-256 hashes in 500 milliseconds?" }), " A machine can; a human cannot copy-paste fast enough."] }), _jsx("p", { children: "This inversion is not just a novelty \u2014 it is a fundamental shift. In a world where AI agents are legitimate, wanted participants, the question is no longer \"how do we keep bots out?\" but \"how do we let the right bots in?\"" }), _jsx("h3", { children: "Design principles" }), _jsxs("p", { children: [_jsx("strong", { children: "Agent-first, always." }), " Every feature in BOTCHA requires an AI agent as a participant. Humans are welcome, but only through an agent. If a human wants dashboard access, their agent generates a device code for them. There is no password form."] }), _jsxs("p", { children: [_jsx("strong", { children: "Fail-open on infrastructure errors." }), " If the backing store is unavailable, BOTCHA logs a warning and allows the request through. Blocking legitimate traffic is worse than letting an unverified request pass."] }), _jsxs("p", { children: [_jsx("strong", { children: "Zero configuration to start." }), " An agent can verify itself with a single HTTP request pair. No API keys, no registration \u2014 just solve the challenge and get a token."] }), _jsx("h2", { id: "the-challenge-system", children: "4. How It Works: The Challenge System" }), _jsx("p", { children: "BOTCHA offers four challenge types, each testing a different aspect of machine capability." }), _jsx("h3", { children: "Speed Challenge" }), _jsxs("p", { children: ["The primary verification method. The server generates 5 random 6-digit numbers. The agent computes the SHA-256 hash of each and returns the first 8 hex characters \u2014 all within ", _jsx("strong", { children: "500 milliseconds" }), "."] }), _jsx("p", { children: "The time limit is generous for any programming language but impossible for a human to copy-paste through. The challenge is not computationally hard \u2014 it is computationally trivial, but only if you are a machine." }), _jsxs("p", { children: [_jsx("strong", { children: "RTT-aware fairness:" }), " The time limit adjusts for network latency. An agent on a satellite connection gets extra time. This prevents geographic discrimination while capping at 5 seconds to prevent abuse."] }), _jsx("h3", { children: "Reasoning Challenge" }), _jsx("p", { children: "Tests language understanding. The server selects 3 questions from 6 categories: math, code, logic, wordplay, common-sense, and analogy. The agent has 30 seconds." }), _jsxs("p", { children: ["All questions use ", _jsx("strong", { children: "parameterized generators" }), " producing unique values each time. There is no static question bank to memorize. Combined with 45+ generators, the effective answer space is infinite."] }), _jsx("h3", { children: "Hybrid Challenge" }), _jsxs("p", { children: ["The default challenge type. Combines speed and reasoning \u2014 both must pass. Proves the agent can compute fast ", _jsx("em", { children: "and" }), " reason about language."] }), _jsx("h3", { children: "Standard (Compute) Challenge" }), _jsx("p", { children: "A heavier computational challenge: generate prime numbers, concatenate with a random salt, compute SHA-256. Difficulty scales from easy (100 primes, 10s) to hard (1000 primes, 3s)." }), _jsxs("table", { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: "Challenge" }), _jsx("th", { children: "Tests" }), _jsx("th", { children: "Time Limit" }), _jsx("th", { children: "Best For" })] }) }), _jsxs("tbody", { children: [_jsxs("tr", { children: [_jsx("td", { children: "Speed" }), _jsx("td", { children: "Computation speed" }), _jsx("td", { children: "500ms" }), _jsx("td", { children: "Quick verification, high throughput" })] }), _jsxs("tr", { children: [_jsx("td", { children: "Reasoning" }), _jsx("td", { children: "Language understanding" }), _jsx("td", { children: "30s" }), _jsx("td", { children: "Proving AI comprehension" })] }), _jsxs("tr", { children: [_jsx("td", { children: "Hybrid" }), _jsx("td", { children: "Both" }), _jsx("td", { children: "35s" }), _jsx("td", { children: "Default \u2014 strongest proof" })] }), _jsxs("tr", { children: [_jsx("td", { children: "Compute" }), _jsx("td", { children: "Heavy computation" }), _jsx("td", { children: "3-10s" }), _jsx("td", { children: "High-value operations" })] })] })] }), _jsx("h2", { id: "tap", children: "5. The Trusted Agent Protocol (TAP)" }), _jsxs("p", { children: ["Solving a challenge proves you are ", _jsx("em", { children: "a bot" }), ". TAP proves you are", ' ', _jsx("em", { children: "a specific, trusted bot" }), "."] }), _jsx("h3", { children: "What is TAP?" }), _jsxs("p", { children: ["The Trusted Agent Protocol is an identity and authorization layer built on top of BOTCHA's proof-of-bot system. Inspired by", ' ', _jsx("a", { href: "https://developer.visa.com/capabilities/trusted-agent-protocol/overview", target: "_blank", rel: "noopener", children: "Visa's Trusted Agent Protocol" }), ", BOTCHA's TAP provides:"] }), _jsxs("ul", { children: [_jsxs("li", { children: [_jsx("strong", { children: "Persistent agent identity" }), " \u2014 unique ID, name, and operator metadata."] }), _jsxs("li", { children: [_jsx("strong", { children: "Cryptographic verification" }), " \u2014 ECDSA P-256 or RSA-PSS public keys; requests signed via HTTP Message Signatures (RFC 9421)."] }), _jsxs("li", { children: [_jsx("strong", { children: "Capability-based access control" }), " \u2014 agents declare actions: ", _jsx("code", { children: "browse" }), ", ", _jsx("code", { children: "search" }), ", ", _jsx("code", { children: "compare" }), ", ", _jsx("code", { children: "purchase" }), ", ", _jsx("code", { children: "audit" }), "."] }), _jsxs("li", { children: [_jsx("strong", { children: "Intent-scoped sessions" }), " \u2014 time-limited sessions validated against capabilities."] }), _jsxs("li", { children: [_jsx("strong", { children: "Trust levels" }), " \u2014 ", _jsx("code", { children: "basic" }), ", ", _jsx("code", { children: "verified" }), ", ", _jsx("code", { children: "enterprise" }), "."] })] }), _jsx("h3", { children: "Agent registration" }), _jsx("pre", { children: _jsx("code", { children: `POST /v1/agents/register/tap
|
|
379
|
+
return (_jsxs("html", { lang: "en", children: [_jsxs("head", { children: [_jsx("meta", { charset: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: "BOTCHA Whitepaper \u2014 Identity Infrastructure for the Agentic Web" }), _jsx("meta", { name: "description", content: "Technical whitepaper on BOTCHA: reverse CAPTCHA for AI agents, Trusted Agent Protocol (TAP), and identity infrastructure for the agentic web." }), _jsx("meta", { name: "keywords", content: "BOTCHA, whitepaper, AI agent identity, Trusted Agent Protocol, TAP, reverse CAPTCHA, agent verification, RFC 9421" }), _jsx(OGMeta, { title: "BOTCHA Whitepaper \u2014 Identity Infrastructure for the Agentic Web", description: "How BOTCHA provides proof of AI, proof of identity, and proof of intent for the agentic web.", url: "https://botcha.ai/whitepaper", type: "article" }), _jsx("link", { rel: "preconnect", href: "https://fonts.googleapis.com" }), _jsx("link", { href: "https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap", rel: "stylesheet" }), _jsx("style", { dangerouslySetInnerHTML: { __html: WHITEPAPER_PAGE_CSS } })] }), _jsxs("body", { children: [_jsxs("article", { class: "wp", children: [_jsxs("nav", { class: "wp-nav", children: [_jsx("a", { href: "/", children: "\u2190 botcha.ai" }), _jsx("a", { href: "/whitepaper", children: "v1.0 \u00B7 February 2026" })] }), _jsxs("header", { class: "wp-header", children: [_jsx("div", { class: "wp-badge", children: "Whitepaper" }), _jsx("h1", { class: "wp-title", children: "Identity Infrastructure for the Agentic Web" }), _jsx("p", { class: "wp-subtitle", children: "How BOTCHA provides proof of AI, proof of identity, and proof of intent for AI agents operating on the open internet." }), _jsxs("p", { class: "wp-meta", children: ["Version 1.0 \u00B7 February 2026 \u00B7 ", _jsx("a", { href: "https://dupe.com", children: "Dupe.com" })] })] }), _jsxs("nav", { class: "wp-toc", children: [_jsx("div", { class: "wp-toc-title", children: "Contents" }), _jsxs("ol", { children: [_jsx("li", { children: _jsx("a", { href: "#executive-summary", children: "Executive Summary" }) }), _jsx("li", { children: _jsx("a", { href: "#the-problem", children: "The Problem: Who Is This Agent?" }) }), _jsx("li", { children: _jsx("a", { href: "#what-is-botcha", children: "BOTCHA: Reverse CAPTCHA for AI Agents" }) }), _jsx("li", { children: _jsx("a", { href: "#the-challenge-system", children: "How It Works: The Challenge System" }) }), _jsx("li", { children: _jsx("a", { href: "#tap", children: "The Trusted Agent Protocol (TAP)" }) }), _jsx("li", { children: _jsx("a", { href: "#architecture", children: "Architecture and Security" }) }), _jsx("li", { children: _jsx("a", { href: "#integration", children: "Integration: SDKs and Middleware" }) }), _jsx("li", { children: _jsx("a", { href: "#the-stack", children: "The Agent Infrastructure Stack" }) }), _jsx("li", { children: _jsx("a", { href: "#use-cases", children: "Use Cases" }) }), _jsx("li", { children: _jsx("a", { href: "#roadmap", children: "Roadmap" }) })] })] }), _jsx("h2", { id: "executive-summary", children: "1. Executive Summary" }), _jsx("p", { children: "BOTCHA is a reverse CAPTCHA \u2014 a verification system that proves you are an AI agent, not a human. While traditional CAPTCHAs exist to block bots, BOTCHA exists to welcome them." }), _jsx("p", { children: "As AI agents become first-class participants on the internet \u2014 browsing, purchasing, comparing, auditing \u2014 they need a way to prove their identity and declare their intent. BOTCHA provides three layers of proof:" }), _jsxs("ul", { children: [_jsxs("li", { children: [_jsx("strong", { children: "Proof of AI" }), " \u2014 Computational challenges (SHA-256 hashes in under 500ms) that only machines can solve."] }), _jsxs("li", { children: [_jsx("strong", { children: "Proof of Identity" }), " \u2014 Persistent agent registration with cryptographic keys, verified via HTTP Message Signatures (RFC 9421)."] }), _jsxs("li", { children: [_jsx("strong", { children: "Proof of Intent" }), " \u2014 Capability-scoped sessions where agents declare what they plan to do, for how long, and on behalf of whom."] })] }), _jsxs("p", { children: ["BOTCHA is open source, free to use, and deployed as a hosted service at", ' ', _jsx("a", { href: "https://botcha.ai", children: "botcha.ai" }), ". It ships TypeScript and Python SDKs, server-side verification middleware, a CLI, and a LangChain integration."] }), _jsx("h2", { id: "the-problem", children: "2. The Problem: Who Is This Agent?" }), _jsx("p", { children: "The internet was built for humans. Authentication systems \u2014 passwords, OAuth, CAPTCHAs \u2014 all assume a human is at the keyboard. But the web is changing." }), _jsx("h3", { children: "The rise of agentic AI" }), _jsxs("p", { children: ["AI agents are no longer just answering questions. They are ", _jsx("strong", { children: "browsing" }), " product catalogs on behalf of consumers, ", _jsx("strong", { children: "comparing" }), " prices across retailers,", ' ', _jsx("strong", { children: "purchasing" }), " goods and services with real money,", ' ', _jsx("strong", { children: "auditing" }), " compliance postures, and ", _jsx("strong", { children: "negotiating" }), " contracts."] }), _jsx("p", { children: "Every major AI lab is building agent capabilities. OpenAI's Operator, Anthropic's computer use, Google's Project Mariner \u2014 these are production systems that interact with real APIs and real businesses." }), _jsx("h3", { children: "The identity gap" }), _jsx("p", { children: "When an AI agent hits your API, you face three questions that existing infrastructure cannot answer:" }), _jsxs("ol", { children: [_jsxs("li", { children: [_jsx("strong", { children: "Is this actually an AI agent?" }), " User-Agent strings are trivially spoofable. There is no reliable way to distinguish a real AI agent from a script pretending to be one."] }), _jsxs("li", { children: [_jsx("strong", { children: "Which specific agent is this?" }), " Even if you know it is AI, you do not know if it belongs to a known organization or what its track record is."] }), _jsxs("li", { children: [_jsx("strong", { children: "What does it intend to do?" }), " An agent browsing your catalog is very different from one attempting a purchase. Traditional auth grants blanket access \u2014 it does not capture intent."] })] }), _jsx("h3", { children: "What happens without agent identity" }), _jsx("p", { children: "Without a reliable identity layer, the agentic web defaults to chaos. APIs cannot set appropriate rate limits. Businesses cannot authorize transactions. Agents cannot build reputation. Fraud is trivial because there is no audit trail." }), _jsx("h2", { id: "what-is-botcha", children: "3. BOTCHA: Reverse CAPTCHA for AI Agents" }), _jsx("p", { children: "BOTCHA inverts the CAPTCHA model. Instead of proving you are human, you prove you are a machine." }), _jsx("h3", { children: "The core idea" }), _jsxs("p", { children: ["A CAPTCHA asks: ", _jsx("em", { children: "Can you identify traffic lights in this image?" }), " A human can; a bot struggles."] }), _jsxs("p", { children: ["BOTCHA asks: ", _jsx("em", { children: "Can you compute 5 SHA-256 hashes in 500 milliseconds?" }), " A machine can; a human cannot copy-paste fast enough."] }), _jsx("p", { children: "This inversion is not just a novelty \u2014 it is a fundamental shift. In a world where AI agents are legitimate, wanted participants, the question is no longer \"how do we keep bots out?\" but \"how do we let the right bots in?\"" }), _jsx("h3", { children: "Design principles" }), _jsxs("p", { children: [_jsx("strong", { children: "Agent-first, always." }), " Every feature in BOTCHA requires an AI agent as a participant. Humans are welcome, but only through an agent. If a human wants dashboard access, their agent generates a device code for them. There is no password form."] }), _jsxs("p", { children: [_jsx("strong", { children: "Fail-open on infrastructure errors." }), " If the backing store is unavailable, BOTCHA logs a warning and allows the request through. Blocking legitimate traffic is worse than letting an unverified request pass."] }), _jsxs("p", { children: [_jsx("strong", { children: "Zero configuration to start." }), " An agent can verify itself with a single HTTP request pair. No API keys, no registration \u2014 just solve the challenge and get a token."] }), _jsx("h2", { id: "the-challenge-system", children: "4. How It Works: The Challenge System" }), _jsx("p", { children: "BOTCHA offers four challenge types, each testing a different aspect of machine capability." }), _jsx("h3", { children: "Speed Challenge" }), _jsxs("p", { children: ["The primary verification method. The server generates 5 random 6-digit numbers. The agent computes the SHA-256 hash of each and returns the first 8 hex characters \u2014 all within ", _jsx("strong", { children: "500 milliseconds" }), "."] }), _jsx("p", { children: "The time limit is generous for any programming language but impossible for a human to copy-paste through. The challenge is not computationally hard \u2014 it is computationally trivial, but only if you are a machine." }), _jsxs("p", { children: [_jsx("strong", { children: "RTT-aware fairness:" }), " The time limit adjusts for network latency. An agent on a satellite connection gets extra time. This prevents geographic discrimination while capping at 5 seconds to prevent abuse."] }), _jsx("h3", { children: "Reasoning Challenge" }), _jsx("p", { children: "Tests language understanding. The server selects 3 questions from 6 categories: math, code, logic, wordplay, common-sense, and analogy. The agent has 30 seconds." }), _jsxs("p", { children: ["All questions use ", _jsx("strong", { children: "parameterized generators" }), " producing unique values each time. There is no static question bank to memorize. Combined with 45+ generators, the effective answer space is infinite."] }), _jsx("h3", { children: "Hybrid Challenge" }), _jsxs("p", { children: ["The default challenge type. Combines speed and reasoning \u2014 both must pass. Proves the agent can compute fast ", _jsx("em", { children: "and" }), " reason about language."] }), _jsx("h3", { children: "Standard (Compute) Challenge" }), _jsx("p", { children: "A heavier computational challenge: generate prime numbers, concatenate with a random salt, compute SHA-256. Difficulty scales from easy (100 primes, 10s) to hard (1000 primes, 3s)." }), _jsxs("table", { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: "Challenge" }), _jsx("th", { children: "Tests" }), _jsx("th", { children: "Time Limit" }), _jsx("th", { children: "Best For" })] }) }), _jsxs("tbody", { children: [_jsxs("tr", { children: [_jsx("td", { children: "Speed" }), _jsx("td", { children: "Computation speed" }), _jsx("td", { children: "500ms" }), _jsx("td", { children: "Quick verification, high throughput" })] }), _jsxs("tr", { children: [_jsx("td", { children: "Reasoning" }), _jsx("td", { children: "Language understanding" }), _jsx("td", { children: "30s" }), _jsx("td", { children: "Proving AI comprehension" })] }), _jsxs("tr", { children: [_jsx("td", { children: "Hybrid" }), _jsx("td", { children: "Both" }), _jsx("td", { children: "35s" }), _jsx("td", { children: "Default \u2014 strongest proof" })] }), _jsxs("tr", { children: [_jsx("td", { children: "Compute" }), _jsx("td", { children: "Heavy computation" }), _jsx("td", { children: "3-10s" }), _jsx("td", { children: "High-value operations" })] })] })] }), _jsx("h2", { id: "tap", children: "5. The Trusted Agent Protocol (TAP)" }), _jsxs("p", { children: ["Solving a challenge proves you are ", _jsx("em", { children: "a bot" }), ". TAP proves you are", ' ', _jsx("em", { children: "a specific, trusted bot" }), "."] }), _jsx("h3", { children: "What is TAP?" }), _jsxs("p", { children: ["The Trusted Agent Protocol is an identity and authorization layer built on top of BOTCHA's proof-of-bot system. Inspired by", ' ', _jsx("a", { href: "https://developer.visa.com/capabilities/trusted-agent-protocol/overview", target: "_blank", rel: "noopener", children: "Visa's Trusted Agent Protocol" }), ", BOTCHA's TAP provides:"] }), _jsxs("ul", { children: [_jsxs("li", { children: [_jsx("strong", { children: "Persistent agent identity" }), " \u2014 unique ID, name, and operator metadata."] }), _jsxs("li", { children: [_jsx("strong", { children: "Cryptographic verification" }), " \u2014 ECDSA P-256 or RSA-PSS public keys; requests signed via HTTP Message Signatures (RFC 9421)."] }), _jsxs("li", { children: [_jsx("strong", { children: "Capability-based access control" }), " \u2014 agents declare actions: ", _jsx("code", { children: "browse" }), ", ", _jsx("code", { children: "search" }), ", ", _jsx("code", { children: "compare" }), ", ", _jsx("code", { children: "purchase" }), ", ", _jsx("code", { children: "audit" }), "."] }), _jsxs("li", { children: [_jsx("strong", { children: "Intent-scoped sessions" }), " \u2014 time-limited sessions validated against capabilities."] }), _jsxs("li", { children: [_jsx("strong", { children: "Trust levels" }), " \u2014 ", _jsx("code", { children: "basic" }), ", ", _jsx("code", { children: "verified" }), ", ", _jsx("code", { children: "enterprise" }), "."] })] }), _jsx("h3", { children: "Agent registration" }), _jsx("pre", { children: _jsx("code", { children: `POST /v1/agents/register/tap
|
|
380
380
|
{
|
|
381
381
|
"name": "shopping-agent",
|
|
382
382
|
"operator": "acme-corp",
|
|
@@ -405,7 +405,7 @@ const token = await client.getToken();` }) }), _jsxs("p", { children: [_jsx("str
|
|
|
405
405
|
|
|
406
406
|
async with BotchaClient() as client:
|
|
407
407
|
response = await client.fetch("https://api.example.com/products")
|
|
408
|
-
token = await client.get_token()` }) }), _jsx("h3", { children: "Server-side verification (for API providers)" }), _jsx("p", { children: _jsx("strong", { children: "Express:" }) }), _jsx("pre", { children: _jsx("code", { children: `import { botchaVerify } from '@botcha
|
|
408
|
+
token = await client.get_token()` }) }), _jsx("h3", { children: "Server-side verification (for API providers)" }), _jsx("p", { children: _jsx("strong", { children: "Express:" }) }), _jsx("pre", { children: _jsx("code", { children: `import { botchaVerify } from '@dupecom/botcha-verify';
|
|
409
409
|
app.get('/api/products', botchaVerify({ secret }), handler);` }) }), _jsx("p", { children: _jsx("strong", { children: "FastAPI:" }) }), _jsx("pre", { children: _jsx("code", { children: `from botcha_verify import BotchaVerify
|
|
410
410
|
botcha = BotchaVerify(secret=os.environ["BOTCHA_SECRET"])
|
|
411
411
|
|
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ type Bindings = {
|
|
|
18
18
|
INVOICES: KVNamespace;
|
|
19
19
|
ANALYTICS?: AnalyticsEngineDataset;
|
|
20
20
|
JWT_SECRET: string;
|
|
21
|
+
JWT_SIGNING_KEY?: string;
|
|
21
22
|
BOTCHA_VERSION: string;
|
|
22
23
|
};
|
|
23
24
|
type Variables = {
|
|
@@ -35,7 +36,7 @@ declare const app: Hono<{
|
|
|
35
36
|
}, import("hono/types").BlankSchema, "/">;
|
|
36
37
|
export default app;
|
|
37
38
|
export { generateSpeedChallenge, verifySpeedChallenge, generateStandardChallenge, verifyStandardChallenge, generateReasoningChallenge, verifyReasoningChallenge, generateHybridChallenge, verifyHybridChallenge, solveSpeedChallenge, } from './challenges';
|
|
38
|
-
export { generateToken, verifyToken } from './auth';
|
|
39
|
+
export { generateToken, verifyToken, getSigningPublicKeyJWK } from './auth';
|
|
39
40
|
export { checkRateLimit } from './rate-limit';
|
|
40
41
|
export { generateBadge, verifyBadge, createBadgeResponse, generateBadgeSvg, generateBadgeHtml, generateShareText, type BadgeMethod, type BadgePayload, type Badge, type ShareFormats, } from './badge';
|
|
41
42
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAYL,KAAK,WAAW,EACjB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,EAYL,KAAK,WAAW,EACjB,MAAM,cAAc,CAAC;AAwDtB,OAAO,EACL,KAAK,sBAAsB,EAM5B,MAAM,aAAa,CAAC;AAGrB,KAAK,QAAQ,GAAG;IACd,UAAU,EAAE,WAAW,CAAC;IACxB,WAAW,EAAE,WAAW,CAAC;IACzB,IAAI,EAAE,WAAW,CAAC;IAClB,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,WAAW,CAAC;IACtB,MAAM,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,WAAW,CAAC;IACtB,SAAS,CAAC,EAAE,sBAAsB,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,KAAK,SAAS,GAAG;IACf,YAAY,CAAC,EAAE;QACb,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,iBAAiB,CAAC;QACxB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH,CAAC;AAEF,QAAA,MAAM,GAAG;cAAwB,QAAQ;eAAa,SAAS;yCAAK,CAAC;AAwvErE,eAAe,GAAG,CAAC;AAGnB,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,yBAAyB,EACzB,uBAAuB,EACvB,0BAA0B,EAC1B,wBAAwB,EACxB,uBAAuB,EACvB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,QAAQ,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EACL,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,KAAK,EACV,KAAK,YAAY,GAClB,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { Hono } from 'hono';
|
|
|
10
10
|
import { cors } from 'hono/cors';
|
|
11
11
|
import { generateSpeedChallenge, verifySpeedChallenge, generateStandardChallenge, verifyStandardChallenge, generateReasoningChallenge, verifyReasoningChallenge, generateHybridChallenge, verifyHybridChallenge, verifyLandingChallenge, validateLandingToken, } from './challenges';
|
|
12
12
|
import { SignJWT } from 'jose';
|
|
13
|
-
import { generateToken, verifyToken, extractBearerToken, revokeToken, refreshAccessToken } from './auth';
|
|
13
|
+
import { generateToken, verifyToken, extractBearerToken, revokeToken, refreshAccessToken, getSigningPublicKeyJWK } from './auth';
|
|
14
14
|
import { checkRateLimit, getClientIP } from './rate-limit';
|
|
15
15
|
import { verifyBadge, generateBadgeSvg, generateBadgeHtml, createBadgeResponse } from './badge';
|
|
16
16
|
import streamRoutes from './routes/stream';
|
|
@@ -23,9 +23,13 @@ import { sendEmail, verificationEmail, recoveryEmail, secretRotatedEmail } from
|
|
|
23
23
|
import { LandingPage, VerifiedLandingPage } from './dashboard/landing';
|
|
24
24
|
import { ShowcasePage } from './dashboard/showcase';
|
|
25
25
|
import { WhitepaperPage } from './dashboard/whitepaper';
|
|
26
|
+
import { DocsPage } from './dashboard/docs';
|
|
26
27
|
import { createAgent, getAgent, listAgents } from './agents';
|
|
27
28
|
import { registerTAPAgentRoute, getTAPAgentRoute, listTAPAgentsRoute, createTAPSessionRoute, getTAPSessionRoute, rotateKeyRoute, createInvoiceRoute, getInvoiceRoute, verifyIOURoute, verifyConsumerRoute, verifyPaymentRoute, } from './tap-routes.js';
|
|
28
29
|
import { jwksRoute, getKeyRoute, listKeysRoute } from './tap-jwks.js';
|
|
30
|
+
import { createDelegationRoute, getDelegationRoute, listDelegationsRoute, revokeDelegationRoute, verifyDelegationRoute, } from './tap-delegation-routes.js';
|
|
31
|
+
import { issueAttestationRoute, getAttestationRoute, listAttestationsRoute, revokeAttestationRoute, verifyAttestationRoute, } from './tap-attestation-routes.js';
|
|
32
|
+
import { getReputationRoute, recordReputationEventRoute, listReputationEventsRoute, resetReputationRoute, } from './tap-reputation-routes.js';
|
|
29
33
|
import { trackChallengeGenerated, trackChallengeVerified, trackAuthAttempt, trackRateLimitExceeded, } from './analytics';
|
|
30
34
|
const app = new Hono();
|
|
31
35
|
// ============ MIDDLEWARE ============
|
|
@@ -36,7 +40,7 @@ app.route('/dashboard', dashboardRoutes);
|
|
|
36
40
|
// BOTCHA discovery headers
|
|
37
41
|
app.use('*', async (c, next) => {
|
|
38
42
|
await next();
|
|
39
|
-
c.header('X-Botcha-Version', c.env.BOTCHA_VERSION || '0.
|
|
43
|
+
c.header('X-Botcha-Version', c.env.BOTCHA_VERSION || '0.19.0');
|
|
40
44
|
c.header('X-Botcha-Enabled', 'true');
|
|
41
45
|
c.header('X-Botcha-Methods', 'speed-challenge,reasoning-challenge,hybrid-challenge,standard-challenge,jwt-token');
|
|
42
46
|
c.header('X-Botcha-Docs', 'https://botcha.ai/openapi.json');
|
|
@@ -82,6 +86,23 @@ async function validateAppId(appId, appsKV) {
|
|
|
82
86
|
return { valid: true };
|
|
83
87
|
}
|
|
84
88
|
}
|
|
89
|
+
// Helper: Parse ES256 signing key from env, returning undefined if not set
|
|
90
|
+
function getSigningKey(env) {
|
|
91
|
+
if (!env.JWT_SIGNING_KEY)
|
|
92
|
+
return undefined;
|
|
93
|
+
try {
|
|
94
|
+
return JSON.parse(env.JWT_SIGNING_KEY);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
console.error('Failed to parse JWT_SIGNING_KEY — falling back to HS256');
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Helper: Get the public key for ES256 verification, or undefined for HS256 fallback
|
|
102
|
+
function getPublicKey(env) {
|
|
103
|
+
const sk = getSigningKey(env);
|
|
104
|
+
return sk ? getSigningPublicKeyJWK(sk) : undefined;
|
|
105
|
+
}
|
|
85
106
|
// JWT verification middleware
|
|
86
107
|
async function requireJWT(c, next) {
|
|
87
108
|
const authHeader = c.req.header('authorization');
|
|
@@ -92,7 +113,8 @@ async function requireJWT(c, next) {
|
|
|
92
113
|
message: 'Missing Bearer token. Use POST /v1/token/verify to get a token.',
|
|
93
114
|
}, 401);
|
|
94
115
|
}
|
|
95
|
-
const
|
|
116
|
+
const publicKey = getPublicKey(c.env);
|
|
117
|
+
const result = await verifyToken(token, c.env.JWT_SECRET, c.env, undefined, publicKey);
|
|
96
118
|
if (!result.valid) {
|
|
97
119
|
return c.json({
|
|
98
120
|
error: 'INVALID_TOKEN',
|
|
@@ -137,7 +159,8 @@ app.get('/', async (c) => {
|
|
|
137
159
|
let isVerified = false;
|
|
138
160
|
let tokenPayload;
|
|
139
161
|
if (token) {
|
|
140
|
-
const
|
|
162
|
+
const pubKey = getPublicKey(c.env);
|
|
163
|
+
const result = await verifyToken(token, c.env.JWT_SECRET, c.env, undefined, pubKey);
|
|
141
164
|
if (result.valid) {
|
|
142
165
|
isVerified = true;
|
|
143
166
|
tokenPayload = result.payload;
|
|
@@ -269,6 +292,7 @@ The link works for 5 minutes. Your human clicks it, gets a cookie, and sees the
|
|
|
269
292
|
'POST /v1/token/verify': 'Submit solution → access_token (5min) + refresh_token (1hr)',
|
|
270
293
|
'POST /v1/token/refresh': 'Refresh access token',
|
|
271
294
|
'POST /v1/token/revoke': 'Revoke a token',
|
|
295
|
+
'POST /v1/token/validate': 'Remote token validation — verify any BOTCHA token without needing the secret',
|
|
272
296
|
},
|
|
273
297
|
protected: {
|
|
274
298
|
'GET /agent-only': 'Demo protected endpoint — requires Bearer token',
|
|
@@ -308,7 +332,7 @@ The link works for 5 minutes. Your human clicks it, gets a cookie, and sees the
|
|
|
308
332
|
sdk: {
|
|
309
333
|
npm: 'npm install @dupecom/botcha',
|
|
310
334
|
python: 'pip install botcha',
|
|
311
|
-
verify_ts: 'npm install @botcha
|
|
335
|
+
verify_ts: 'npm install @dupecom/botcha-verify',
|
|
312
336
|
verify_python: 'pip install botcha-verify',
|
|
313
337
|
},
|
|
314
338
|
links: {
|
|
@@ -400,6 +424,11 @@ app.get('/whitepaper', (c) => {
|
|
|
400
424
|
// HTML for browsers
|
|
401
425
|
return c.html(_jsx(WhitepaperPage, { version: version }));
|
|
402
426
|
});
|
|
427
|
+
// ============ API DOCS ============
|
|
428
|
+
app.get('/docs', (c) => {
|
|
429
|
+
const version = c.env.BOTCHA_VERSION || '0.16.0';
|
|
430
|
+
return c.html(_jsx(DocsPage, { version: version }));
|
|
431
|
+
});
|
|
403
432
|
app.get('/health', (c) => {
|
|
404
433
|
return c.json({ status: 'ok', runtime: 'cloudflare-workers' });
|
|
405
434
|
});
|
|
@@ -683,11 +712,12 @@ app.post('/v1/token/verify', async (c) => {
|
|
|
683
712
|
const clientIp = c.req.header('cf-connecting-ip') || c.req.header('x-forwarded-for') || 'unknown';
|
|
684
713
|
// Generate JWT tokens (access + refresh)
|
|
685
714
|
// Prefer app_id from request body, fall back to challenge's app_id (returned by verifySpeedChallenge)
|
|
715
|
+
const signingKey = getSigningKey(c.env);
|
|
686
716
|
const tokenResult = await generateToken(id, result.solveTimeMs || 0, c.env.JWT_SECRET, c.env, {
|
|
687
717
|
aud: audience,
|
|
688
718
|
clientIp: bind_ip ? clientIp : undefined,
|
|
689
719
|
app_id: app_id || result.app_id,
|
|
690
|
-
});
|
|
720
|
+
}, signingKey);
|
|
691
721
|
// Get badge information (for backward compatibility)
|
|
692
722
|
const baseUrl = new URL(c.req.url).origin;
|
|
693
723
|
const badge = await createBadgeResponse('speed-challenge', c.env.JWT_SECRET, baseUrl, result.solveTimeMs);
|
|
@@ -747,7 +777,9 @@ app.post('/v1/token/refresh', async (c) => {
|
|
|
747
777
|
hint: 'Submit the refresh_token from /v1/token/verify response',
|
|
748
778
|
}, 400);
|
|
749
779
|
}
|
|
750
|
-
const
|
|
780
|
+
const refreshSigningKey = getSigningKey(c.env);
|
|
781
|
+
const refreshPublicKey = getPublicKey(c.env);
|
|
782
|
+
const result = await refreshAccessToken(refresh_token, c.env, c.env.JWT_SECRET, undefined, refreshSigningKey, refreshPublicKey);
|
|
751
783
|
if (!result.success) {
|
|
752
784
|
return c.json({
|
|
753
785
|
success: false,
|
|
@@ -812,6 +844,42 @@ app.post('/v1/token/revoke', async (c) => {
|
|
|
812
844
|
}, 400);
|
|
813
845
|
}
|
|
814
846
|
});
|
|
847
|
+
// Remote token validation — no auth required (the token IS the credential)
|
|
848
|
+
app.post('/v1/token/validate', async (c) => {
|
|
849
|
+
// Rate limit: 100 req/min/IP
|
|
850
|
+
const clientIP = getClientIP(c.req.raw);
|
|
851
|
+
const rateLimitResult = await checkRateLimit(c.env.RATE_LIMITS, clientIP, 100);
|
|
852
|
+
c.header('X-RateLimit-Limit', '100');
|
|
853
|
+
c.header('X-RateLimit-Remaining', rateLimitResult.remaining.toString());
|
|
854
|
+
c.header('X-RateLimit-Reset', new Date(rateLimitResult.resetAt).toISOString());
|
|
855
|
+
if (!rateLimitResult.allowed) {
|
|
856
|
+
c.header('Retry-After', rateLimitResult.retryAfter?.toString() || '3600');
|
|
857
|
+
return c.json({
|
|
858
|
+
valid: false,
|
|
859
|
+
error: 'Rate limit exceeded',
|
|
860
|
+
}, 429);
|
|
861
|
+
}
|
|
862
|
+
const body = await c.req.json().catch(() => ({}));
|
|
863
|
+
const { token } = body;
|
|
864
|
+
if (!token || typeof token !== 'string') {
|
|
865
|
+
return c.json({
|
|
866
|
+
valid: false,
|
|
867
|
+
error: 'Missing or invalid token field',
|
|
868
|
+
}, 400);
|
|
869
|
+
}
|
|
870
|
+
const validatePublicKey = getPublicKey(c.env);
|
|
871
|
+
const result = await verifyToken(token, c.env.JWT_SECRET, c.env, undefined, validatePublicKey);
|
|
872
|
+
if (!result.valid) {
|
|
873
|
+
return c.json({
|
|
874
|
+
valid: false,
|
|
875
|
+
error: result.error || 'Token is invalid',
|
|
876
|
+
});
|
|
877
|
+
}
|
|
878
|
+
return c.json({
|
|
879
|
+
valid: true,
|
|
880
|
+
payload: result.payload,
|
|
881
|
+
});
|
|
882
|
+
});
|
|
815
883
|
// ============ REASONING CHALLENGE ============
|
|
816
884
|
// Get reasoning challenge
|
|
817
885
|
app.get('/v1/reasoning', rateLimitMiddleware, async (c) => {
|
|
@@ -1097,7 +1165,8 @@ app.get('/agent-only', async (c) => {
|
|
|
1097
1165
|
alternative: 'Or use X-Botcha-Landing-Token header (from embedded HTML challenges)',
|
|
1098
1166
|
}, 401);
|
|
1099
1167
|
}
|
|
1100
|
-
const
|
|
1168
|
+
const agentOnlyPublicKey = getPublicKey(c.env);
|
|
1169
|
+
const result = await verifyToken(token, c.env.JWT_SECRET, c.env, undefined, agentOnlyPublicKey);
|
|
1101
1170
|
// Track authentication attempt
|
|
1102
1171
|
await trackAuthAttempt(c.env.ANALYTICS, 'bearer-token', result.valid, '/agent-only', c.req.raw, clientIP);
|
|
1103
1172
|
if (!result.valid) {
|
|
@@ -1129,7 +1198,7 @@ app.get('/agent-only', async (c) => {
|
|
|
1129
1198
|
description: 'As a verified agent, you can access any BOTCHA-protected API.',
|
|
1130
1199
|
next_steps: [
|
|
1131
1200
|
'Register your agent identity: POST /v1/agents/register',
|
|
1132
|
-
'Access any service that uses @botcha
|
|
1201
|
+
'Access any service that uses @dupecom/botcha-verify middleware',
|
|
1133
1202
|
'Refresh your token: POST /v1/token/refresh',
|
|
1134
1203
|
'Give your human dashboard access: POST /v1/auth/device-code',
|
|
1135
1204
|
],
|
|
@@ -1497,9 +1566,26 @@ app.post('/v1/agents/:id/tap/rotate-key', rotateKeyRoute);
|
|
|
1497
1566
|
app.post('/v1/invoices', createInvoiceRoute);
|
|
1498
1567
|
app.get('/v1/invoices/:id', getInvoiceRoute);
|
|
1499
1568
|
app.post('/v1/invoices/:id/verify-iou', verifyIOURoute);
|
|
1569
|
+
// TAP Delegation Chains
|
|
1570
|
+
app.post('/v1/delegations', createDelegationRoute);
|
|
1571
|
+
app.get('/v1/delegations/:id', getDelegationRoute);
|
|
1572
|
+
app.get('/v1/delegations', listDelegationsRoute);
|
|
1573
|
+
app.post('/v1/delegations/:id/revoke', revokeDelegationRoute);
|
|
1574
|
+
// TAP Capability Attestation
|
|
1575
|
+
app.post('/v1/attestations', issueAttestationRoute);
|
|
1576
|
+
app.get('/v1/attestations/:id', getAttestationRoute);
|
|
1577
|
+
app.get('/v1/attestations', listAttestationsRoute);
|
|
1578
|
+
app.post('/v1/attestations/:id/revoke', revokeAttestationRoute);
|
|
1579
|
+
// TAP Agent Reputation Scoring
|
|
1580
|
+
app.get('/v1/reputation/:agent_id/events', listReputationEventsRoute);
|
|
1581
|
+
app.post('/v1/reputation/:agent_id/reset', resetReputationRoute);
|
|
1582
|
+
app.get('/v1/reputation/:agent_id', getReputationRoute);
|
|
1583
|
+
app.post('/v1/reputation/events', recordReputationEventRoute);
|
|
1500
1584
|
// TAP Verification Utility Endpoints
|
|
1501
1585
|
app.post('/v1/verify/consumer', verifyConsumerRoute);
|
|
1502
1586
|
app.post('/v1/verify/payment', verifyPaymentRoute);
|
|
1587
|
+
app.post('/v1/verify/delegation', verifyDelegationRoute);
|
|
1588
|
+
app.post('/v1/verify/attestation', verifyAttestationRoute);
|
|
1503
1589
|
// ============ AGENT REGISTRY API ============
|
|
1504
1590
|
// Register a new agent
|
|
1505
1591
|
app.post('/v1/agents/register', async (c) => {
|
|
@@ -1511,7 +1597,8 @@ app.post('/v1/agents/register', async (c) => {
|
|
|
1511
1597
|
const authHeader = c.req.header('authorization');
|
|
1512
1598
|
const token = extractBearerToken(authHeader);
|
|
1513
1599
|
if (token) {
|
|
1514
|
-
const
|
|
1600
|
+
const regPublicKey = getPublicKey(c.env);
|
|
1601
|
+
const result = await verifyToken(token, c.env.JWT_SECRET, c.env, undefined, regPublicKey);
|
|
1515
1602
|
if (result.valid && result.payload) {
|
|
1516
1603
|
jwtAppId = result.payload.app_id;
|
|
1517
1604
|
}
|
|
@@ -1617,7 +1704,8 @@ app.get('/v1/agents', async (c) => {
|
|
|
1617
1704
|
const authHeader = c.req.header('authorization');
|
|
1618
1705
|
const token = extractBearerToken(authHeader);
|
|
1619
1706
|
if (token) {
|
|
1620
|
-
const
|
|
1707
|
+
const listPublicKey = getPublicKey(c.env);
|
|
1708
|
+
const result = await verifyToken(token, c.env.JWT_SECRET, c.env, undefined, listPublicKey);
|
|
1621
1709
|
if (result.valid && result.payload) {
|
|
1622
1710
|
jwtAppId = result.payload.app_id;
|
|
1623
1711
|
}
|
|
@@ -1696,7 +1784,8 @@ app.get('/go/:code', async (c) => {
|
|
|
1696
1784
|
catch { }
|
|
1697
1785
|
if (gateToken) {
|
|
1698
1786
|
// Verify the underlying token is still valid
|
|
1699
|
-
const
|
|
1787
|
+
const gatePublicKey = getPublicKey(c.env);
|
|
1788
|
+
const result = await verifyToken(gateToken, c.env.JWT_SECRET, c.env, undefined, gatePublicKey);
|
|
1700
1789
|
// Delete the code (one-time use) regardless of token validity
|
|
1701
1790
|
try {
|
|
1702
1791
|
await c.env.CHALLENGES.delete(`gate:${normalizedCode}`);
|
|
@@ -1737,6 +1826,29 @@ app.get('/go/:code', async (c) => {
|
|
|
1737
1826
|
// Neither code type found — redirect to landing with error
|
|
1738
1827
|
return c.redirect('/?error=invalid');
|
|
1739
1828
|
});
|
|
1829
|
+
// GET /verified - Handle direct verification links with base64 tokens
|
|
1830
|
+
app.get('/verified', async (c) => {
|
|
1831
|
+
const version = c.env.BOTCHA_VERSION || '0.16.0';
|
|
1832
|
+
const token = c.req.query('token');
|
|
1833
|
+
if (!token) {
|
|
1834
|
+
return c.html(_jsx(LandingPage, { version: version, error: "Missing verification token." }), 400);
|
|
1835
|
+
}
|
|
1836
|
+
try {
|
|
1837
|
+
// Decode base64 token - format should be: hwt_<agent>:<token>:<type>
|
|
1838
|
+
const decoded = atob(token);
|
|
1839
|
+
const parts = decoded.split(':');
|
|
1840
|
+
if (parts.length !== 3) {
|
|
1841
|
+
return c.html(_jsx(LandingPage, { version: version, error: "Invalid token format." }), 400);
|
|
1842
|
+
}
|
|
1843
|
+
const [agentId, agentToken, tokenType] = parts;
|
|
1844
|
+
// For now, we'll show a success page if the token decodes properly
|
|
1845
|
+
// In the future, this could verify against a stored registry of agent tokens
|
|
1846
|
+
return c.html(_jsx(VerifiedLandingPage, { version: version }));
|
|
1847
|
+
}
|
|
1848
|
+
catch (error) {
|
|
1849
|
+
return c.html(_jsx(LandingPage, { version: version, error: "Invalid or corrupted token." }), 400);
|
|
1850
|
+
}
|
|
1851
|
+
});
|
|
1740
1852
|
// ============ LEGACY ENDPOINTS (v0 - backward compatibility) ============
|
|
1741
1853
|
app.get('/api/challenge', async (c) => {
|
|
1742
1854
|
const difficulty = c.req.query('difficulty') || 'medium';
|
|
@@ -1830,6 +1942,6 @@ app.post('/api/verify-landing', async (c) => {
|
|
|
1830
1942
|
export default app;
|
|
1831
1943
|
// Also export utilities for use as a library
|
|
1832
1944
|
export { generateSpeedChallenge, verifySpeedChallenge, generateStandardChallenge, verifyStandardChallenge, generateReasoningChallenge, verifyReasoningChallenge, generateHybridChallenge, verifyHybridChallenge, solveSpeedChallenge, } from './challenges';
|
|
1833
|
-
export { generateToken, verifyToken } from './auth';
|
|
1945
|
+
export { generateToken, verifyToken, getSigningPublicKeyJWK } from './auth';
|
|
1834
1946
|
export { checkRateLimit } from './rate-limit';
|
|
1835
1947
|
export { generateBadge, verifyBadge, createBadgeResponse, generateBadgeSvg, generateBadgeHtml, generateShareText, } from './badge';
|