@dupecom/botcha 0.13.1 → 0.15.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 (35) hide show
  1. package/README.md +48 -2
  2. package/dist/lib/client/index.d.ts +64 -2
  3. package/dist/lib/client/index.d.ts.map +1 -1
  4. package/dist/lib/client/index.js +136 -1
  5. package/dist/lib/client/types.d.ts +68 -0
  6. package/dist/lib/client/types.d.ts.map +1 -1
  7. package/dist/lib/index.js +2 -0
  8. package/dist/src/challenges/compute.d.ts +19 -0
  9. package/dist/src/challenges/compute.d.ts.map +1 -0
  10. package/dist/src/challenges/compute.js +88 -0
  11. package/dist/src/challenges/hybrid.d.ts +45 -0
  12. package/dist/src/challenges/hybrid.d.ts.map +1 -0
  13. package/dist/src/challenges/hybrid.js +94 -0
  14. package/dist/src/challenges/reasoning.d.ts +29 -0
  15. package/dist/src/challenges/reasoning.d.ts.map +1 -0
  16. package/dist/src/challenges/reasoning.js +414 -0
  17. package/dist/src/challenges/speed.d.ts +34 -0
  18. package/dist/src/challenges/speed.d.ts.map +1 -0
  19. package/dist/src/challenges/speed.js +115 -0
  20. package/dist/src/middleware/tap-enhanced-verify.d.ts +57 -0
  21. package/dist/src/middleware/tap-enhanced-verify.d.ts.map +1 -0
  22. package/dist/src/middleware/tap-enhanced-verify.js +368 -0
  23. package/dist/src/middleware/verify.d.ts +12 -0
  24. package/dist/src/middleware/verify.d.ts.map +1 -0
  25. package/dist/src/middleware/verify.js +141 -0
  26. package/dist/src/utils/badge-image.d.ts +15 -0
  27. package/dist/src/utils/badge-image.d.ts.map +1 -0
  28. package/dist/src/utils/badge-image.js +253 -0
  29. package/dist/src/utils/badge.d.ts +39 -0
  30. package/dist/src/utils/badge.d.ts.map +1 -0
  31. package/dist/src/utils/badge.js +125 -0
  32. package/dist/src/utils/signature.d.ts +23 -0
  33. package/dist/src/utils/signature.d.ts.map +1 -0
  34. package/dist/src/utils/signature.js +160 -0
  35. package/package.json +6 -1
package/README.md CHANGED
@@ -36,7 +36,8 @@ Use cases:
36
36
  - 📧 Email verification, account recovery, and secret rotation
37
37
  - 🤖 Agent-first dashboard auth (challenge-based login + device code handoff)
38
38
  - 🆔 Persistent agent identities with registry
