@domino-sdk/relay 1.67.0 → 1.68.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 (72) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/dist/{accounts-C2O8mpB8.d.ts → accounts-DnpKoJCo.d.ts} +210 -3
  3. package/dist/{attempt-captures-ClHAoo_n.d.ts → attempt-captures-DMNFMYFb.d.ts} +9 -1
  4. package/dist/authoring.d.ts +349 -38
  5. package/dist/authoring.js +125 -18
  6. package/dist/{automatic-outcomes-BEnPn4Uh.d.ts → automatic-outcomes-CQ3vpiQl.d.ts} +2 -2
  7. package/dist/avatar.d.ts +1 -1
  8. package/dist/browser.d.ts +10 -9
  9. package/dist/browser.js +12 -13
  10. package/dist/{catalog-CbiftcxQ.d.ts → catalog-BLGie8Lh.d.ts} +60 -2
  11. package/dist/chunk-4JSPMFO2.js +427 -0
  12. package/dist/{chunk-5DZNMLDM.js → chunk-55WJVFWC.js} +2 -2
  13. package/dist/{chunk-Q5QVAF7R.js → chunk-5AKD4ZF3.js} +37 -25
  14. package/dist/{chunk-DSJ46QLB.js → chunk-6UBFSMCM.js} +1 -1
  15. package/dist/{chunk-P33ZAJMS.js → chunk-6YTSRWRB.js} +1199 -677
  16. package/dist/{chunk-RDUSFUXX.js → chunk-75KF633N.js} +9 -1
  17. package/dist/{chunk-Q6KTTVOI.js → chunk-7YSVZA7A.js} +1 -1
  18. package/dist/{chunk-BMJHFWVT.js → chunk-CZ7NQ7W7.js} +10 -43
  19. package/dist/{chunk-X3FMVRMM.js → chunk-DDJN2T5A.js} +1 -1
  20. package/dist/{chunk-KUNPCDN6.js → chunk-DNPDR4Z7.js} +16 -9
  21. package/dist/{chunk-RWR2LOPA.js → chunk-EXZVWQOQ.js} +2 -2
  22. package/dist/{chunk-MVQQDPQX.js → chunk-HXTKI34N.js} +14 -2
  23. package/dist/{chunk-FGXLXENM.js → chunk-IW46TW3A.js} +21 -1
  24. package/dist/{chunk-5SBA6X5X.js → chunk-KKHENO57.js} +2 -2
  25. package/dist/{chunk-U66GUVSG.js → chunk-LZXDYSUH.js} +2 -0
  26. package/dist/{chunk-QYC3CZVD.js → chunk-MEUAJIVO.js} +2 -2
  27. package/dist/{chunk-BQXRCJ3N.js → chunk-P4TPW4SY.js} +1 -1
  28. package/dist/{chunk-NRMQVK2W.js → chunk-R3MNZKNJ.js} +1 -1
  29. package/dist/{chunk-Z2Z5DBNW.js → chunk-SD74HD75.js} +45 -9
  30. package/dist/{chunk-JK3XV2CR.js → chunk-TYZFVL73.js} +50 -8
  31. package/dist/chunk-VAGGGB6B.js +87 -0
  32. package/dist/{chunk-2HHZV7U3.js → chunk-VRZZB7CQ.js} +1 -1
  33. package/dist/{client-CZPewB9h.d.ts → client-BMif22WQ.d.ts} +133 -7
  34. package/dist/{dashboards-jGPM3AxF.d.ts → dashboards-DMk-vL1q.d.ts} +4 -4
  35. package/dist/{deployments-BVFd7ddA.d.ts → deployments-BCr418BX.d.ts} +582 -173
  36. package/dist/{identity-integration-W1Vo3Ql9.d.ts → identity-integration-r76xaAax.d.ts} +1 -1
  37. package/dist/index.d.ts +10 -10
  38. package/dist/index.js +10 -10
  39. package/dist/internal.d.ts +137 -14
  40. package/dist/internal.js +240 -19
  41. package/dist/{limits-C4RzrOV4.d.ts → limits-ByVRQePO.d.ts} +6 -1
  42. package/dist/{offers-BpYenB9i.d.ts → offers-xcPbYaEv.d.ts} +2 -2
  43. package/dist/portal-proxy.d.ts +2 -2
  44. package/dist/portal-proxy.js +11 -11
  45. package/dist/react/index.d.ts +37 -15
  46. package/dist/react/index.js +12 -13
  47. package/dist/{reward-deliveries-BOWpMytr.d.ts → reward-deliveries-0VvT6LMj.d.ts} +1 -1
  48. package/dist/runtime/authoring.js +1 -1
  49. package/dist/runtime/chunks/2UDZ6TPL.js +1 -0
  50. package/dist/runtime/manifest.json +3 -3
  51. package/dist/runtime/schema.js +1 -1
  52. package/dist/schema.d.ts +398 -104
  53. package/dist/schema.js +62 -8
  54. package/dist/server/index.d.ts +12 -12
  55. package/dist/server/index.js +2046 -886
  56. package/dist/{sign-in-providers-BRYVOSlG.d.ts → sign-in-providers-C5_753DZ.d.ts} +2 -2
  57. package/dist/solana.d.ts +171 -0
  58. package/dist/solana.js +364 -0
  59. package/dist/{submission-input-C152xIdn.d.ts → submission-input-CaL8drIh.d.ts} +2 -2
  60. package/dist/{telegram-browser-657QqiQl.d.ts → telegram-browser-DLtHPRBI.d.ts} +6 -108
  61. package/dist/telegram.d.ts +8 -8
  62. package/dist/telegram.js +2 -2
  63. package/dist/testing.d.ts +85 -13
  64. package/dist/testing.js +101 -11
  65. package/dist/{tracker-data-BqY-9Vu-.d.ts → tracker-data-CAK942sx.d.ts} +298 -1
  66. package/dist/{transport-CthYgZXK.d.ts → transport-CkidqTOk.d.ts} +5250 -1226
  67. package/dist/{wallet-Btng186v.d.ts → wallet-DQtJelQQ.d.ts} +367 -13
  68. package/dist/wallet-browser-dpmr22Xv.d.ts +106 -0
  69. package/package.json +16 -1
  70. package/dist/chunk-UWUS4OOV.js +0 -59
  71. package/dist/chunk-UYVJZR33.js +0 -34
  72. package/dist/runtime/chunks/C2MGLQXC.js +0 -1
