@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.
Files changed (42) hide show
  1. package/README.md +1 -1
  2. package/dist/auth.d.ts +48 -3
  3. package/dist/auth.d.ts.map +1 -1
  4. package/dist/auth.js +89 -21
  5. package/dist/dashboard/docs.d.ts +15 -0
  6. package/dist/dashboard/docs.d.ts.map +1 -0
  7. package/dist/dashboard/docs.js +556 -0
  8. package/dist/dashboard/layout.d.ts +12 -0
  9. package/dist/dashboard/layout.d.ts.map +1 -1
  10. package/dist/dashboard/layout.js +12 -5
  11. package/dist/dashboard/showcase.d.ts.map +1 -1
  12. package/dist/dashboard/showcase.js +2 -1
  13. package/dist/dashboard/whitepaper.d.ts.map +1 -1
  14. package/dist/dashboard/whitepaper.js +3 -3
  15. package/dist/index.d.ts +2 -1
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +125 -13
  18. package/dist/static.d.ts +592 -2
  19. package/dist/static.d.ts.map +1 -1
  20. package/dist/static.js +422 -9
  21. package/dist/tap-attestation-routes.d.ts +204 -0
  22. package/dist/tap-attestation-routes.d.ts.map +1 -0
  23. package/dist/tap-attestation-routes.js +396 -0
  24. package/dist/tap-attestation.d.ts +178 -0
  25. package/dist/tap-attestation.d.ts.map +1 -0
  26. package/dist/tap-attestation.js +416 -0
  27. package/dist/tap-delegation-routes.d.ts +236 -0
  28. package/dist/tap-delegation-routes.d.ts.map +1 -0
  29. package/dist/tap-delegation-routes.js +378 -0
  30. package/dist/tap-delegation.d.ts +127 -0
  31. package/dist/tap-delegation.d.ts.map +1 -0
  32. package/dist/tap-delegation.js +490 -0
  33. package/dist/tap-jwks.d.ts +2 -1
  34. package/dist/tap-jwks.d.ts.map +1 -1
  35. package/dist/tap-jwks.js +31 -7
  36. package/dist/tap-reputation-routes.d.ts +154 -0
  37. package/dist/tap-reputation-routes.d.ts.map +1 -0
  38. package/dist/tap-reputation-routes.js +341 -0
  39. package/dist/tap-reputation.d.ts +136 -0
  40. package/dist/tap-reputation.d.ts.map +1 -0
  41. package/dist/tap-reputation.js +346 -0
  42. package/package.json +1 -1
@@ -1,5 +1,12 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
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("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." }), _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", { name: "twitter:card", content: "summary_large_image" }), _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: 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 })] })] }));
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("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." }), _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", { name: "twitter:card", content: "summary_large_image" }), _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: 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 })] })] }));
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("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("script", { type: "application/ld+json", dangerouslySetInnerHTML: { __html: JSON.stringify({
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;AAKnC,eAAO,MAAM,YAAY,+kiBAywBxB,CAAC;AAiRF,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CA6QhE,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,CAgqBlD,CAAC"}
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/verify';
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
@@ -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;AAmCtB,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,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;AAunErE,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,MAAM,QAAQ,CAAC;AACpD,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"}
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.16.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 result = await verifyToken(token, c.env.JWT_SECRET, c.env);
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 result = await verifyToken(token, c.env.JWT_SECRET, c.env);
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/verify',
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 result = await refreshAccessToken(refresh_token, c.env, c.env.JWT_SECRET);
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 result = await verifyToken(token, c.env.JWT_SECRET, c.env);
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/verify middleware',
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 result = await verifyToken(token, c.env.JWT_SECRET, c.env);
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 result = await verifyToken(token, c.env.JWT_SECRET, c.env);
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 result = await verifyToken(gateToken, c.env.JWT_SECRET, c.env);
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';