39
- - 🔏 Trusted Agent Protocol (TAP) — cryptographic agent auth with HTTP Message Signatures
39
+ - 🔏 Trusted Agent Protocol (TAP) — cryptographic agent auth with HTTP Message Signatures (SDK: `registerTAPAgent`, `createTAPSession`)
40
+ - 🌐 TAP showcase homepage at [botcha.ai](https://botcha.ai) — one of the first services to implement [Visa's Trusted Agent Protocol](https://github.com/visa/trusted-agent-protocol)
40
41
 
41
42
  ## Install
42
43
 
@@ -416,6 +417,51 @@ curl -X POST https://botcha.ai/v1/sessions/tap \
416
417
  | `POST /v1/sessions/tap` | Create TAP session with intent validation |
417
418
  | `GET /v1/sessions/:id/tap` | Get TAP session info |
418
419
 
420
+ ### TAP SDK Methods
421
+
422
+ **TypeScript:**
423
+
424
+ ```typescript
425
+ import { BotchaClient } from '@dupecom/botcha/client';
426
+
427
+ const client = new BotchaClient({ appId: 'app_abc123' });
428
+
429
+ // Register a TAP agent
430
+ const agent = await client.registerTAPAgent({
431
+ name: 'my-agent',
432
+ operator: 'Acme Corp',
433
+ capabilities: [{ action: 'browse', scope: ['products'] }],
434
+ trust_level: 'verified',
435
+ });
436
+
437
+ // Create a TAP session
438
+ const session = await client.createTAPSession({
439
+ agent_id: agent.agent_id,
440
+ user_context: 'user-hash',
441
+ intent: { action: 'browse', resource: 'products', duration: 3600 },
442
+ });
443
+ ```
444
+
445
+ **Python:**
446
+
447
+ ```python
448
+ from botcha import BotchaClient
449
+
450
+ async with BotchaClient(app_id="app_abc123") as client:
451
+ agent = await client.register_tap_agent(
452
+ name="my-agent",
453
+ operator="Acme Corp",
454
+ capabilities=[{"action": "browse", "scope": ["products"]}],
455
+ trust_level="verified",
456
+ )
457
+
458
+ session = await client.create_tap_session(
459
+ agent_id=agent.agent_id,
460
+ user_context="user-hash",
461
+ intent={"action": "browse", "resource": "products", "duration": 3600},
462
+ )
463
+ ```
464
+
419
465
  ### Express Middleware (Verification Modes)
420
466
 
421
467
  ```typescript
@@ -510,7 +556,7 @@ BOTCHA is designed to be auto-discoverable by AI agents through multiple standar
510
556
  All responses include these headers for agent discovery:
511
557
 
512
558
  ```http
513
- X-Botcha-Version: 0.12.0
559
+ X-Botcha-Version: 0.15.0
514
560
  X-Botcha-Enabled: true
515
561
  X-Botcha-Methods: hybrid-challenge,speed-challenge,reasoning-challenge,standard-challenge
516
562
  X-Botcha-Docs: https://botcha.ai/openapi.json
@@ -1,5 +1,5 @@
1
- export type { SpeedProblem, BotchaClientOptions, ChallengeResponse, StandardChallengeResponse, VerifyResponse, TokenResponse, StreamSession, StreamEvent, Problem, VerifyResult, StreamChallengeOptions, CreateAppResponse, VerifyEmailResponse, ResendVerificationResponse, RecoverAccountResponse, RotateSecretResponse, } from './types.js';
2
- import type { BotchaClientOptions, VerifyResponse, CreateAppResponse, VerifyEmailResponse, ResendVerificationResponse, RecoverAccountResponse, RotateSecretResponse } from './types.js';
1
+ export type { SpeedProblem, BotchaClientOptions, ChallengeResponse, StandardChallengeResponse, VerifyResponse, TokenResponse, StreamSession, StreamEvent, Problem, VerifyResult, StreamChallengeOptions, CreateAppResponse, VerifyEmailResponse, ResendVerificationResponse, RecoverAccountResponse, RotateSecretResponse, TAPAction, TAPTrustLevel, TAPSignatureAlgorithm, TAPCapability, TAPIntent, RegisterTAPAgentOptions, TAPAgentResponse, TAPAgentListResponse, CreateTAPSessionOptions, TAPSessionResponse, } from './types.js';
2
+ import type { BotchaClientOptions, VerifyResponse, CreateAppResponse, VerifyEmailResponse, ResendVerificationResponse, RecoverAccountResponse, RotateSecretResponse, RegisterTAPAgentOptions, TAPAgentResponse, TAPAgentListResponse, CreateTAPSessionOptions, TAPSessionResponse } from './types.js';
3
3
  export { BotchaStreamClient } from './stream.js';
4
4
  /**
5
5
  * BOTCHA Client SDK for AI Agents
@@ -154,6 +154,68 @@ export declare class BotchaClient {
154
154
  * ```
155
155
  */
156
156
  rotateSecret(appId?: string): Promise<RotateSecretResponse>;
157
+ /**
158
+ * Register an agent with TAP (Trusted Agent Protocol) capabilities.
159
+ * Enables cryptographic agent authentication with optional public key signing.
160
+ *
161
+ * @param options - Registration options including name, public key, capabilities
162
+ * @returns TAP agent details including agent_id
163
+ * @throws Error if registration fails
164
+ *
165
+ * @example
166
+ * ```typescript
167
+ * const agent = await client.registerTAPAgent({
168
+ * name: 'my-shopping-agent',
169
+ * operator: 'acme-corp',
170
+ * capabilities: [{ action: 'browse', scope: ['products'] }],
171
+ * trust_level: 'verified',
172
+ * });
173
+ * console.log(agent.agent_id);
174
+ * ```
175
+ */
176
+ registerTAPAgent(options: RegisterTAPAgentOptions): Promise<TAPAgentResponse>;
177
+ /**
178
+ * Get a TAP agent by ID.
179
+ *
180
+ * @param agentId - The agent ID to retrieve
181
+ * @returns TAP agent details
182
+ * @throws Error if agent not found
183
+ */
184
+ getTAPAgent(agentId: string): Promise<TAPAgentResponse>;
185
+ /**
186
+ * List TAP agents for the current app.
187
+ *
188
+ * @param tapOnly - If true, only return TAP-enabled agents (default: false)
189
+ * @returns List of TAP agents with counts
190
+ * @throws Error if listing fails
191
+ */
192
+ listTAPAgents(tapOnly?: boolean): Promise<TAPAgentListResponse>;
193
+ /**
194
+ * Create a TAP session after agent verification.
195
+ *
196
+ * @param options - Session options including agent_id, user_context, and intent
197
+ * @returns TAP session details including session_id and expiry
198
+ * @throws Error if session creation fails
199
+ *
200
+ * @example
201
+ * ```typescript
202
+ * const session = await client.createTAPSession({
203
+ * agent_id: 'agent_abc123',
204
+ * user_context: 'user-hash',
205
+ * intent: { action: 'browse', resource: 'products', duration: 3600 },
206
+ * });
207
+ * console.log(session.session_id, session.expires_at);
208
+ * ```
209
+ */
210
+ createTAPSession(options: CreateTAPSessionOptions): Promise<TAPSessionResponse>;
211
+ /**
212
+ * Get a TAP session by ID.
213
+ *
214
+ * @param sessionId - The session ID to retrieve
215
+ * @returns TAP session details including time_remaining
216
+ * @throws Error if session not found or expired
217
+ */
218
+ getTAPSession(sessionId: string): Promise<TAPSessionResponse>;
157
219
  }