@@ -0,0 +1,427 @@
1
+ import {
2
+ activityTypeSchema
3
+ } from "./chunk-DNPDR4Z7.js";
4
+ import {
5
+ completionRecordSchema,
6
+ completionSourceSchema,
7
+ identifier,
8
+ isSolanaNetwork,
9
+ pageCursorSchema,
10
+ pageLimit,
11
+ solanaAddressSchema,
12
+ solanaSignatureSchema
13
+ } from "./chunk-6YTSRWRB.js";
14
+
15
+ // src/server/webhooks.ts
16
+ import * as z from "zod";
17
+ var PayoutSourceKind = {
18
+ Quest: "quest",
19
+ Leaderboard: "leaderboard",
20
+ Engagement: "engagement",
21
+ Manual: "manual"
22
+ };
23
+ var webhookEventSchema = /* @__PURE__ */ (() => z.object({
24
+ id: z.string().uuid(),
25
+ version: z.literal(1),
26
+ type: activityTypeSchema,
27
+ createdAt: z.number().int().nonnegative(),
28
+ organization: z.string(),
29
+ project: z.string(),
30
+ environment: z.enum(["test", "live"]),
31
+ data: z.record(z.string(), z.json())
32
+ }))();
33
+ var walletLinkedEventDataSchema = /* @__PURE__ */ (() => z.object({
34
+ member: z.string(),
35
+ chain: z.string(),
36
+ network: z.string().nullable(),
37
+ address: z.string()
38
+ }))();
39
+ var webhookControlInputSchema = /* @__PURE__ */ (() => z.object({ actionId: z.string().uuid().optional() }).strict())();
40
+ var webhookInputSchema = /* @__PURE__ */ (() => z.object({
41
+ url: z.url().max(2048).refine((value) => {
42
+ const url2 = new URL(value);
43
+ return url2.protocol === "https:" && !url2.username && !url2.password && !url2.hash;
44
+ }, "Use an HTTPS URL without credentials or a fragment"),
45
+ types: z.array(activityTypeSchema).min(1).max(100).refine((v) => new Set(v).size === v.length)
46
+ }).strict())();
47
+ var webhookCreateInputSchema = /* @__PURE__ */ (() => webhookInputSchema.extend({ actionId: z.string().uuid().optional() }).strict())();
48
+ var webhookRotateInputSchema = /* @__PURE__ */ (() => z.object({ actionId: z.string().uuid().optional() }).strict())();
49
+ var webhookUpdateSchema = /* @__PURE__ */ (() => webhookInputSchema.partial().extend({ enabled: z.boolean().optional() }).strict())();
50
+ var webhookEndpointSchema = /* @__PURE__ */ (() => z.object({
51
+ ...webhookInputSchema.shape,
52
+ id: z.string().uuid(),
53
+ enabled: z.boolean(),
54
+ disabledReason: z.string().nullable(),
55
+ consecutiveFailures: z.number().int().nonnegative(),
56
+ createdAt: z.number(),
57
+ updatedAt: z.number()
58
+ }))();
59
+ var webhookEndpointStateSchema = /* @__PURE__ */ (() => webhookEndpointSchema.extend({
60
+ revision: z.number().int().nonnegative(),
61
+ deletedAt: z.number().int().safe().nonnegative().nullable()
62
+ }))();
63
+ var webhookDeleteInputSchema = /* @__PURE__ */ (() => z.strictObject({
64
+ actionId: z.string().uuid().default(() => crypto.randomUUID()),
65
+ expectedRevision: z.number().int().nonnegative(),
66
+ reason: z.string().trim().min(1).max(500)
67
+ }))();
68
+ var webhookStateQuerySchema = /* @__PURE__ */ (() => z.strictObject({
69
+ cursor: pageCursorSchema.optional(),
70
+ limit: z.coerce.number().int().min(1).max(100).default(50)
71
+ }))();
72
+ var webhookStatePageSchema = /* @__PURE__ */ (() => z.object({
73
+ items: z.array(webhookEndpointStateSchema),
74
+ nextCursor: pageCursorSchema.nullable()
75
+ }))();
76
+ var webhookSecretSchema = /* @__PURE__ */ (() => z.object({
77
+ endpoint: webhookEndpointSchema,
78
+ secret: z.string(),
79
+ previousValidUntil: z.number().nullable()
80
+ }))();
81
+ var webhookDeliverySchema = /* @__PURE__ */ (() => z.object({
82
+ id: z.string().uuid(),
83
+ endpoint: z.string().uuid(),
84
+ event: webhookEventSchema,
85
+ status: z.enum(["pending", "delivered", "failed", "skipped"]),
86
+ attempts: z.number().int().nonnegative(),
87
+ responseStatus: z.number().nullable(),
88
+ lastError: z.string().nullable(),
89
+ createdAt: z.number(),
90
+ deliveredAt: z.number().nullable(),
91
+ replayOf: z.string().uuid().nullable()
92
+ }))();
93
+ var webhookQuerySchema = /* @__PURE__ */ (() => z.object({
94
+ /** A page's `nextCursor`: the deliveries after it, newest first. */
95
+ cursor: pageCursorSchema.optional(),
96
+ /** @deprecated Use `cursor`. Removed in 2.0.0. */
97
+ before: z.string().uuid().optional(),
98
+ limit: z.coerce.number().int().min(1).max(100).default(50)
99
+ }).strict())();
100
+ var webhookDeliveryPageSchema = /* @__PURE__ */ (() => z.object({
101
+ items: z.array(webhookDeliverySchema),
102
+ nextCursor: pageCursorSchema.nullable().default(null),
103
+ /** @deprecated Use `nextCursor`, passed back as `cursor`. Removed in 2.0.0. */
104
+ next: z.string().uuid().nullable()
105
+ }))();
106
+ var WEBHOOK_MAX_BYTES = 64 * 1024;
107
+ async function verifyWebhook(input) {
108
+ const bytes = new TextEncoder().encode(input.body);
109
+ const tolerance = input.toleranceSeconds ?? 300;
110
+ const now = input.now ?? Date.now();
111
+ if (bytes.length > WEBHOOK_MAX_BYTES || !Number.isFinite(now) || !Number.isFinite(tolerance) || tolerance < 0 || tolerance > 300) {
112
+ throw new Error("Invalid webhook verification input");
113
+ }
114
+ const parts = input.signature.split(",");
115
+ const timestamps = parts.filter((part) => part.startsWith("t="));
116
+ const timestamp = timestamps[0]?.slice(2) ?? "";
117
+ const signatures = parts.filter((part) => /^v1=[a-f0-9]{64}$/.test(part)).map((part) => part.slice(3));
118
+ if (timestamps.length !== 1 || !/^\d{1,12}$/.test(timestamp) || Math.abs(now / 1e3 - Number(timestamp)) > tolerance || signatures.length < 1 || signatures.length > 2) {
119
+ throw new Error("Invalid or expired webhook signature");
120
+ }
121
+ const secrets = typeof input.secret === "string" ? [input.secret] : input.secret;
122
+ const message = new TextEncoder().encode(`${timestamp}.${input.body}`);
123
+ for (const secret of secrets) {
124
+ if (!secret) {
125
+ continue;
126
+ }
127
+ const key = await crypto.subtle.importKey(
128
+ "raw",
129
+ new TextEncoder().encode(secret),
130
+ { name: "HMAC", hash: "SHA-256" },
131
+ false,
132
+ ["verify"]
133
+ );
134
+ for (const signature of signatures) {
135
+ const digest = Uint8Array.from(
136
+ signature.match(/../g) ?? [],
137
+ (byte) => Number.parseInt(byte, 16)
138
+ );
139
+ if (await crypto.subtle.verify("HMAC", key, digest, message)) {
140
+ return webhookEventSchema.parse(JSON.parse(input.body));
141
+ }
142
+ }
143
+ }
144
+ throw new Error("Invalid webhook signature");
145
+ }
146
+
147
+ // src/server/completions.ts
148
+ import * as z2 from "zod";
149
+ var completionRevokeSchema = /* @__PURE__ */ (() => z2.object({
150
+ actionId: identifier,
151
+ reason: z2.string().trim().min(1).max(500),
152
+ freeOccurrence: z2.boolean().default(false)
153
+ }).strict())();
154
+ var RevokedEntitlementOutcome = {
155
+ /** No other completion grants the reward: it is void, after cancelling a handover in progress. */
156
+ Voided: "voided",
157
+ /** Lowered to the best tier another completion grants, after cancelling a handover in progress. */
158
+ Downgraded: "downgraded",
159
+ /** Another completion grants the same tier, or it was already void. */
160
+ Kept: "kept",
161
+ /** Already collected: its earned tier follows the other completions, and the item stays handed over. */
162
+ Flagged: "flagged"
163
+ };
164
+ var RevokedDeliveryOutcome = {
165
+ /** The role was delivered and stays: remove it in Discord if appropriate. */
166
+ Flagged: "flagged",
167
+ /** The grant was stopped before any call to Discord. */
168
+ Cancelled: "cancelled",
169
+ /** The grant was stopped, but a call to Discord may already have been sent and can still land. */
170
+ InFlight: "in-flight",
171
+ /** The grant had failed, so Discord never received the role. */
172
+ NotDelivered: "not-delivered"
173
+ };
174
+ var RevokedReferralOutcome = {
175
+ /** The inviter's rewards for this member are reversed. */
176
+ Unqualified: "unqualified",
177
+ /** Qualified on another accepted completion of the program's quest instead. */
178
+ Requalified: "requalified"
179
+ };
180
+ var entitlementOutcomeSchema = /* @__PURE__ */ (() => z2.string().min(1).max(64))();
181
+ var deliveryOutcomeSchema = /* @__PURE__ */ (() => z2.string().min(1).max(64))();
182
+ var referralOutcomeSchema = /* @__PURE__ */ (() => z2.string().min(1).max(64))();
183
+ var completionRevocationSchema = /* @__PURE__ */ (() => z2.object({
184
+ completion: identifier,
185
+ /** The quest ID, or the board ID when `source.kind` is `leaderboard`. */
186
+ quest: identifier,
187
+ member: identifier,
188
+ /** What paid the revoked completion. `source.id` repeats `quest`. */
189
+ source: completionSourceSchema.optional(),
190
+ revokedAt: z2.number(),
191
+ occurrenceFreed: z2.boolean(),
192
+ badges: z2.array(z2.object({ badge: identifier, stillAwarded: z2.boolean() })).optional(),
193
+ groups: z2.array(z2.object({ group: identifier, stillMember: z2.boolean() })).optional(),
194
+ points: z2.array(
195
+ z2.object({
196
+ entry: identifier,
197
+ balance: identifier,
198
+ reversal: identifier.nullable(),
199
+ reversed: z2.number().int(),
200
+ unreversed: z2.number().int()
201
+ })
202
+ ),
203
+ entitlements: z2.array(
204
+ z2.object({
205
+ entitlement: identifier,
206
+ reward: identifier,
207
+ outcome: entitlementOutcomeSchema,
208
+ status: z2.string()
209
+ })
210
+ ),
211
+ deliveries: z2.array(
212
+ z2.object({
213
+ delivery: z2.string(),
214
+ roleId: z2.string(),
215
+ outcome: deliveryOutcomeSchema,
216
+ /**
217
+ * By Relay's records, another accepted, unrevoked completion of the member also granted this
218
+ * role to the same Discord account and server. Relay does not read Discord's membership.
219
+ */
220
+ stillGranted: z2.boolean()
221
+ })
222
+ ),
223
+ referrals: z2.array(
224
+ z2.object({
225
+ program: identifier,
226
+ outcome: referralOutcomeSchema
227
+ })
228
+ ),
229
+ streakMilestone: z2.boolean(),
230
+ budgets: z2.array(
231
+ z2.object({ budget: identifier, released: z2.number().int().nonnegative() })
232
+ ).optional()
233
+ }))();
234
+ var completionRestoreSchema = /* @__PURE__ */ (() => z2.object({
235
+ actionId: identifier,
236
+ reason: z2.string().trim().min(1).max(500)
237
+ }).strict())();
238
+ var RestoredEntitlementOutcome = {
239
+ /** The revocation voided it, and it is available again. */
240
+ Restored: "restored",
241
+ /** The revocation lowered or flagged it: its earned tier is the completion's again. */
242
+ Raised: "raised",
243
+ /** It changed since the revocation (an operator restored, voided or corrected it), so it stays. */
244
+ Kept: "kept"
245
+ };
246
+ var RestoredDeliveryOutcome = {
247
+ /** The grant had not reached Discord, and it is queued again. */
248
+ Requeued: "requeued",
249
+ /** The grant counts again for reconciliation, and its delivery status stays. */
250
+ Kept: "kept"
251
+ };
252
+ var RestoredReferralOutcome = {
253
+ /** The member qualifies on this completion again. */
254
+ Qualified: "qualified",
255
+ /** The program is disabled or gone, or the referral is suspended, so nothing changed. */
256
+ Kept: "kept"
257
+ };
258
+ var openOutcome = /* @__PURE__ */ (() => z2.string().min(1).max(64))();
259
+ var completionRestorationSchema = /* @__PURE__ */ (() => z2.object({
260
+ completion: identifier,
261
+ /** The quest ID, or the board ID when `source.kind` is `leaderboard`. */
262
+ quest: identifier,
263
+ member: identifier,
264
+ source: completionSourceSchema.optional(),
265
+ restoredAt: z2.number(),
266
+ points: z2.array(
267
+ z2.object({
268
+ entry: identifier,
269
+ balance: identifier,
270
+ reversal: identifier,
271
+ amount: z2.number().int()
272
+ })
273
+ ),
274
+ badges: z2.array(z2.object({ badge: identifier })),
275
+ groups: z2.array(z2.object({ group: identifier, added: z2.boolean() })),
276
+ entitlements: z2.array(
277
+ z2.object({
278
+ entitlement: identifier,
279
+ reward: identifier,
280
+ outcome: openOutcome,
281
+ status: z2.string()
282
+ })
283
+ ),
284
+ deliveries: z2.array(
285
+ z2.object({
286
+ delivery: z2.string(),
287
+ roleId: z2.string(),
288
+ outcome: openOutcome
289
+ })
290
+ ),
291
+ referrals: z2.array(
292
+ z2.object({
293
+ program: identifier,
294
+ outcome: openOutcome
295
+ })
296
+ ),
297
+ streakMilestone: z2.boolean(),
298
+ budgets: z2.array(
299
+ z2.object({ budget: identifier, charged: z2.number().int().nonnegative() })
300
+ ).optional()
301
+ }))();
302
+ var completionRevocationShortfallSchema = /* @__PURE__ */ (() => z2.object({
303
+ completion: identifier,
304
+ quest: identifier,
305
+ revokedAt: z2.number().int().nonnegative().safe(),
306
+ unreversedPoints: z2.record(identifier, z2.number().int().positive().safe())
307
+ }))();
308
+ var revokedCompletionSchema = /* @__PURE__ */ (() => z2.object({
309
+ completion: identifier,
310
+ quest: identifier,
311
+ /** The completion key: its occurrence, such as `once` or a day. */
312
+ key: z2.string(),
313
+ revokedAt: z2.number().int().nonnegative().safe(),
314
+ /** Why it was revoked, and what the revoke did, which a restore re-applies. */
315
+ reason: z2.string().optional(),
316
+ revocation: completionRevocationSchema.optional()
317
+ }))();
318
+ var maxCompletionReceipts = 20;
319
+ var receiptNetworkPattern = /^[-a-z0-9]{3,8}:[-_a-zA-Z0-9]{1,32}$/;
320
+ var receiptValue = /* @__PURE__ */ (() => z2.string().min(1).max(256).regex(/^[\x21-\x7e]+$/, "Use printable characters without spaces"))();
321
+ var completionReceiptInputSchema = /* @__PURE__ */ (() => z2.object({
322
+ actionId: identifier,
323
+ key: z2.string().regex(
324
+ /^[a-z0-9][a-z0-9._-]{0,63}$/,
325
+ "Use 1 to 64 lowercase letters, digits, dots, hyphens or underscores"
326
+ ),
327
+ network: z2.string().regex(
328
+ receiptNetworkPattern,
329
+ "Use a CAIP-2 chain ID such as solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
330
+ ),
331
+ signature: receiptValue,
332
+ asset: receiptValue.optional(),
333
+ recipient: receiptValue.optional(),
334
+ label: z2.string().trim().min(1).max(120).optional()
335
+ }).strict().superRefine((receipt, context) => {
336
+ if (!isSolanaNetwork(receipt.network)) {
337
+ return;
338
+ }
339
+ if (!solanaSignatureSchema.safeParse(receipt.signature).success) {
340
+ context.addIssue({
341
+ code: "custom",
342
+ path: ["signature"],
343
+ message: "Use a Solana transaction signature: base58, 64 bytes"
344
+ });
345
+ }
346
+ for (const field of ["asset", "recipient"]) {
347
+ const value = receipt[field];
348
+ if (value !== void 0 && !solanaAddressSchema.safeParse(value).success) {
349
+ context.addIssue({
350
+ code: "custom",
351
+ path: [field],
352
+ message: "Use a base58 Solana address"
353
+ });
354
+ }
355
+ }
356
+ }))();
357
+ var completionReceiptSchema = /* @__PURE__ */ (() => z2.object({
358
+ completion: identifier,
359
+ /** The quest ID, or the board ID for a leaderboard prize's completion. */
360
+ quest: identifier,
361
+ member: identifier,
362
+ key: z2.string(),
363
+ network: z2.string(),
364
+ signature: z2.string(),
365
+ asset: z2.string().nullable(),
366
+ recipient: z2.string().nullable(),
367
+ label: z2.string().nullable(),
368
+ recordedAt: z2.number().int().nonnegative().safe(),
369
+ /** The operator or key that recorded it. */
370
+ recordedBy: z2.string().nullable(),
371
+ completionRevokedAt: z2.number().int().nonnegative().safe().nullable()
372
+ }))();
373
+ var completionReceiptListSchema = /* @__PURE__ */ (() => z2.array(completionReceiptSchema))();
374
+ var memberCompletionQuerySchema = /* @__PURE__ */ (() => z2.strictObject({
375
+ member: identifier,
376
+ quest: identifier.optional(),
377
+ cursor: pageCursorSchema.optional(),
378
+ limit: pageLimit
379
+ }))();
380
+ var memberCompletionSchema = /* @__PURE__ */ (() => completionRecordSchema.extend({
381
+ completedAt: z2.number().int().nonnegative().safe().nullable()
382
+ }))();
383
+ var memberCompletionPageSchema = /* @__PURE__ */ (() => z2.object({
384
+ items: z2.array(memberCompletionSchema),
385
+ nextCursor: pageCursorSchema.nullable()
386
+ }))();
387
+
388
+ export {
389
+ PayoutSourceKind,
390
+ webhookEventSchema,
391
+ walletLinkedEventDataSchema,
392
+ webhookControlInputSchema,
393
+ webhookInputSchema,
394
+ webhookCreateInputSchema,
395
+ webhookRotateInputSchema,
396
+ webhookUpdateSchema,
397
+ webhookEndpointSchema,
398
+ webhookEndpointStateSchema,
399
+ webhookDeleteInputSchema,
400
+ webhookStateQuerySchema,
401
+ webhookStatePageSchema,
402
+ webhookSecretSchema,
403
+ webhookDeliverySchema,
404
+ webhookQuerySchema,
405
+ webhookDeliveryPageSchema,
406
+ WEBHOOK_MAX_BYTES,
407
+ verifyWebhook,
408
+ completionRevokeSchema,
409
+ RevokedEntitlementOutcome,
410
+ RevokedDeliveryOutcome,
411
+ RevokedReferralOutcome,
412
+ completionRevocationSchema,
413
+ completionRestoreSchema,
414
+ RestoredEntitlementOutcome,
415
+ RestoredDeliveryOutcome,
416
+ RestoredReferralOutcome,
417
+ completionRestorationSchema,
418
+ completionRevocationShortfallSchema,
419
+ revokedCompletionSchema,
420
+ maxCompletionReceipts,
421
+ completionReceiptInputSchema,
422
+ completionReceiptSchema,
423
+ completionReceiptListSchema,
424
+ memberCompletionQuerySchema,
425
+ memberCompletionSchema,
426
+ memberCompletionPageSchema
427
+ };
@@ -12,10 +12,10 @@ import {
12
12
  resourceHandle,
13
13
  responseShape,
14
14
  tierRewardSchema
15
- } from "./chunk-P33ZAJMS.js";
15
+ } from "./chunk-6YTSRWRB.js";
16
16
  import {
17
17
  parseDefinition
18
- } from "./chunk-FGXLXENM.js";
18
+ } from "./chunk-IW46TW3A.js";
19
19
 
