@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/analytics.d.ts +60 -0
- package/dist/analytics.d.ts.map +1 -0
- package/dist/analytics.js +130 -0
- package/dist/apps.d.ts +93 -0
- package/dist/apps.d.ts.map +1 -0
- package/dist/apps.js +152 -0
- package/dist/auth.d.ts +93 -6
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +251 -9
- package/dist/challenges.d.ts +31 -7
- package/dist/challenges.d.ts.map +1 -1
- package/dist/challenges.js +550 -144
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +480 -49
- package/dist/rate-limit.d.ts +11 -1
- package/dist/rate-limit.d.ts.map +1 -1
- package/dist/rate-limit.js +13 -2
- package/dist/static.d.ts +517 -0
- package/dist/static.d.ts.map +1 -0
- package/dist/static.js +635 -0
- package/package.json +1 -1
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
|
|
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
|
|
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
|
-
|
|
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
|
|
60
|
+
.setExpirationTime('1h') // 1 hour
|
|
21
61
|
.sign(secretKey);
|
|
22
|
-
|
|
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
|
-
*
|
|
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
|
}
|
package/dist/challenges.d.ts
CHANGED
|
@@ -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,
|
|
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
|
package/dist/challenges.d.ts.map
CHANGED
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"challenges.d.ts","sourceRoot":"","sources":["../src/challenges.ts"],"names":[],"mappings":"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"}
|