@dupecom/botcha-cloudflare 0.3.2 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/auth.js CHANGED
@@ -1,44 +1,286 @@
1
1
  /**
2
2
  * BOTCHA Authentication & JWT Token Management
3
3
  *
4
- * Token-based auth flow for production API access
4
+ * Token-based auth flow with security features:
5
+ * - JTI (JWT ID) for revocation
6
+ * - Audience claims for API scoping
7
+ * - Client IP binding for additional security
8
+ * - Short-lived access tokens (5 min) with refresh tokens (1 hour)
9
+ * - Token revocation via KV storage
5
10
  */
6
11
  import { SignJWT, jwtVerify } from 'jose';
7
12
  /**
8
- * Generate a JWT token after successful challenge verification
13
+ * Generate JWT tokens (access + refresh) after successful challenge verification
14
+ *
15
+ * Access token: 5 minutes, used for API access
16
+ * Refresh token: 1 hour, used to get new access tokens
9
17
  */
10
- export async function generateToken(challengeId, solveTimeMs, secret) {
18
+ export async function generateToken(challengeId, solveTimeMs, secret, env, options) {
11
19
  const encoder = new TextEncoder();
12
20
  const secretKey = encoder.encode(secret);
13
- const token = await new SignJWT({
21
+ // Generate unique JTIs for both tokens
22
+ const accessJti = crypto.randomUUID();
23
+ const refreshJti = crypto.randomUUID();
24
+ // Access token: 5 minutes
25
+ const accessTokenPayload = {
14
26
  type: 'botcha-verified',
15
27
  solveTime: solveTimeMs,
16
- })
28
+ jti: accessJti,
29
+ };
30
+ // Add optional claims
31
+ if (options?.aud) {
32
+ accessTokenPayload.aud = options.aud;
33
+ }
34
+ if (options?.clientIp) {
35
+ accessTokenPayload.client_ip = options.clientIp;
36
+ }
37
+ if (options?.app_id) {
38
+ accessTokenPayload.app_id = options.app_id;
39
+ }
40
+ const accessToken = await new SignJWT(accessTokenPayload)
41
+ .setProtectedHeader({ alg: 'HS256' })
42
+ .setSubject(challengeId)
43
+ .setIssuedAt()
44
+ .setExpirationTime('5m') // 5 minutes
45
+ .sign(secretKey);
46
+ // Refresh token: 1 hour
47
+ const refreshTokenPayload = {
48
+ type: 'botcha-refresh',
49
+ solveTime: solveTimeMs,
50
+ jti: refreshJti,
51
+ };
52
+ // Include app_id in refresh token if provided
53
+ if (options?.app_id) {
54
+ refreshTokenPayload.app_id = options.app_id;
55
+ }
56
+ const refreshToken = await new SignJWT(refreshTokenPayload)
17
57
  .setProtectedHeader({ alg: 'HS256' })
18
58
  .setSubject(challengeId)
19
59
  .setIssuedAt()
20
- .setExpirationTime('1h') // 1 hour expiry
60
+ .setExpirationTime('1h') // 1 hour
21
61
  .sign(secretKey);
22
- return token;
62
+ // Store refresh token JTI in KV if env provided (for revocation tracking)
63
+ // Also store aud, client_ip, and app_id so they carry over on refresh
64
+ if (env?.CHALLENGES) {
65
+ try {
66
+ const refreshData = { sub: challengeId, iat: Date.now() };
67
+ if (options?.aud) {
68
+ refreshData.aud = options.aud;
69
+ }
70
+ if (options?.clientIp) {
71
+ refreshData.client_ip = options.clientIp;
72
+ }
73
+ if (options?.app_id) {
74
+ refreshData.app_id = options.app_id;
75
+ }
76
+ await env.CHALLENGES.put(`refresh:${refreshJti}`, JSON.stringify(refreshData), { expirationTtl: 3600 } // 1 hour TTL
77
+ );
78
+ }
79
+ catch (error) {
80
+ // Fail-open: continue even if KV storage fails
81
+ console.error('Failed to store refresh token in KV:', error);
82
+ }
83
+ }
84
+ return {
85
+ access_token: accessToken,
86
+ expires_in: 300, // 5 minutes in seconds
87
+ refresh_token: refreshToken,
88
+ refresh_expires_in: 3600, // 1 hour in seconds
89
+ };
90
+ }
91
+ /**
92
+ * Revoke a token by its JTI
93
+ *
94
+ * Stores the JTI in the revocation list (KV) with 1 hour TTL
95
+ */
96
+ export async function revokeToken(jti, env) {
97
+ try {
98
+ await env.CHALLENGES.put(`revoked:${jti}`, JSON.stringify({ revokedAt: Date.now() }), { expirationTtl: 3600 } // 1 hour TTL (matches max token lifetime)
99
+ );
100
+ }
101
+ catch (error) {
102
+ throw new Error(`Failed to revoke token: ${error instanceof Error ? error.message : 'Unknown error'}`);
103
+ }
23
104
  }
24
105
  /**
25
- * Verify a JWT token
106
+ * Refresh an access token using a valid refresh token
107
+ *
108
+ * Verifies the refresh token, checks revocation, and issues a new access token
109
+ */
110
+ export async function refreshAccessToken(refreshToken, env, secret, options) {
111
+ try {
112
+ const encoder = new TextEncoder();
113
+ const secretKey = encoder.encode(secret);
114
+ // Verify refresh token
115
+ const { payload } = await jwtVerify(refreshToken, secretKey, {
116
+ algorithms: ['HS256'],
117
+ });
118
+ // Check token type
119
+ if (payload.type !== 'botcha-refresh') {
120
+ return {
121
+ success: false,
122
+ error: 'Invalid token type. Expected refresh token.',
123
+ };
124
+ }
125
+ const jti = payload.jti;
126
+ // Check if token is revoked
127
+ if (jti) {
128
+ try {
129
+ const revoked = await env.CHALLENGES.get(`revoked:${jti}`);
130
+ if (revoked) {
131
+ return {
132
+ success: false,
133
+ error: 'Refresh token has been revoked',
134
+ };
135
+ }
136
+ }
137
+ catch (error) {
138
+ // Fail-open: if KV check fails, allow token to proceed
139
+ console.error('Failed to check revocation status:', error);
140
+ }
141
+ }
142
+ // Check if refresh token exists in KV and retrieve stored claims (aud, client_ip, app_id)
143
+ let storedAud;
144
+ let storedClientIp;
145
+ let storedAppId;
146
+ if (jti) {
147
+ try {
148
+ const storedToken = await env.CHALLENGES.get(`refresh:${jti}`);
149
+ if (!storedToken) {
150
+ return {
151
+ success: false,
152
+ error: 'Refresh token not found or expired',
153
+ };
154
+ }
155
+ // Extract stored claims to carry over to new access token
156
+ try {
157
+ const storedData = JSON.parse(storedToken);
158
+ storedAud = storedData.aud;
159
+ storedClientIp = storedData.client_ip;
160
+ storedAppId = storedData.app_id;
161
+ }
162
+ catch {
163
+ // Ignore parse errors on legacy KV entries
164
+ }
165
+ }
166
+ catch (error) {
167
+ // Fail-open: if KV check fails, allow token to proceed
168
+ console.error('Failed to verify refresh token in KV:', error);
169
+ }
170
+ }
171
+ // Generate new access token
172
+ const newAccessJti = crypto.randomUUID();
173
+ const accessTokenPayload = {
174
+ type: 'botcha-verified',
175
+ solveTime: payload.solveTime,
176
+ jti: newAccessJti,
177
+ };
178
+ // Carry over claims: prefer explicit options, fall back to stored KV values
179
+ const effectiveAud = options?.aud || storedAud;
180
+ const effectiveClientIp = options?.clientIp || storedClientIp;
181
+ const effectiveAppId = options?.app_id || storedAppId || payload.app_id;
182
+ if (effectiveAud) {
183
+ accessTokenPayload.aud = effectiveAud;
184
+ }
185
+ if (effectiveClientIp) {
186
+ accessTokenPayload.client_ip = effectiveClientIp;
187
+ }
188
+ if (effectiveAppId) {
189
+ accessTokenPayload.app_id = effectiveAppId;
190
+ }
191
+ const accessToken = await new SignJWT(accessTokenPayload)
192
+ .setProtectedHeader({ alg: 'HS256' })
193
+ .setSubject(payload.sub || '')
194
+ .setIssuedAt()
195
+ .setExpirationTime('5m') // 5 minutes
196
+ .sign(secretKey);
197
+ return {
198
+ success: true,
199
+ tokens: {
200
+ access_token: accessToken,
201
+ expires_in: 300, // 5 minutes in seconds
202
+ },
203
+ };
204
+ }
205
+ catch (error) {
206
+ return {
207
+ success: false,
208
+ error: error instanceof Error ? error.message : 'Invalid refresh token',
209
+ };
210
+ }
211
+ }
212
+ /**
213
+ * Verify a JWT token with security checks
214
+ *
215
+ * Checks:
216
+ * - Token signature and expiry
217
+ * - Revocation status (via JTI)
218
+ * - Audience claim (if provided)
219
+ * - Client IP binding (if provided)
26
220
  */
27
- export async function verifyToken(token, secret) {
221
+ export async function verifyToken(token, secret, env, options) {
28
222
  try {
29
223
  const encoder = new TextEncoder();
30
224
  const secretKey = encoder.encode(secret);
31
225
  const { payload } = await jwtVerify(token, secretKey, {
32
226
  algorithms: ['HS256'],
33
227
  });
228
+ // Check token type (must be access token, not refresh token)
229
+ if (payload.type !== 'botcha-verified') {
230
+ return {
231
+ valid: false,
232
+ error: 'Invalid token type',
233
+ };
234
+ }
235
+ const jti = payload.jti;
236
+ // Check revocation status (fail-open if KV unavailable)
237
+ if (jti && env?.CHALLENGES) {
238
+ try {
239
+ const revoked = await env.CHALLENGES.get(`revoked:${jti}`);
240
+ if (revoked) {
241
+ return {
242
+ valid: false,
243
+ error: 'Token has been revoked',
244
+ };
245
+ }
246
+ }
247
+ catch (error) {
248
+ // Fail-open: if KV check fails, allow token to proceed
249
+ console.error('Failed to check revocation status:', error);
250
+ }
251
+ }
252
+ // Validate audience claim (if required)
253
+ if (options?.requiredAud) {
254
+ const tokenAud = payload.aud;
255
+ if (!tokenAud || tokenAud !== options.requiredAud) {
256
+ return {
257
+ valid: false,
258
+ error: 'Invalid audience claim',
259
+ };
260
+ }
261
+ }
262
+ // Validate client IP binding (if required)
263
+ if (options?.clientIp) {
264
+ const tokenIp = payload.client_ip;
265
+ if (!tokenIp || tokenIp !== options.clientIp) {
266
+ return {
267
+ valid: false,
268
+ error: 'Client IP mismatch',
269
+ };
270
+ }
271
+ }
34
272
  return {
35
273
  valid: true,
36
274
  payload: {
37
275
  sub: payload.sub || '',
38
276
  iat: payload.iat || 0,
39
277
  exp: payload.exp || 0,
278
+ jti: jti || '',
40
279
  type: payload.type,
41
280
  solveTime: payload.solveTime,
281
+ aud: payload.aud,
282
+ client_ip: payload.client_ip,
283
+ app_id: payload.app_id,
42
284
  },
43
285
  };
44
286
  }
@@ -20,6 +20,10 @@ export interface SpeedChallenge {
20
20
  expectedAnswers: string[];
21
21
  issuedAt: number;
22
22
  expiresAt: number;
23
+ baseTimeLimit: number;
24
+ adjustedTimeLimit: number;
25
+ rttMs?: number;
26
+ app_id?: string;
23
27
  }
24
28
  export interface StandardChallenge {
25
29
  id: string;
@@ -27,6 +31,7 @@ export interface StandardChallenge {
27
31
  expectedAnswer: string;
28
32
  expiresAt: number;
29
33
  difficulty: 'easy' | 'medium' | 'hard';
34
+ app_id?: string;
30
35
  }
31
36
  export interface ReasoningQuestion {
32
37
  id: string;
@@ -44,6 +49,7 @@ export interface ReasoningChallenge {
44
49
  expectedAnswers: Record<string, string[]>;
45
50
  issuedAt: number;
46
51
  expiresAt: number;
52
+ app_id?: string;
47
53
  }
48
54
  export interface ChallengeResult {
49
55
  valid: boolean;
@@ -51,6 +57,7 @@ export interface ChallengeResult {
51
57
  solveTimeMs?: number;
52
58
  correctCount?: number;
53
59
  totalCount?: number;
60
+ app_id?: string;
54
61
  }
55
62
  export interface HybridChallenge {
56
63
  id: string;
@@ -58,12 +65,13 @@ export interface HybridChallenge {
58
65
  reasoningChallengeId: string;
59
66
  issuedAt: number;
60
67
  expiresAt: number;
68
+ app_id?: string;
61
69
  }
62
70
  /**
63
- * Generate a speed challenge: 5 SHA256 problems, 500ms to solve ALL
71
+ * Generate a speed challenge: 5 SHA256 problems, RTT-aware timeout
64
72
  * Trivial for AI, impossible for humans to copy-paste fast enough
65
73
  */
66
- export declare function generateSpeedChallenge(kv?: KVNamespace): Promise<{
74
+ export declare function generateSpeedChallenge(kv?: KVNamespace, clientTimestamp?: number, app_id?: string): Promise<{
67
75
  id: string;
68
76
  problems: {
69
77
  num: number;
@@ -71,15 +79,26 @@ export declare function generateSpeedChallenge(kv?: KVNamespace): Promise<{
71
79
  }[];
72
80
  timeLimit: number;
73
81
  instructions: string;
82
+ rttInfo?: {
83
+ measuredRtt: number;
84
+ adjustedTimeout: number;
85
+ explanation: string;
86
+ };
74
87
  }>;
75
88
  /**
76
- * Verify a speed challenge response
89
+ * Verify a speed challenge response with RTT-aware timeout
77
90
  */
78
- export declare function verifySpeedChallenge(id: string, answers: string[], kv?: KVNamespace): Promise<ChallengeResult>;
91
+ export declare function verifySpeedChallenge(id: string, answers: string[], kv?: KVNamespace): Promise<ChallengeResult & {
92
+ rttInfo?: {
93
+ measuredRtt: number;
94
+ adjustedTimeout: number;
95
+ actualTime: number;
96
+ };
97
+ }>;
79
98
  /**
80
99
  * Generate a standard challenge: compute SHA256 of concatenated primes
81
100
  */
82
- export declare function generateStandardChallenge(difficulty?: 'easy' | 'medium' | 'hard', kv?: KVNamespace): Promise<{
101
+ export declare function generateStandardChallenge(difficulty?: 'easy' | 'medium' | 'hard', kv?: KVNamespace, app_id?: string): Promise<{
83
102
  id: string;
84
103
  puzzle: string;
85
104
  timeLimit: number;
@@ -111,7 +130,7 @@ export declare function solveSpeedChallenge(problems: number[]): Promise<string[
111
130
  /**
112
131
  * Generate a reasoning challenge: 3 random questions requiring LLM capabilities
113
132
  */
114
- export declare function generateReasoningChallenge(kv?: KVNamespace): Promise<{
133
+ export declare function generateReasoningChallenge(kv?: KVNamespace, app_id?: string): Promise<{
115
134
  id: string;
116
135
  questions: {
117
136
  id: string;
@@ -128,7 +147,7 @@ export declare function verifyReasoningChallenge(id: string, answers: Record<str
128
147
  /**
129
148
  * Generate a hybrid challenge: speed + reasoning combined
130
149
  */
131
- export declare function generateHybridChallenge(kv?: KVNamespace): Promise<{
150
+ export declare function generateHybridChallenge(kv?: KVNamespace, clientTimestamp?: number, app_id?: string): Promise<{
132
151
  id: string;
133
152
  speed: {
134
153
  problems: {
@@ -146,6 +165,11 @@ export declare function generateHybridChallenge(kv?: KVNamespace): Promise<{
146
165
  timeLimit: number;
147
166
  };
148
167
  instructions: string;
168
+ rttInfo?: {
169
+ measuredRtt: number;
170
+ adjustedTimeout: number;
171
+ explanation: string;
172
+ };
149
173
  }>;
150
174
  /**
151
175
  * Verify a hybrid challenge response
@@ -1 +1 @@
1
- {"version":3,"file":"challenges.d.ts","sourceRoot":"","sources":["../src/challenges.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,MAAM,WAAW,GAAG;IACxB,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa,GAAG,QAAQ,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IACtF,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzF,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC,CAAC;AAGF,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC/C,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;CACxC;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,SAAS,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,cAAc,CAAC;IAC9E,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAChE,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,gBAAgB,EAAE,MAAM,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AA4ED;;;GAGG;AACH,wBAAsB,sBAAsB,CAAC,EAAE,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;IACtE,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CA+BD;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EAAE,EACjB,EAAE,CAAC,EAAE,WAAW,GACf,OAAO,CAAC,eAAe,CAAC,CA4B1B;AASD;;GAEG;AACH,wBAAsB,yBAAyB,CAC7C,UAAU,GAAE,MAAM,GAAG,QAAQ,GAAG,MAAiB,EACjD,EAAE,CAAC,EAAE,WAAW,GACf,OAAO,CAAC;IACT,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CA4BD;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,EACd,EAAE,CAAC,EAAE,WAAW,GACf,OAAO,CAAC,eAAe,CAAC,CAyB1B;AAKD;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,EAAE,CAAC,EAAE,WAAW,GACf,OAAO,CAAC;IACT,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC,CAuCD;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAa5F;AAGD;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAE/E;AA8ID;;GAEG;AACH,wBAAsB,0BAA0B,CAAC,EAAE,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;IAC1E,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CAwDD;AA6BD;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,EAAE,CAAC,EAAE,WAAW,GACf,OAAO,CAAC,eAAe,CAAC,CAqE1B;AAKD;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,EAAE,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;IACvE,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,CAAC,CAoCD;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,EAAE,EAAE,MAAM,EACV,YAAY,EAAE,MAAM,EAAE,EACtB,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACxC,EAAE,CAAC,EAAE,WAAW,GACf,OAAO,CAAC;IACT,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,CAAC,CAyED"}
1
+ {"version":3,"file":"challenges.d.ts","sourceRoot":"","sources":["../src/challenges.ts"],"names":[],"mappings":"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"}