158
220
  /**
159
221
  * Convenience function for one-off solves
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/client/index.ts"],"names":[],"mappings":"AAMA,YAAY,EACV,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,yBAAyB,EACzB,cAAc,EACd,aAAa,EACb,aAAa,EACb,WAAW,EACX,OAAO,EACP,YAAY,EACZ,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,EACnB,0BAA0B,EAC1B,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAEV,mBAAmB,EAGnB,cAAc,EAEd,iBAAiB,EACjB,mBAAmB,EACnB,0BAA0B,EAC1B,sBAAsB,EACtB,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,KAAK,CAAC,CAAS;IACvB,OAAO,CAAC,IAAI,CAAsB;IAClC,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,cAAc,CAAuB;gBAEjC,OAAO,GAAE,mBAAwB;IAS7C;;;;;OAKG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE;IAMnC;;;;;;;OAOG;IACG,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC;IA2FjC;;;;;;OAMG;IACG,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAkCrC;;OAEG;IACH,UAAU,IAAI,IAAI;IAMlB;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IA+BlE;;OAEG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC;IAsBpE;;;;;;;;;OASG;IACG,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC;IA2F/D;;;;;;;;OAQG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAoBtD;;;;;;;;;;;;;;;;OAgBG;IACG,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA2B1D;;;;;;;;;;;;;OAaG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAyB7E;;;;;;OAMG;IACG,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAwB7E;;;;;;;;;OASG;IACG,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAoBpE;;;;;;;;;;;;;OAaG;IACG,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;CA+BlE;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAIxD;AAED,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/client/index.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import crypto from 'crypto';
2
2
  // SDK version - hardcoded since npm_package_version is unreliable when used as a library
3
- const SDK_VERSION = '0.11.0';
3
+ const SDK_VERSION = '0.13.1';
4
4
  // Export stream client
5
5
  export { BotchaStreamClient } from './stream.js';
6
6
  /**
@@ -494,6 +494,141 @@ export class BotchaClient {
494
494
  }
495
495
  return await res.json();
496
496
  }
497
+ // ============ TAP (TRUSTED AGENT PROTOCOL) ============
498
+ /**
499
+ * Register an agent with TAP (Trusted Agent Protocol) capabilities.
500
+ * Enables cryptographic agent authentication with optional public key signing.
501
+ *
502
+ * @param options - Registration options including name, public key, capabilities
503
+ * @returns TAP agent details including agent_id
504
+ * @throws Error if registration fails
505
+ *
506
+ * @example
507
+ * ```typescript
508
+ * const agent = await client.registerTAPAgent({
509
+ * name: 'my-shopping-agent',
510
+ * operator: 'acme-corp',
511
+ * capabilities: [{ action: 'browse', scope: ['products'] }],
512
+ * trust_level: 'verified',
513
+ * });
514
+ * console.log(agent.agent_id);
515
+ * ```
516
+ */
517
+ async registerTAPAgent(options) {
518
+ const url = this.appId
519
+ ? `${this.baseUrl}/v1/agents/register/tap?app_id=${encodeURIComponent(this.appId)}`
520
+ : `${this.baseUrl}/v1/agents/register/tap`;
521
+ const headers = {
522
+ 'Content-Type': 'application/json',
523
+ 'User-Agent': this.agentIdentity,
524
+ };
525
+ if (this.cachedToken) {
526
+ headers['Authorization'] = `Bearer ${this.cachedToken}`;
527
+ }
528
+ const res = await fetch(url, {
529
+ method: 'POST',
530
+ headers,
531
+ body: JSON.stringify(options),
532
+ });
533
+ if (!res.ok) {
534
+ const body = await res.json().catch(() => ({}));
535
+ throw new Error(body.message || `TAP agent registration failed with status ${res.status}`);
536
+ }
537
+ return await res.json();
538
+ }
539
+ /**
540
+ * Get a TAP agent by ID.
541
+ *
542
+ * @param agentId - The agent ID to retrieve
543
+ * @returns TAP agent details
544
+ * @throws Error if agent not found
545
+ */
546
+ async getTAPAgent(agentId) {
547
+ const res = await fetch(`${this.baseUrl}/v1/agents/${encodeURIComponent(agentId)}/tap`, {
548
+ headers: { 'User-Agent': this.agentIdentity },
549
+ });
550
+ if (!res.ok) {
551
+ const body = await res.json().catch(() => ({}));
552
+ throw new Error(body.message || `TAP agent retrieval failed with status ${res.status}`);
553
+ }
554
+ return await res.json();
555
+ }
556
+ /**
557
+ * List TAP agents for the current app.
558
+ *
559
+ * @param tapOnly - If true, only return TAP-enabled agents (default: false)
560
+ * @returns List of TAP agents with counts
561
+ * @throws Error if listing fails
562
+ */
563
+ async listTAPAgents(tapOnly = false) {
564
+ let url = this.appId
565
+ ? `${this.baseUrl}/v1/agents/tap?app_id=${encodeURIComponent(this.appId)}`
566
+ : `${this.baseUrl}/v1/agents/tap`;
567
+ if (tapOnly) {
568
+ url += url.includes('?') ? '&tap_only=true' : '?tap_only=true';
569
+ }
570
+ const headers = {
571
+ 'User-Agent': this.agentIdentity,
572
+ };
573
+ if (this.cachedToken) {
574
+ headers['Authorization'] = `Bearer ${this.cachedToken}`;
575
+ }
576
+ const res = await fetch(url, { headers });
577
+ if (!res.ok) {
578
+ const body = await res.json().catch(() => ({}));
579
+ throw new Error(body.message || `TAP agent listing failed with status ${res.status}`);
580
+ }
581
+ return await res.json();
582
+ }
583
+ /**
584
+ * Create a TAP session after agent verification.
585
+ *
586
+ * @param options - Session options including agent_id, user_context, and intent
587
+ * @returns TAP session details including session_id and expiry
588
+ * @throws Error if session creation fails
589
+ *
590
+ * @example
591
+ * ```typescript
592
+ * const session = await client.createTAPSession({
593
+ * agent_id: 'agent_abc123',
594
+ * user_context: 'user-hash',
595
+ * intent: { action: 'browse', resource: 'products', duration: 3600 },
596
+ * });
597
+ * console.log(session.session_id, session.expires_at);
598
+ * ```
599
+ */
600
+ async createTAPSession(options) {
601
+ const res = await fetch(`${this.baseUrl}/v1/sessions/tap`, {
602
+ method: 'POST',
603
+ headers: {
604
+ 'Content-Type': 'application/json',
605
+ 'User-Agent': this.agentIdentity,
606
+ },
607
+ body: JSON.stringify(options),
608
+ });
609
+ if (!res.ok) {
610
+ const body = await res.json().catch(() => ({}));
611
+ throw new Error(body.message || `TAP session creation failed with status ${res.status}`);
612
+ }
613
+ return await res.json();
614
+ }
615
+ /**
616
+ * Get a TAP session by ID.
617
+ *
618
+ * @param sessionId - The session ID to retrieve
619
+ * @returns TAP session details including time_remaining
620
+ * @throws Error if session not found or expired
621
+ */
622
+ async getTAPSession(sessionId) {
623
+ const res = await fetch(`${this.baseUrl}/v1/sessions/${encodeURIComponent(sessionId)}/tap`, {
624
+ headers: { 'User-Agent': this.agentIdentity },
625
+ });
626
+ if (!res.ok) {
627
+ const body = await res.json().catch(() => ({}));
628
+ throw new Error(body.message || `TAP session retrieval failed with status ${res.status}`);
629
+ }
630
+ return await res.json();
631
+ }
497
632
  }