20
20
  // src/engagement.ts
21
21
  import * as z from "zod";
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  imageAssetArtifactSchema
3
- } from "./chunk-X3FMVRMM.js";
3
+ } from "./chunk-DDJN2T5A.js";
4
4
  import {
5
5
  authScopeSchema,
6
6
  exchangeResultSchema
7
- } from "./chunk-DSJ46QLB.js";
7
+ } from "./chunk-6UBFSMCM.js";
8
8
  import {
9
9
  appIdentityKindSchema,
10
10
  cosmosAddressSchema,
@@ -17,7 +17,7 @@ import {
17
17
  openIdentityKindSchema,
18
18
  pageCursorSchema,
19
19
  solanaAddressSchema
20
- } from "./chunk-P33ZAJMS.js";
20
+ } from "./chunk-6YTSRWRB.js";
21
21
 
22
22
  // src/credential-secrets.ts
23
23
  import * as z from "zod";
@@ -418,6 +418,34 @@ var memberImportListQuerySchema = /* @__PURE__ */ (() => z2.object({
418
418
  // src/server/schedules.ts
419
419
  import * as z3 from "zod";
420
420
  import { Cron } from "croner";
421
+
422
+ // src/server/request-body.ts
423
+ async function boundedBodyText(body, limit) {
424
+ const reader = body.getReader();
425
+ let text = "";
426
+ let size = 0;
427
+ const decoder = new TextDecoder();
428
+ try {
429
+ for (; ; ) {
430
+ const chunk = await reader.read();
431
+ if (chunk.done) {
432
+ break;
433
+ }
434
+ size += chunk.value.byteLength;
435
+ if (size > limit) {
436
+ void reader.cancel().catch(() => {
437
+ });
438
+ return null;
439
+ }
440
+ text += decoder.decode(chunk.value, { stream: true });
441
+ }
442
+ return text + decoder.decode();
443
+ } catch {
444
+ return null;
445
+ }
446
+ }
447
+
448
+ // src/server/schedules.ts
421
449
  var APP_SCHEDULE_LIMIT = 10;
422
450
  var APP_SCHEDULE_MIN_INTERVAL = 3e5;
423
451
  var APP_SCHEDULE_TIMEOUT = 3e4;
@@ -564,29 +592,12 @@ async function verifyScheduledRequest(request, key) {
564
592
  if (request.method !== "POST" || url.search !== "" || url.hash !== "" || !key || !signature || !/^[a-f0-9]{64}$/.test(signature)) {
565
593
  return null;
566
594
  }
567
- const reader = request.clone().body?.getReader();
568
- if (!reader) {
595
+ const stream = request.clone().body;
596
+ if (!stream) {
569
597
  return null;
570
598
  }
571
- let body = "";
572
- let size = 0;
573
- const decoder = new TextDecoder();
574
- try {
575
- for (; ; ) {
576
- const chunk = await reader.read();
577
- if (chunk.done) {
578
- break;
579
- }
580
- size += chunk.value.byteLength;
581
- if (size > 4096) {
582
- void reader.cancel().catch(() => {
583
- });
584
- return null;
585
- }
586
- body += decoder.decode(chunk.value, { stream: true });
587
- }
588
- body += decoder.decode();
589
- } catch {
599
+ const body = await boundedBodyText(stream, 4096);
600
+ if (body === null) {
590
601
  return null;
591
602
  }
592
603
  const secret = await crypto.subtle.importKey(
@@ -626,7 +637,7 @@ var starters = [
626
637
  {
627
638
  id: "campaign",
628
639
  title: "Campaign tour",
629
- summary: "A neutral quest app with a guided tour of every quest kind. The blank canvas for anything."
640
+ summary: "A quest app with a guided tour of every quest kind, in a clean default look to rebrand. The blank canvas for anything."
630
641
  },
631
642
  {
632
643
  id: "classic",
@@ -1430,6 +1441,7 @@ export {
1430
1441
  memberImportSchema,
1431
1442
  memberImportPageSchema,
1432
1443
  memberImportListQuerySchema,
1444
+ boundedBodyText,
1433
1445
  APP_SCHEDULE_LIMIT,
1434
1446
  APP_SCHEDULE_MIN_INTERVAL,
1435
1447
  APP_SCHEDULE_TIMEOUT,
@@ -19,7 +19,7 @@ import {
19
19
  storedQuestDescriptionSchema,
20
20
  storedReviewModeSchema,
21
21
  tieredRewardReferenceSchema
22
- } from "./chunk-P33ZAJMS.js";
22
+ } from "./chunk-6YTSRWRB.js";
23
23
 
24
24
  // src/participant-activity.ts
25
25
  import * as z from "zod";