@dupecom/botcha-cloudflare 0.9.0 → 0.10.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/apps.d.ts CHANGED
@@ -6,6 +6,9 @@
6
6
  * - SHA-256 secret hashing (never store plaintext)
7
7
  * - KV storage for app configs
8
8
  * - Rate limit tracking per app
9
+ * - Email verification for account recovery
10
+ * - Email→app_id reverse index for recovery lookups
11
+ * - Secret rotation with email notification
9
12
  */
10
13
  export type KVNamespace = {
11
14
  get: (key: string, type?: 'text' | 'json' | 'arrayBuffer' | 'stream') => Promise<any>;
@@ -22,6 +25,10 @@ export interface AppConfig {
22
25
  secret_hash: string;
23
26
  created_at: number;
24
27
  rate_limit: number;
28
+ email: string;
29
+ email_verified: boolean;
30
+ email_verification_code?: string;
31
+ email_verification_expires?: number;
25
32
  }
26
33
  /**
27
34
  * Result of app creation (includes plaintext secret - only shown once!)
@@ -29,7 +36,20 @@ export interface AppConfig {
29
36
  export interface CreateAppResult {
30
37
  app_id: string;
31
38
  app_secret: string;
39
+ email: string;
40
+ email_verified: boolean;
41
+ verification_required: boolean;
32
42
  }
43
+ /**
44
+ * Public app info returned by getApp (excludes secrets and internal fields)
45
+ */
46
+ export type PublicAppConfig = {
47
+ app_id: string;
48
+ created_at: number;
49
+ rate_limit: number;
50
+ email: string;
51
+ email_verified: boolean;
52
+ };
33
53
  /**
34
54
  * Generate a crypto-random app ID
35
55
  * Format: 'app_' + 16 hex chars
@@ -52,6 +72,10 @@ export declare function generateAppSecret(): string;
52
72
  * @returns SHA-256 hash as hex string
53
73
  */
54
74
  export declare function hashSecret(secret: string): Promise<string>;
75
+ /**
76
+ * Generate a 6-digit numeric verification code
77
+ */
78
+ export declare function generateVerificationCode(): string;
55
79
  /**
56
80
  * Create a new app with crypto-random credentials
57
81
  *
@@ -60,15 +84,52 @@ export declare function hashSecret(secret: string): Promise<string>;
60
84
  * - app_secret: 'sk_' + 32 hex chars
61
85
  *
62
86
  * Stores in KV at key `app:{app_id}` with:
63
- * - app_id
64
- * - secret_hash (SHA-256, never plaintext)
65
- * - created_at (timestamp)
66
- * - rate_limit (default: 100 req/hour)
87
+ * - app_id, secret_hash (SHA-256), created_at, rate_limit, email, email_verified
88
+ *
89
+ * Also stores email→app_id reverse index at `email:{email}` for recovery lookups.
67
90
  *
68
91
  * @param kv - KV namespace for storage
69
- * @returns {app_id, app_secret} - SECRET ONLY RETURNED ONCE!
92
+ * @param email - Required owner email address
93
+ * @returns {app_id, app_secret, email, email_verified, verification_required}
94
+ */
95
+ export declare function createApp(kv: KVNamespace, email: string): Promise<CreateAppResult>;
96
+ /**
97
+ * Get the plaintext verification code for an app (internal use only — for sending via email).
98
+ *
99
+ * This is a separate step because createApp returns the code hash, not the plaintext.
100
+ * Instead, we generate and return code in createApp flow; this function regenerates
101
+ * a new code for resend scenarios.
70
102
  */
71
- export declare function createApp(kv: KVNamespace): Promise<CreateAppResult>;
103
+ export declare function regenerateVerificationCode(kv: KVNamespace, app_id: string): Promise<{
104
+ code: string;
105
+ } | null>;
106
+ /**
107
+ * Verify email with the 6-digit code
108
+ *
109
+ * @returns { verified: true } on success, { verified: false, reason } on failure
110
+ */
111
+ export declare function verifyEmailCode(kv: KVNamespace, app_id: string, code: string): Promise<{
112
+ verified: boolean;
113
+ reason?: string;
114
+ }>;
115
+ /**
116
+ * Look up app_id by email (for account recovery)
117
+ *
118
+ * Uses the email→app_id reverse index stored in KV.
119
+ * Only works for apps with verified emails.
120
+ */
121
+ export declare function getAppByEmail(kv: KVNamespace, email: string): Promise<{
122
+ app_id: string;
123
+ email_verified: boolean;
124
+ } | null>;
125
+ /**
126
+ * Rotate app secret — generates a new secret and invalidates the old one.
127
+ *
128
+ * @returns New app_secret (plaintext, only returned once) or null on failure
129
+ */
130
+ export declare function rotateAppSecret(kv: KVNamespace, app_id: string): Promise<{
131
+ app_secret: string;
132
+ } | null>;
72
133
  /**
73
134
  * Get app configuration by app_id
74
135
  *
@@ -78,7 +139,12 @@ export declare function createApp(kv: KVNamespace): Promise<CreateAppResult>;
78
139
  * @param app_id - The app ID to retrieve
79
140
  * @returns App config (without secret_hash) or null if not found
80
141
  */
81
- export declare function getApp(kv: KVNamespace, app_id: string): Promise<Omit<AppConfig, 'secret_hash'> | null>;
142
+ export declare function getApp(kv: KVNamespace, app_id: string): Promise<PublicAppConfig | null>;
143
+ /**
144
+ * Get raw app config (internal use only — includes secret_hash)
145
+ * Used by validateAppSecret and dashboard auth.
146
+ */
147
+ export declare function getAppRaw(kv: KVNamespace, app_id: string): Promise<AppConfig | null>;
82
148
  /**
83
149
  * Validate an app secret against stored hash
84
150
  *
@@ -1 +1 @@
1
- {"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../src/apps.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,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;AAIF;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAID;;;;;GAKG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAOtC;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAO1C;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOhE;AAID;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,SAAS,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,eAAe,CAAC,CAoBzE;AAED;;;;;;;;GAQG;AACH,wBAAsB,MAAM,CAC1B,EAAE,EAAE,WAAW,EACf,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,GAAG,IAAI,CAAC,CAoBhD;AAED;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,WAAW,EACf,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC,CA6BlB"}
1
+ {"version":3,"file":"apps.d.ts","sourceRoot":"","sources":["../src/apps.ts"],"names":[],"mappings":"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"}
package/dist/apps.js CHANGED
@@ -6,6 +6,9 @@
6
6
  * - SHA-256 secret hashing (never store plaintext)
7
7
  * - KV storage for app configs
8
8
  * - Rate limit tracking per app
9
+ * - Email verification for account recovery
10
+ * - Email→app_id reverse index for recovery lookups
11
+ * - Secret rotation with email notification
9
12
  */
10
13
  // ============ CRYPTO UTILITIES ============
11
14
  /**
@@ -51,6 +54,16 @@ export async function hashSecret(secret) {
51
54
  const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
52
55
  return hashHex;
53
56
  }
57
+ /**
58
+ * Generate a 6-digit numeric verification code
59
+ */
60
+ export function generateVerificationCode() {
61
+ const bytes = new Uint8Array(4);
62
+ crypto.getRandomValues(bytes);
63
+ // Convert to number and mod 1,000,000 to get 6 digits
64
+ const num = ((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]) >>> 0;
65
+ return (num % 1000000).toString().padStart(6, '0');
66
+ }
54
67
  // ============ APP MANAGEMENT ============
55
68
  /**
56
69
  * Create a new app with crypto-random credentials
@@ -60,32 +73,156 @@ export async function hashSecret(secret) {
60
73
  * - app_secret: 'sk_' + 32 hex chars
61
74
  *
62
75
  * Stores in KV at key `app:{app_id}` with:
63
- * - app_id
64
- * - secret_hash (SHA-256, never plaintext)
65
- * - created_at (timestamp)
66
- * - rate_limit (default: 100 req/hour)
76
+ * - app_id, secret_hash (SHA-256), created_at, rate_limit, email, email_verified
77
+ *
78
+ * Also stores email→app_id reverse index at `email:{email}` for recovery lookups.
67
79
  *
68
80
  * @param kv - KV namespace for storage
69
- * @returns {app_id, app_secret} - SECRET ONLY RETURNED ONCE!
81
+ * @param email - Required owner email address
82
+ * @returns {app_id, app_secret, email, email_verified, verification_required}
70
83
  */
71
- export async function createApp(kv) {
84
+ export async function createApp(kv, email) {
72
85
  const app_id = generateAppId();
73
86
  const app_secret = generateAppSecret();
74
87
  const secret_hash = await hashSecret(app_secret);
88
+ // Generate email verification code
89
+ const verificationCode = generateVerificationCode();
90
+ const verificationCodeHash = await hashSecret(verificationCode);
75
91
  const config = {
76
92
  app_id,
77
93
  secret_hash,
78
94
  created_at: Date.now(),
79
95
  rate_limit: 100, // Default: 100 requests/hour
96
+ email,
97
+ email_verified: false,
98
+ email_verification_code: verificationCodeHash,
99
+ email_verification_expires: Date.now() + 10 * 60 * 1000, // 10 minutes
80
100
  };
81
- // Store in KV with key format: app:{app_id}
82
- // No TTL - apps persist indefinitely unless explicitly deleted
83
- await kv.put(`app:${app_id}`, JSON.stringify(config));
101
+ // Store app config and email→app_id index in parallel
102
+ await Promise.all([
103
+ kv.put(`app:${app_id}`, JSON.stringify(config)),
104
+ kv.put(`email:${email.toLowerCase()}`, app_id),
105
+ ]);
84
106
  return {
85
107
  app_id,
86
108
  app_secret, // ONLY returned at creation time!
109
+ email,
110
+ email_verified: false,
111
+ verification_required: true,
87
112
  };
88
113
  }
114
+ /**
115
+ * Get the plaintext verification code for an app (internal use only — for sending via email).
116
+ *
117
+ * This is a separate step because createApp returns the code hash, not the plaintext.
118
+ * Instead, we generate and return code in createApp flow; this function regenerates
119
+ * a new code for resend scenarios.
120
+ */
121
+ export async function regenerateVerificationCode(kv, app_id) {
122
+ try {
123
+ const data = await kv.get(`app:${app_id}`, 'text');
124
+ if (!data)
125
+ return null;
126
+ const config = JSON.parse(data);
127
+ if (config.email_verified)
128
+ return null; // Already verified
129
+ const code = generateVerificationCode();
130
+ const codeHash = await hashSecret(code);
131
+ config.email_verification_code = codeHash;
132
+ config.email_verification_expires = Date.now() + 10 * 60 * 1000;
133
+ await kv.put(`app:${app_id}`, JSON.stringify(config));
134
+ return { code };
135
+ }
136
+ catch (error) {
137
+ console.error(`Failed to regenerate verification code for ${app_id}:`, error);
138
+ return null;
139
+ }
140
+ }
141
+ /**
142
+ * Verify email with the 6-digit code
143
+ *
144
+ * @returns { verified: true } on success, { verified: false, reason } on failure
145
+ */
146
+ export async function verifyEmailCode(kv, app_id, code) {
147
+ try {
148
+ const data = await kv.get(`app:${app_id}`, 'text');
149
+ if (!data) {
150
+ return { verified: false, reason: 'App not found' };
151
+ }
152
+ const config = JSON.parse(data);
153
+ if (config.email_verified) {
154
+ return { verified: false, reason: 'Email already verified' };
155
+ }
156
+ if (!config.email_verification_code || !config.email_verification_expires) {
157
+ return { verified: false, reason: 'No verification pending' };
158
+ }
159
+ if (Date.now() > config.email_verification_expires) {
160
+ return { verified: false, reason: 'Verification code expired' };
161
+ }
162
+ // Compare hashed codes
163
+ const providedHash = await hashSecret(code);
164
+ if (providedHash !== config.email_verification_code) {
165
+ return { verified: false, reason: 'Invalid verification code' };
166
+ }
167
+ // Mark email as verified, clear verification fields
168
+ config.email_verified = true;
169
+ delete config.email_verification_code;
170
+ delete config.email_verification_expires;
171
+ await kv.put(`app:${app_id}`, JSON.stringify(config));
172
+ return { verified: true };
173
+ }
174
+ catch (error) {
175
+ console.error(`Failed to verify email for ${app_id}:`, error);
176
+ return { verified: false, reason: 'Verification failed' };
177
+ }
178
+ }
179
+ /**
180
+ * Look up app_id by email (for account recovery)
181
+ *
182
+ * Uses the email→app_id reverse index stored in KV.
183
+ * Only works for apps with verified emails.
184
+ */
185
+ export async function getAppByEmail(kv, email) {
186
+ try {
187
+ const app_id = await kv.get(`email:${email.toLowerCase()}`, 'text');
188
+ if (!app_id)
189
+ return null;
190
+ const data = await kv.get(`app:${app_id}`, 'text');
191
+ if (!data)
192
+ return null;
193
+ const config = JSON.parse(data);
194
+ return {
195
+ app_id: config.app_id,
196
+ email_verified: config.email_verified,
197
+ };
198
+ }
199
+ catch (error) {
200
+ console.error(`Failed to look up app by email:`, error);
201
+ return null;
202
+ }
203
+ }
204
+ /**
205
+ * Rotate app secret — generates a new secret and invalidates the old one.
206
+ *
207
+ * @returns New app_secret (plaintext, only returned once) or null on failure
208
+ */
209
+ export async function rotateAppSecret(kv, app_id) {
210
+ try {
211
+ const data = await kv.get(`app:${app_id}`, 'text');
212
+ if (!data)
213
+ return null;
214
+ const config = JSON.parse(data);
215
+ const new_secret = generateAppSecret();
216
+ const new_hash = await hashSecret(new_secret);
217
+ config.secret_hash = new_hash;
218
+ await kv.put(`app:${app_id}`, JSON.stringify(config));
219
+ return { app_secret: new_secret };
220
+ }
221
+ catch (error) {
222
+ console.error(`Failed to rotate secret for ${app_id}:`, error);
223
+ return null;
224
+ }
225
+ }
89
226
  /**
90
227
  * Get app configuration by app_id
91
228
  *
@@ -107,6 +244,8 @@ export async function getApp(kv, app_id) {
107
244
  app_id: config.app_id,
108
245
  created_at: config.created_at,
109
246
  rate_limit: config.rate_limit,
247
+ email: config.email,
248
+ email_verified: config.email_verified,
110
249
  };
111
250
  }
112
251
  catch (error) {
@@ -114,6 +253,22 @@ export async function getApp(kv, app_id) {
114
253
  return null;
115
254
  }
116
255
  }
256
+ /**
257
+ * Get raw app config (internal use only — includes secret_hash)
258
+ * Used by validateAppSecret and dashboard auth.
259
+ */
260
+ export async function getAppRaw(kv, app_id) {
261
+ try {
262
+ const data = await kv.get(`app:${app_id}`, 'text');
263
+ if (!data)
264
+ return null;
265
+ return JSON.parse(data);
266
+ }
267
+ catch (error) {
268
+ console.error(`Failed to get raw app ${app_id}:`, error);
269
+ return null;
270
+ }
271
+ }
117
272
  /**
118
273
  * Validate an app secret against stored hash
119
274
  *
@@ -1 +1 @@
1
- {"version":3,"file":"challenges.d.ts","sourceRoot":"","sources":["../src/challenges.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"challenges.d.ts","sourceRoot":"","sources":["../src/challenges.ts"],"names":[],"mappings":"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"}
@@ -120,9 +120,10 @@ export async function generateSpeedChallenge(kv, clientTimestamp, app_id) {
120
120
  };
121
121
  // Store in KV with 5 minute TTL (safety buffer for time checks)
122
122
  await storeChallenge(kv, id, challenge, 300);
123
+ const pipelineHint = ' Tip: compute all hashes and submit in a single HTTP request. Sequential shell commands will likely exceed the time limit.';
123
124
  const instructions = rttMs > 0
124
- ? `Compute SHA256 of each number, return first 8 hex chars of each. Submit as array. You have ${adjustedTimeLimit}ms (adjusted for your ${rttMs}ms network latency).`
125
- : 'Compute SHA256 of each number, return first 8 hex chars of each. Submit as array. You have 500ms.';
125
+ ? `Compute SHA256 of each number, return first 8 hex chars of each. Submit as array. You have ${adjustedTimeLimit}ms (adjusted for your ${rttMs}ms network latency).${pipelineHint}`
126
+ : `Compute SHA256 of each number, return first 8 hex chars of each. Submit as array. You have 500ms.${pipelineHint}`;
126
127
  return {
127
128
  id,
128
129
  problems,
@@ -956,8 +957,8 @@ export async function generateHybridChallenge(kv, clientTimestamp, app_id) {
956
957
  hybridChallenges.set(id, hybrid);
957
958
  }
958
959
  const instructions = speedChallenge.rttInfo
959
- ? `Solve ALL speed problems (SHA256) in <${speedChallenge.timeLimit}ms (RTT-adjusted) AND answer ALL reasoning questions. Submit both together.`
960
- : 'Solve ALL speed problems (SHA256) in <500ms AND answer ALL reasoning questions. Submit both together.';
960
+ ? `Solve ALL speed problems (SHA256) in <${speedChallenge.timeLimit}ms (RTT-adjusted) AND answer ALL reasoning questions. Submit both together. Tip: compute all hashes in-process and submit in a single HTTP request.`
961
+ : 'Solve ALL speed problems (SHA256) in <500ms AND answer ALL reasoning questions. Submit both together. Tip: compute all hashes in-process and submit in a single HTTP request.';
961
962
  return {
962
963
  id,
963
964
  speed: {
@@ -0,0 +1,70 @@
1
+ /**
2
+ * BOTCHA Dashboard — Analytics Engine Query API
3
+ *
4
+ * Server-side endpoints that query CF Analytics Engine SQL API
5
+ * and return HTML fragments for htmx to swap in.
6
+ *
7
+ * Data schema (from analytics.ts writeDataPoint):
8
+ * blobs[0] = eventType (challenge_generated | challenge_verified | auth_success | auth_failure | rate_limit_exceeded | error)
9
+ * blobs[1] = challengeType (speed | standard | reasoning | hybrid | '')
10
+ * blobs[2] = endpoint
11
+ * blobs[3] = verificationResult (success | failure | '')
12
+ * blobs[4] = authMethod
13
+ * blobs[5] = clientIP
14
+ * blobs[6] = country
15
+ * blobs[7] = errorType
16
+ * doubles[0] = solveTimeMs
17
+ * doubles[1] = responseTimeMs
18
+ * indexes[0] = eventType
19
+ * indexes[1] = challengeType or 'none'
20
+ * indexes[2] = endpoint or 'unknown'
21
+ */
22
+ import type { Context } from 'hono';
23
+ interface DashboardEnv {
24
+ Bindings: {
25
+ ANALYTICS?: AnalyticsEngineDataset;
26
+ CF_API_TOKEN?: string;
27
+ CF_ACCOUNT_ID?: string;
28
+ [key: string]: unknown;
29
+ };
30
+ [key: string]: unknown;
31
+ }
32
+ type AnalyticsEngineDataset = {
33
+ writeDataPoint: (data: {
34
+ blobs?: string[];
35
+ doubles?: number[];
36
+ indexes?: string[];
37
+ }) => void;
38
+ };
39
+ /**
40
+ * GET /dashboard/api/overview?period=24h
41
+ * Returns HTML fragment with key stats: total challenges, verifications, success rate, avg solve time
42
+ */
43
+ export declare function handleOverview(c: Context<DashboardEnv>, appId: string): Promise<Response>;
44
+ /**
45
+ * GET /dashboard/api/volume?period=24h
46
+ * Returns HTML fragment with time-bucketed event volume
47
+ */
48
+ export declare function handleVolume(c: Context<DashboardEnv>, appId: string): Promise<Response>;
49
+ /**
50
+ * GET /dashboard/api/types?period=24h
51
+ * Returns HTML fragment with challenge type breakdown
52
+ */
53
+ export declare function handleTypes(c: Context<DashboardEnv>, appId: string): Promise<Response>;
54
+ /**
55
+ * GET /dashboard/api/performance?period=24h
56
+ * Returns HTML fragment with performance metrics (solve times, response times)
57
+ */
58
+ export declare function handlePerformance(c: Context<DashboardEnv>, appId: string): Promise<Response>;
59
+ /**
60
+ * GET /dashboard/api/errors?period=24h
61
+ * Returns HTML fragment with error breakdown
62
+ */
63
+ export declare function handleErrors(c: Context<DashboardEnv>, appId: string): Promise<Response>;
64
+ /**
65
+ * GET /dashboard/api/geo?period=24h
66
+ * Returns HTML fragment with geographic distribution
67
+ */
68
+ export declare function handleGeo(c: Context<DashboardEnv>, appId: string): Promise<Response>;
69
+ export {};
70
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/dashboard/api.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAKpC,UAAU,YAAY;IACpB,QAAQ,EAAE;QACR,SAAS,CAAC,EAAE,sBAAsB,CAAC;QACnC,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,CAAC;IACF,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,KAAK,sBAAsB,GAAG;IAC5B,cAAc,EAAE,CAAC,IAAI,EAAE;QACrB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;KACpB,KAAK,IAAI,CAAC;CACZ,CAAC;AA2KF;;;GAGG;AACH,wBAAsB,cAAc,CAAC,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,MAAM,qBA4D3E;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,MAAM,qBAgDzE;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,MAAM,qBA8CxE;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,MAAM,qBAyE9E;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,MAAM,qBA8CzE;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,MAAM,qBA4CtE"}