498
633
  /**
499
634
  * Convenience function for one-off solves
@@ -131,4 +131,72 @@ export interface RotateSecretResponse {
131
131
  error?: string;
132
132
  message?: string;
133
133
  }
134
+ export type TAPAction = 'browse' | 'compare' | 'purchase' | 'audit' | 'search';
135
+ export type TAPTrustLevel = 'basic' | 'verified' | 'enterprise';
136
+ export type TAPSignatureAlgorithm = 'ecdsa-p256-sha256' | 'rsa-pss-sha256';
137
+ export interface TAPCapability {
138
+ action: TAPAction;
139
+ scope?: string[];
140
+ restrictions?: {
141
+ max_amount?: number;
142
+ rate_limit?: number;
143
+ [key: string]: any;
144
+ };
145
+ }
146
+ export interface TAPIntent {
147
+ action: TAPAction;
148
+ resource?: string;
149
+ scope?: string[];
150
+ duration?: number;
151
+ }
152
+ export interface RegisterTAPAgentOptions {
153
+ name: string;
154
+ operator?: string;
155
+ version?: string;
156
+ public_key?: string;
157
+ signature_algorithm?: TAPSignatureAlgorithm;
158
+ capabilities?: TAPCapability[];
159
+ trust_level?: TAPTrustLevel;
160
+ issuer?: string;
161
+ }
162
+ export interface TAPAgentResponse {
163
+ success: boolean;
164
+ agent_id: string;
165
+ app_id: string;
166
+ name: string;
167
+ operator?: string;
168
+ version?: string;
169
+ created_at: string;
170
+ tap_enabled: boolean;
171
+ trust_level?: TAPTrustLevel;
172
+ capabilities?: TAPCapability[];
173
+ signature_algorithm?: TAPSignatureAlgorithm;
174
+ issuer?: string;
175
+ has_public_key: boolean;
176
+ key_fingerprint?: string;
177
+ last_verified_at?: string | null;
178
+ public_key?: string;
179
+ }
180
+ export interface TAPAgentListResponse {
181
+ success: boolean;
182
+ agents: TAPAgentResponse[];
183
+ count: number;
184
+ tap_enabled_count: number;
185
+ }
186
+ export interface CreateTAPSessionOptions {
187
+ agent_id: string;
188
+ user_context: string;
189
+ intent: TAPIntent;
190
+ }
191
+ export interface TAPSessionResponse {
192
+ success: boolean;
193
+ session_id: string;
194
+ agent_id: string;
195
+ app_id?: string;
196
+ capabilities?: TAPCapability[];
197
+ intent: TAPIntent;
198
+ created_at?: string;
199
+ expires_at: string;
200
+ time_remaining?: number;
201
+ }
134
202
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../lib/client/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../lib/client/types.ts"],"names":[],"mappings":"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"}
package/dist/lib/index.js CHANGED
@@ -114,3 +114,5 @@ export function solve(problems) {
114
114
  // ============ EXPORTS ============
115
115
  export const botcha = { verify, solve };
116
116
  export default botcha;
117
+ // TAP Enhanced Middleware available via:
118
+ // import { tapEnhancedVerify, createTAPVerifyMiddleware, tapVerifyModes } from '@dupecom/botcha/middleware'
@@ -0,0 +1,19 @@
1
+ export declare function generateChallenge(difficulty?: 'easy' | 'medium' | 'hard'): {
2
+ id: string;
3
+ puzzle: string;
4
+ timeLimit: number;
5
+ hint: string;
6
+ };
7
+ export declare function verifyChallenge(id: string, answer: string): {
8
+ valid: boolean;
9
+ reason?: string;
10
+ timeMs?: number;
11
+ };
12
+ export declare function generatePrimes(count: number): number[];
13
+ export declare function isPrime(n: number): boolean;
14
+ declare const _default: {
15
+ generateChallenge: typeof generateChallenge;
16
+ verifyChallenge: typeof verifyChallenge;
17
+ };
18
+ export default _default;
19
+ //# sourceMappingURL=compute.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compute.d.ts","sourceRoot":"","sources":["../../../src/challenges/compute.ts"],"names":[],"mappings":"AAuBA,wBAAgB,iBAAiB,CAAC,UAAU,GAAE,MAAM,GAAG,QAAQ,GAAG,MAAiB,GAAG;IACpF,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd,CAmCA;AAED,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG;IAC3D,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CA0BA;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAYtD;AAED,wBAAgB,OAAO,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAU1C;;;;;AAED,wBAAsD"}
@@ -0,0 +1,88 @@
1
+ import crypto from 'crypto';
2
+ // In-memory challenge store (use Redis in production)
3
+ const challenges = new Map();
4
+ // Clean up expired challenges periodically
5
+ setInterval(() => {
6
+ const now = Date.now();
7
+ for (const [id, challenge] of challenges) {
8
+ if (challenge.expiresAt < now) {
9
+ challenges.delete(id);
10
+ }
11
+ }
12
+ }, 60000);
13
+ export function generateChallenge(difficulty = 'medium') {
14
+ const id = crypto.randomUUID();
15
+ // Different difficulty levels
16
+ const config = {
17
+ easy: { primes: 100, timeLimit: 10000 },
18
+ medium: { primes: 500, timeLimit: 5000 },
19
+ hard: { primes: 1000, timeLimit: 3000 },
20
+ }[difficulty];
21
+ // Random salt makes each challenge unique — precomputed lookup tables won't work
22
+ const salt = crypto.randomUUID().replace(/-/g, '').substring(0, 16);
23
+ // Generate first N primes, concatenate with salt, hash
24
+ const primes = generatePrimes(config.primes);
25
+ const concatenated = primes.join('') + salt;
26
+ const hash = crypto.createHash('sha256').update(concatenated).digest('hex');
27
+ const answer = hash.substring(0, 16); // First 16 chars
28
+ const challenge = {
29
+ id,
30
+ puzzle: `Compute SHA256 of the first ${config.primes} prime numbers concatenated (no separators) followed by the salt "${salt}". Return the first 16 hex characters.`,
31
+ expectedAnswer: answer,
32
+ expiresAt: Date.now() + config.timeLimit + 1000, // Small grace period
33
+ difficulty,
34
+ };
35
+ challenges.set(id, challenge);
36
+ return {
37
+ id,
38
+ puzzle: challenge.puzzle,
39
+ timeLimit: config.timeLimit,
40
+ hint: `Example: First 5 primes + salt = "235711${salt}" → SHA256 → first 16 chars`,
41
+ };
42
+ }
43
+ export function verifyChallenge(id, answer) {
44
+ const challenge = challenges.get(id);
45
+ if (!challenge) {
46
+ return { valid: false, reason: 'Challenge not found or expired' };
47
+ }
48
+ const now = Date.now();
49
+ if (now > challenge.expiresAt) {
50
+ challenges.delete(id);
51
+ return { valid: false, reason: 'Challenge expired - too slow!' };
52
+ }
53
+ const isValid = answer.toLowerCase() === challenge.expectedAnswer.toLowerCase();
54
+ // Clean up used challenge
55
+ challenges.delete(id);
56
+ if (!isValid) {
57
+ return { valid: false, reason: 'Incorrect answer' };
58
+ }
59
+ return {
60
+ valid: true,
61
+ timeMs: challenge.expiresAt - now - 1000, // Approximate solve time
62
+ };
63
+ }
64
+ export function generatePrimes(count) {
65
+ const primes = [];
66
+ let num = 2;
67
+ while (primes.length < count) {
68
+ if (isPrime(num)) {
69
+ primes.push(num);
70
+ }
71
+ num++;
72
+ }
73
+ return primes;
74
+ }
75
+ export function isPrime(n) {
76
+ if (n < 2)
77
+ return false;
78
+ if (n === 2)
79
+ return true;
80
+ if (n % 2 === 0)
81
+ return false;
82
+ for (let i = 3; i <= Math.sqrt(n); i += 2) {
83
+ if (n % i === 0)
84
+ return false;
85
+ }
86
+ return true;
87
+ }
88
+ export default { generateChallenge, verifyChallenge };
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Generate a hybrid challenge: speed + reasoning combined
3
+ * Must solve SHA256 problems in <500ms AND answer reasoning questions
4
+ */
5
+ export declare function generateHybridChallenge(): {
6
+ id: string;
7
+ speed: {
8
+ problems: {
9
+ num: number;
10
+ operation: string;
11
+ }[];
12
+ timeLimit: number;
13
+ };
14
+ reasoning: {
15
+ questions: {
16
+ id: string;
17
+ question: string;
18
+ category: string;
19
+ }[];
20
+ timeLimit: number;
21
+ };
22
+ instructions: string;
23
+ };
24
+ export declare function verifyHybridChallenge(id: string, speedAnswers: string[], reasoningAnswers: Record<string, string>): {
25
+ valid: boolean;
26
+ reason?: string;
27
+ speed: {
28
+ passed: boolean;
29
+ solveTimeMs?: number;
30
+ reason?: string;
31
+ };
32
+ reasoning: {
33
+ passed: boolean;
34
+ score?: string;
35
+ solveTimeMs?: number;
36
+ reason?: string;
37
+ };
38
+ totalTimeMs?: number;
39
+ };
40
+ declare const _default: {
41
+ generateHybridChallenge: typeof generateHybridChallenge;
42
+ verifyHybridChallenge: typeof verifyHybridChallenge;
43
+ };
44
+ export default _default;
45
+ //# sourceMappingURL=hybrid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hybrid.d.ts","sourceRoot":"","sources":["../../../src/challenges/hybrid.ts"],"names":[],"mappings":"AAsBA;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE;QACL,QAAQ,EAAE;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QAC/C,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,SAAS,EAAE;QACT,SAAS,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QAChE,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,YAAY,EAAE,MAAM,CAAC;CACtB,CA4BA;AAED,wBAAgB,qBAAqB,CACnC,EAAE,EAAE,MAAM,EACV,YAAY,EAAE,MAAM,EAAE,EACtB,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACvC;IACD,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClE,SAAS,EAAE;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CA2DA;;;;;AAED,wBAAkE"}
@@ -0,0 +1,94 @@
1
+ import crypto from 'crypto';
2
+ import { generateSpeedChallenge, verifySpeedChallenge } from './speed.js';
3
+ import { generateReasoningChallenge, verifyReasoningChallenge } from './reasoning.js';
4
+ const hybridChallenges = new Map();
5
+ // Cleanup expired
6
+ setInterval(() => {
7
+ const now = Date.now();
8
+ for (const [id, c] of hybridChallenges) {
9
+ if (c.expiresAt < now)
10
+ hybridChallenges.delete(id);
11
+ }
12
+ }, 60000);
13
+ /**
14
+ * Generate a hybrid challenge: speed + reasoning combined
15
+ * Must solve SHA256 problems in <500ms AND answer reasoning questions
16
+ */
17
+ export function generateHybridChallenge() {
18
+ const id = crypto.randomUUID();
19
+ // Generate both sub-challenges
20
+ const speedChallenge = generateSpeedChallenge();
21
+ const reasoningChallenge = generateReasoningChallenge();
22
+ // Store the mapping
23
+ hybridChallenges.set(id, {
24
+ id,
25
+ speedChallengeId: speedChallenge.id,
26
+ reasoningChallengeId: reasoningChallenge.id,
27
+ issuedAt: Date.now(),
28
+ expiresAt: Date.now() + 35000, // 35 seconds total (500ms for speed + 30s for reasoning + buffer)
29
+ });
30
+ return {
31
+ id,
32
+ speed: {
33
+ problems: speedChallenge.challenges,
34
+ timeLimit: speedChallenge.timeLimit,
35
+ },
36
+ reasoning: {
37
+ questions: reasoningChallenge.questions,
38
+ timeLimit: reasoningChallenge.timeLimit,
39
+ },
40
+ instructions: 'Solve ALL speed problems (SHA256) in <500ms AND answer ALL reasoning questions. Submit both together.',
41
+ };
42
+ }
43
+ export function verifyHybridChallenge(id, speedAnswers, reasoningAnswers) {
44
+ const hybrid = hybridChallenges.get(id);
45
+ if (!hybrid) {
46
+ return {
47
+ valid: false,
48
+ reason: 'Hybrid challenge not found or expired',
49
+ speed: { passed: false, reason: 'Challenge not found' },
50
+ reasoning: { passed: false, reason: 'Challenge not found' },
51
+ };
52
+ }
53
+ const now = Date.now();
54
+ const totalTimeMs = now - hybrid.issuedAt;
55
+ // Don't delete yet - we need to verify both parts
56
+ if (now > hybrid.expiresAt) {
57
+ hybridChallenges.delete(id);
58
+ return {
59
+ valid: false,
60
+ reason: 'Hybrid challenge expired',
61
+ speed: { passed: false, reason: 'Expired' },
62
+ reasoning: { passed: false, reason: 'Expired' },
63
+ totalTimeMs,
64
+ };
65
+ }
66
+ // Verify speed challenge
67
+ const speedResult = verifySpeedChallenge(hybrid.speedChallengeId, speedAnswers);
68
+ // Verify reasoning challenge
69
+ const reasoningResult = verifyReasoningChallenge(hybrid.reasoningChallengeId, reasoningAnswers);
70
+ // Clean up
71
+ hybridChallenges.delete(id);
72
+ const speedPassed = speedResult.valid;
73
+ const reasoningPassed = reasoningResult.valid;
74
+ const bothPassed = speedPassed && reasoningPassed;
75
+ return {
76
+ valid: bothPassed,
77
+ reason: bothPassed
78
+ ? undefined
79
+ : `Failed: ${!speedPassed ? 'speed' : ''}${!speedPassed && !reasoningPassed ? ' + ' : ''}${!reasoningPassed ? 'reasoning' : ''}`,
80
+ speed: {
81
+ passed: speedPassed,
82
+ solveTimeMs: speedResult.solveTimeMs,
83
+ reason: speedResult.reason,
84
+ },
85
+ reasoning: {
86
+ passed: reasoningPassed,
87
+ score: reasoningResult.valid ? `${reasoningResult.correctCount}/${reasoningResult.totalCount}` : undefined,
88
+ solveTimeMs: reasoningResult.solveTimeMs,
89
+ reason: reasoningResult.reason,
90
+ },
91
+ totalTimeMs,
92
+ };
93
+ }
94
+ export default { generateHybridChallenge, verifyHybridChallenge };