@domino-sdk/relay 1.0.0-next.9 → 1.0.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 (59) hide show
  1. package/README.md +1 -1
  2. package/dist/activity-DeKJsRry.d.ts +9112 -0
  3. package/dist/authoring.d.ts +1027 -233
  4. package/dist/authoring.js +478 -277
  5. package/dist/automatic-outcomes-B1xrETxm.d.ts +758 -0
  6. package/dist/avatar.d.ts +2 -2
  7. package/dist/browser-DFe7sWSN.d.ts +4154 -0
  8. package/dist/browser.d.ts +11 -2613
  9. package/dist/browser.js +8 -6
  10. package/dist/{integrations-Ba5TtqTv.d.ts → capability-error-DNMwKmlL.d.ts} +124 -76
  11. package/dist/{chunk-PHU5VDLR.js → chunk-36HTX2BM.js} +389 -169
  12. package/dist/chunk-6QJ3LADK.js +112 -0
  13. package/dist/{chunk-4LBUTHD6.js → chunk-BGGKNIRP.js} +1 -1
  14. package/dist/chunk-EYH5RDIE.js +496 -0
  15. package/dist/chunk-GQKYAQM6.js +84 -0
  16. package/dist/chunk-GUP7YRR4.js +42 -0
  17. package/dist/{chunk-X2F2RAR3.js → chunk-GZ6FJAXN.js} +380 -128
  18. package/dist/chunk-JON5SESL.js +2986 -0
  19. package/dist/chunk-MC6V6VMG.js +49 -0
  20. package/dist/chunk-NPGENI7K.js +37 -0
  21. package/dist/chunk-VFHHLN6A.js +284 -0
  22. package/dist/chunk-WJSSJ7AF.js +151 -0
  23. package/dist/{chunk-7Q4BGGT6.js → chunk-XFMSUPNS.js} +1 -1
  24. package/dist/{chunk-P6FK43GG.js → chunk-ZVIRG24J.js} +145 -42
  25. package/dist/{client-CT4-S5vc.d.ts → client-XiuFnug_.d.ts} +2161 -615
  26. package/dist/{submission-input-0OOGaq8c.d.ts → groups-Ck-OxzjD.d.ts} +916 -1139
  27. package/dist/identity-integration-GxAHdKR2.d.ts +58 -0
  28. package/dist/images-Dv-P5VBw.d.ts +234 -0
  29. package/dist/index.d.ts +13 -9
  30. package/dist/index.js +17 -6
  31. package/dist/internal.d.ts +82 -44
  32. package/dist/internal.js +43 -89
  33. package/dist/offers-Cy-e4o5x.d.ts +431 -0
  34. package/dist/{pages-D3titw5B.d.ts → outcomes-kVB-Juzs.d.ts} +2157 -1448
  35. package/dist/pages-BBYD21IE.d.ts +359 -0
  36. package/dist/participant-rewards-3duLb8YJ.d.ts +668 -0
  37. package/dist/portal-proxy.js +22 -4
  38. package/dist/{profiles-DDMFBRKe.d.ts → profiles-D2aFcOxu.d.ts} +15 -15
  39. package/dist/react/index.d.ts +3038 -1029
  40. package/dist/react/index.js +1627 -779
  41. package/dist/request-error-DWduJCGV.d.ts +62 -0
  42. package/dist/schema-DfJzH2ci.d.ts +5644 -0
  43. package/dist/schema.d.ts +15 -4168
  44. package/dist/schema.js +310 -81
  45. package/dist/server/index.d.ts +81498 -0
  46. package/dist/server/index.js +2520 -0
  47. package/dist/{streaks-CwGReWGt.d.ts → streaks-CWyq8Px5.d.ts} +2 -4
  48. package/dist/submission-input-BZkm6ohU.d.ts +290 -0
  49. package/dist/vite.d.ts +1 -1
  50. package/dist/vite.js +1 -0
  51. package/dist/{wallet-BGOfFkG9.d.ts → wallet-YssWxGg8.d.ts} +35 -38
  52. package/package.json +8 -2
  53. package/dist/chunk-QR7ZA2BJ.js +0 -257
  54. package/dist/chunk-YYD4QUBO.js +0 -2348
  55. package/dist/chunk-ZWY3R6B3.js +0 -26
  56. package/dist/collection-BGneJ6Bk.d.ts +0 -114
  57. package/dist/images-BTgk6OmC.d.ts +0 -1564
  58. package/dist/point-ledgers-iS00Z_v0.d.ts +0 -37
  59. package/dist/schema-Di3aLSiK.d.ts +0 -3532
@@ -0,0 +1,2986 @@
1
+ // src/pages.ts
2
+ import { z } from "zod";
3
+ var pageCursorSchema = z.string().min(1).max(4096);
4
+ var pageQuerySchema = z.strictObject({
5
+ cursor: pageCursorSchema.optional()
6
+ });
7
+
8
+ // src/accounts.ts
9
+ import { z as z2 } from "zod";
10
+ var authProviderSchema = z2.enum(["google", "apple", "x", "discord"]);
11
+ var accountConnectionSchema = z2.object({
12
+ provider: authProviderSchema,
13
+ configured: z2.boolean(),
14
+ status: z2.enum(["disconnected", "connected", "reconnect"]),
15
+ subject: z2.string().nullable(),
16
+ revision: z2.number().int().nonnegative()
17
+ });
18
+ var discordMemberInputSchema = z2.object({}).strict();
19
+ var discordMessageInputSchema = z2.object({
20
+ channelId: z2.string().regex(/^[0-9]{1,20}$/),
21
+ messageId: z2.string().regex(/^[0-9]{1,20}$/)
22
+ }).strict();
23
+ var discordMemberSchema = z2.object({
24
+ userId: z2.string().regex(/^[0-9]{1,20}$/).nullable().default(null),
25
+ nickname: z2.string().nullable().default(null),
26
+ displayName: z2.string().nullable().default(null),
27
+ boostingSince: z2.string().datetime({ offset: true }).nullable().default(null),
28
+ roles: z2.array(z2.string().regex(/^[0-9]{1,20}$/)),
29
+ joinedAt: z2.string().datetime({ offset: true }).nullable(),
30
+ pending: z2.boolean()
31
+ });
32
+
33
+ // src/identifier.ts
34
+ import { z as z3 } from "zod";
35
+ var identifier = z3.string().min(1).max(100).regex(/^[a-zA-Z0-9_-]+$/);
36
+
37
+ // src/discord.ts
38
+ import { z as z4 } from "zod";
39
+ var discordMessageSchema = z4.object({
40
+ guildId: z4.string(),
41
+ channelId: z4.string(),
42
+ messageId: z4.string(),
43
+ userId: z4.string(),
44
+ content: z4.string().nullable(),
45
+ replyTo: z4.string().nullable(),
46
+ publishedAt: z4.number()
47
+ }).strict();
48
+ var discordMessagesSourceSchema = z4.strictObject({
49
+ kind: z4.literal("discord-messages"),
50
+ /** Store each message's text in `data.text`. Off unless set. */
51
+ text: z4.boolean().optional()
52
+ });
53
+ var discordReactionsSourceSchema = z4.strictObject({
54
+ kind: z4.literal("discord-reactions")
55
+ });
56
+ var discordMessageDataSchema = z4.object({
57
+ guildId: z4.string(),
58
+ channelId: z4.string(),
59
+ messageId: z4.string(),
60
+ /** The ID of the message this one replies to, or null. */
61
+ replyTo: z4.string().nullable(),
62
+ /** When Discord says the message was posted, in epoch milliseconds. */
63
+ publishedAt: z4.number()
64
+ });
65
+ var discordMessageTextDataSchema = discordMessageDataSchema.extend({
66
+ text: z4.string().nullable()
67
+ });
68
+ var discordReactionDataSchema = z4.object({
69
+ guildId: z4.string(),
70
+ channelId: z4.string(),
71
+ /** The message reacted to. */
72
+ messageId: z4.string(),
73
+ /** A custom emoji's ID, or null for a Unicode emoji, whose `name` is the emoji itself. */
74
+ emoji: z4.object({ id: z4.string().nullable(), name: z4.string() }),
75
+ /** The role IDs the reactor held in the server when reacting. */
76
+ reactorRoles: z4.array(z4.string()),
77
+ /** When the reacted-to message was posted, in epoch milliseconds. */
78
+ messagePublishedAt: z4.number()
79
+ });
80
+ var discordRewardSchema = z4.strictObject({
81
+ kind: z4.literal("integration"),
82
+ provider: z4.literal("discord"),
83
+ action: z4.literal("grant-role"),
84
+ roleId: z4.string().regex(/^[0-9]{1,20}$/)
85
+ });
86
+ var discordResourceSourceSchema = z4.union([
87
+ z4.strictObject({
88
+ provider: z4.literal("discord"),
89
+ resource: z4.literal("channel"),
90
+ types: z4.array(z4.enum(["text", "announcement"])).min(1)
91
+ }),
92
+ z4.strictObject({
93
+ provider: z4.literal("discord"),
94
+ resource: z4.literal("role"),
95
+ assignable: z4.boolean().default(false)
96
+ })
97
+ ]);
98
+
99
+ // src/tracker-data.ts
100
+ import { z as z5 } from "zod";
101
+ var maxDepth = 16;
102
+ var maxBytes = 32768;
103
+ var trackerDataMaxBranches = 16;
104
+ var trackerDataMaxEntries = 256;
105
+ var scalar = z5.union([z5.string(), z5.number().finite(), z5.boolean(), z5.null()]);
106
+ var size = z5.number().int().safe().nonnegative();
107
+ var bound = z5.number().finite();
108
+ var branches = () => z5.array(node).min(1).max(trackerDataMaxBranches);
109
+ var node = z5.lazy(
110
+ () => z5.strictObject({
111
+ type: z5.enum([
112
+ "object",
113
+ "array",
114
+ "string",
115
+ "number",
116
+ "integer",
117
+ "boolean",
118
+ "null"
119
+ ]).optional(),
120
+ properties: z5.record(z5.string(), node).refine(
121
+ (properties) => Object.keys(properties).length <= trackerDataMaxEntries,
122
+ `An object schema lists at most ${trackerDataMaxEntries} properties`
123
+ ).optional(),
124
+ required: z5.array(z5.string()).max(trackerDataMaxEntries).optional(),
125
+ additionalProperties: z5.union([z5.boolean(), node]).optional(),
126
+ propertyNames: z5.strictObject({
127
+ type: z5.literal("string"),
128
+ enum: z5.array(z5.string()).max(trackerDataMaxEntries).optional()
129
+ }).optional(),
130
+ items: node.optional(),
131
+ minItems: size.optional(),
132
+ maxItems: size.optional(),
133
+ minLength: size.optional(),
134
+ maxLength: size.optional(),
135
+ minimum: bound.optional(),
136
+ maximum: bound.optional(),
137
+ exclusiveMinimum: bound.optional(),
138
+ exclusiveMaximum: bound.optional(),
139
+ enum: z5.array(scalar).min(1).max(trackerDataMaxEntries).optional(),
140
+ const: scalar.optional(),
141
+ anyOf: branches().optional(),
142
+ oneOf: branches().optional(),
143
+ allOf: branches().optional()
144
+ })
145
+ );
146
+ function shapeIssue(value) {
147
+ const pending = [[value, 0]];
148
+ while (pending.length) {
149
+ const [current, level] = pending.pop();
150
+ if (typeof current !== "object" || current === null) {
151
+ continue;
152
+ }
153
+ if (level >= maxDepth) {
154
+ return "Tracker data schemas are at most 32 KB and 16 levels deep";
155
+ }
156
+ if (!Array.isArray(current) && Object.hasOwn(current, "__proto__")) {
157
+ return "Tracker data schemas cannot name a property __proto__";
158
+ }
159
+ for (const child of Object.values(current)) {
160
+ pending.push([child, level + 1]);
161
+ }
162
+ }
163
+ return new TextEncoder().encode(JSON.stringify(value)).byteLength > maxBytes ? "Tracker data schemas are at most 32 KB and 16 levels deep" : null;
164
+ }
165
+ var unions = (s) => [
166
+ ...s.anyOf ?? [],
167
+ ...s.oneOf ?? [],
168
+ ...s.allOf ?? []
169
+ ];
170
+ var compound = (s) => s.properties !== void 0 || s.items !== void 0 || typeof s.additionalProperties === "object" || unions(s).length > 0;
171
+ function nestedUnionIssue(schema, path, insideUnion) {
172
+ const own = unions(schema);
173
+ if (insideUnion && own.filter(compound).length > 1) {
174
+ return path;
175
+ }
176
+ const children = [
177
+ ...Object.entries(schema.properties ?? {}).map(
178
+ ([key, child]) => [child, `${path}.${key}`]
179
+ )
180
+ ];
181
+ if (schema.items) {
182
+ children.push([schema.items, path]);
183
+ }
184
+ if (typeof schema.additionalProperties === "object") {
185
+ children.push([schema.additionalProperties, path]);
186
+ }
187
+ for (const [child, at] of children) {
188
+ const found = nestedUnionIssue(child, at, insideUnion);
189
+ if (found) {
190
+ return found;
191
+ }
192
+ }
193
+ for (const branch of own) {
194
+ const found = nestedUnionIssue(branch, path, true);
195
+ if (found) {
196
+ return found;
197
+ }
198
+ }
199
+ return null;
200
+ }
201
+ var trackerDataSchemaSchema = z5.unknown().superRefine((value, ctx) => {
202
+ const issue = shapeIssue(value);
203
+ if (issue) {
204
+ ctx.addIssue({ code: "custom", message: issue, abort: true });
205
+ }
206
+ }).pipe(node).refine(
207
+ (schema) => schema.type === "object",
208
+ "A tracker's record data is an object: declare it with z.object({ ... })"
209
+ ).superRefine((schema, ctx) => {
210
+ const at = nestedUnionIssue(schema, "data", false);
211
+ if (at) {
212
+ ctx.addIssue({
213
+ code: "custom",
214
+ message: `Tracker data schemas cannot nest a union with several object, array or union branches inside another union's branch (${at}): flatten it into one union`
215
+ });
216
+ }
217
+ });
218
+ var unsupported = {
219
+ pattern: "check string patterns in your evaluator",
220
+ format: "use z.string() and check the format in your evaluator",
221
+ prefixItems: "use an array or an object instead of a tuple",
222
+ multipleOf: "check divisibility in your evaluator",
223
+ not: "describe the allowed values instead",
224
+ $ref: "inline the schema instead of registering or reusing it by ID",
225
+ $defs: "inline the schema instead of registering or reusing it by ID",
226
+ definitions: "inline the schema instead of registering or reusing it by ID",
227
+ if: "use a union instead",
228
+ then: "use a union instead",
229
+ else: "use a union instead",
230
+ contains: "check array contents in your evaluator",
231
+ minContains: "check array contents in your evaluator",
232
+ maxContains: "check array contents in your evaluator",
233
+ uniqueItems: "check uniqueness in your evaluator",
234
+ minProperties: "check key counts in your evaluator",
235
+ maxProperties: "check key counts in your evaluator",
236
+ patternProperties: "use z.record(z.string(), value) instead",
237
+ dependentRequired: "use a union instead",
238
+ dependentSchemas: "use a union instead",
239
+ unevaluatedProperties: "use a strict object instead",
240
+ unevaluatedItems: "use an array instead"
241
+ };
242
+ var nested = /* @__PURE__ */ new Set(["additionalProperties", "items", "propertyNames"]);
243
+ var listed = /* @__PURE__ */ new Set(["anyOf", "oneOf", "allOf"]);
244
+ var supported = /* @__PURE__ */ new Set([
245
+ "type",
246
+ "properties",
247
+ "required",
248
+ "minItems",
249
+ "maxItems",
250
+ "minLength",
251
+ "maxLength",
252
+ "minimum",
253
+ "maximum",
254
+ "exclusiveMinimum",
255
+ "exclusiveMaximum",
256
+ "enum",
257
+ "const",
258
+ ...nested,
259
+ ...listed
260
+ ]);
261
+ var annotations = /* @__PURE__ */ new Set([
262
+ "$schema",
263
+ "$id",
264
+ "$comment",
265
+ "title",
266
+ "description",
267
+ "default",
268
+ "examples",
269
+ "deprecated",
270
+ "readOnly",
271
+ "writeOnly"
272
+ ]);
273
+ function subset(schema, path) {
274
+ if (typeof schema !== "object" || schema === null || Array.isArray(schema)) {
275
+ return schema;
276
+ }
277
+ const kept = {};
278
+ for (const [key, value] of Object.entries(schema)) {
279
+ if (Object.hasOwn(unsupported, key)) {
280
+ throw new Error(
281
+ `Tracker data schemas cannot use ${key} (${path}): ${unsupported[key]}`
282
+ );
283
+ }
284
+ if (annotations.has(key)) {
285
+ continue;
286
+ }
287
+ if (!supported.has(key)) {
288
+ throw new Error(
289
+ `Tracker data schemas cannot use the keyword ${key} (${path}): keep metadata to title, description, default and examples`
290
+ );
291
+ }
292
+ if (key === "properties" && Object.hasOwn(value, "__proto__") || key === "required" && value.includes("__proto__")) {
293
+ throw new Error(
294
+ `Tracker data schemas cannot name a property __proto__ (${path})`
295
+ );
296
+ }
297
+ kept[key] = key === "properties" ? Object.fromEntries(
298
+ Object.entries(value).map(
299
+ ([name2, child]) => [name2, subset(child, `${path}.${name2}`)]
300
+ )
301
+ ) : nested.has(key) ? subset(value, path) : listed.has(key) ? value.map((child) => subset(child, path)) : value;
302
+ }
303
+ return kept;
304
+ }
305
+ function trackerDataSchema(schema) {
306
+ let json;
307
+ try {
308
+ json = z5.toJSONSchema(schema, {
309
+ target: "draft-2020-12",
310
+ io: "input",
311
+ unrepresentable: "throw",
312
+ cycles: "throw",
313
+ reused: "inline",
314
+ override: ({ zodSchema, path }) => {
315
+ const def = zodSchema._zod.def;
316
+ const at = ["data", ...path].join(".");
317
+ if (def.type === "pipe" || def.type === "transform") {
318
+ throw new Error(
319
+ `Tracker data schemas cannot transform values (${at}): records are stored as sent`
320
+ );
321
+ }
322
+ if (def.checks?.some((check) => check._zod.def.check === "custom")) {
323
+ throw new Error(
324
+ `Tracker data schemas cannot use refinements (${at}): check the value in your evaluator`
325
+ );
326
+ }
327
+ }
328
+ });
329
+ } catch (error) {
330
+ const message = error instanceof Error ? error.message : String(error);
331
+ throw new Error(
332
+ message.startsWith("Tracker data schemas") ? message : `Tracker data schemas describe JSON: ${message}. Use z.unknown() for any JSON value.`
333
+ );
334
+ }
335
+ const parsed = trackerDataSchemaSchema.safeParse(subset(json, "data"));
336
+ if (!parsed.success) {
337
+ throw new Error(
338
+ parsed.error.issues.map((issue) => issue.message).join("; ")
339
+ );
340
+ }
341
+ return parsed.data;
342
+ }
343
+ var trackerDataRecordSteps = 25e4;
344
+ var trackerDataBatchSteps = 6e6;
345
+ var BudgetSpent = class extends Error {
346
+ };
347
+ function charge(budget, steps) {
348
+ budget.steps -= steps;
349
+ if (budget.steps < 0) {
350
+ throw new BudgetSpent();
351
+ }
352
+ }
353
+ var maxKeyText = 64;
354
+ var maxPathText = 256;
355
+ function clip(text, limit) {
356
+ return text.length > limit ? text.slice(0, limit - 1) + "\u2026" : text;
357
+ }
358
+ function pathText(path) {
359
+ const keys = [];
360
+ for (let at = path; at; at = at.parent) {
361
+ keys.push(clip(String(at.key), maxKeyText));
362
+ }
363
+ return clip(["data", ...keys.reverse()].join("."), maxPathText);
364
+ }
365
+ var describe = (value) => value === null ? "null" : Array.isArray(value) ? "an array" : typeof value;
366
+ var shownValues = 10;
367
+ function oneOf(values) {
368
+ const shown = values.slice(0, shownValues).map((value) => JSON.stringify(value)).join(", ");
369
+ return values.length > shownValues ? `expected one of ${shown}, or ${values.length - shownValues} more` : `expected one of ${shown}`;
370
+ }
371
+ var enumSets = /* @__PURE__ */ new WeakMap();
372
+ var literalLists = /* @__PURE__ */ new WeakMap();
373
+ function setOf(owner, values) {
374
+ let found = enumSets.get(owner);
375
+ if (!found) {
376
+ found = new Set(values);
377
+ enumSets.set(owner, found);
378
+ }
379
+ return found;
380
+ }
381
+ function literalsOf(schema) {
382
+ let found = literalLists.get(schema);
383
+ if (!found) {
384
+ found = Object.entries(schema.properties ?? {}).filter(
385
+ ([, property]) => property.const !== void 0
386
+ );
387
+ literalLists.set(schema, found);
388
+ }
389
+ return found;
390
+ }
391
+ function matches(schema, value, at, budget) {
392
+ charge(budget, 1);
393
+ const issue = (reason) => ({ at, reason });
394
+ if (schema.const !== void 0 && value !== schema.const) {
395
+ return issue(() => `expected ${JSON.stringify(schema.const)}`);
396
+ }
397
+ if (schema.enum && !setOf(schema, schema.enum).has(value)) {
398
+ const values = schema.enum;
399
+ return issue(() => oneOf(values));
400
+ }
401
+ switch (schema.type) {
402
+ case "null":
403
+ if (value !== null) {
404
+ return issue(() => `expected null, got ${describe(value)}`);
405
+ }
406
+ break;
407
+ case "boolean":
408
+ case "string":
409
+ if (typeof value !== schema.type) {
410
+ const type = schema.type;
411
+ return issue(() => `expected a ${type}, got ${describe(value)}`);
412
+ }
413
+ break;
414
+ case "number":
415
+ if (typeof value !== "number") {
416
+ return issue(() => `expected a number, got ${describe(value)}`);
417
+ }
418
+ break;
419
+ case "integer":
420
+ if (!Number.isInteger(value)) {
421
+ return issue(
422
+ () => typeof value === "number" ? "expected an integer" : `expected an integer, got ${describe(value)}`
423
+ );
424
+ }
425
+ break;
426
+ case "array":
427
+ if (!Array.isArray(value)) {
428
+ return issue(() => `expected an array, got ${describe(value)}`);
429
+ }
430
+ break;
431
+ case "object":
432
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
433
+ return issue(() => `expected an object, got ${describe(value)}`);
434
+ }
435
+ break;
436
+ }
437
+ if (typeof value === "string") {
438
+ const { minLength, maxLength } = schema;
439
+ if (minLength !== void 0 && value.length < minLength) {
440
+ return issue(() => `expected at least ${minLength} characters`);
441
+ }
442
+ if (maxLength !== void 0 && value.length > maxLength) {
443
+ return issue(() => `expected at most ${maxLength} characters`);
444
+ }
445
+ }
446
+ if (typeof value === "number") {
447
+ const limits = [
448
+ [schema.minimum, (limit) => value >= limit, "at least"],
449
+ [schema.exclusiveMinimum, (limit) => value > limit, "more than"],
450
+ [schema.maximum, (limit) => value <= limit, "at most"],
451
+ [schema.exclusiveMaximum, (limit) => value < limit, "less than"]
452
+ ];
453
+ for (const [limit, holds, label] of limits) {
454
+ if (limit !== void 0 && !holds(limit)) {
455
+ return issue(() => `expected ${label} ${limit}`);
456
+ }
457
+ }
458
+ }
459
+ if (Array.isArray(value)) {
460
+ const { minItems, maxItems } = schema;
461
+ if (minItems !== void 0 && value.length < minItems) {
462
+ return issue(() => `expected at least ${minItems} items`);
463
+ }
464
+ if (maxItems !== void 0 && value.length > maxItems) {
465
+ return issue(() => `expected at most ${maxItems} items`);
466
+ }
467
+ if (schema.items) {
468
+ for (let index = 0; index < value.length; index++) {
469
+ const found = matches(
470
+ schema.items,
471
+ value[index],
472
+ { parent: at, key: index },
473
+ budget
474
+ );
475
+ if (found) {
476
+ return found;
477
+ }
478
+ }
479
+ }
480
+ }
481
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
482
+ const object = value;
483
+ const properties = schema.properties ?? {};
484
+ const required = schema.required ?? [];
485
+ charge(budget, required.length);
486
+ for (const key of required) {
487
+ if (!Object.hasOwn(object, key)) {
488
+ return issue(() => `missing required key "${clip(key, maxKeyText)}"`);
489
+ }
490
+ }
491
+ const literals = literalsOf(schema);
492
+ charge(budget, literals.length);
493
+ for (const [key, property] of literals) {
494
+ if (Object.hasOwn(object, key) && object[key] !== property.const) {
495
+ return {
496
+ at: { parent: at, key },
497
+ reason: () => `expected ${JSON.stringify(property.const)}`
498
+ };
499
+ }
500
+ }
501
+ const keys = Object.keys(object);
502
+ charge(budget, keys.length);
503
+ const names = schema.propertyNames?.enum;
504
+ const allowed = names && setOf(schema.propertyNames, names);
505
+ for (const key of keys) {
506
+ if (allowed && !allowed.has(key)) {
507
+ return {
508
+ at: { parent: at, key },
509
+ reason: () => "is not an allowed key"
510
+ };
511
+ }
512
+ const property = Object.hasOwn(properties, key) ? properties[key] : schema.additionalProperties;
513
+ if (property === false) {
514
+ return {
515
+ at: { parent: at, key },
516
+ reason: () => "is not an allowed key"
517
+ };
518
+ }
519
+ if (property && property !== true) {
520
+ const found = matches(
521
+ property,
522
+ object[key],
523
+ { parent: at, key },
524
+ budget
525
+ );
526
+ if (found) {
527
+ return found;
528
+ }
529
+ }
530
+ }
531
+ }
532
+ for (const branch of schema.allOf ?? []) {
533
+ const found = matches(branch, value, at, budget);
534
+ if (found) {
535
+ return found;
536
+ }
537
+ }
538
+ if (schema.anyOf && !schema.anyOf.some((branch) => !matches(branch, value, at, budget))) {
539
+ return issue(() => "matches none of the allowed shapes");
540
+ }
541
+ if (schema.oneOf) {
542
+ let count3 = 0;
543
+ for (const branch of schema.oneOf) {
544
+ if (!matches(branch, value, at, budget) && ++count3 > 1) {
545
+ return issue(() => "matches more than one of the allowed shapes");
546
+ }
547
+ }
548
+ if (!count3) {
549
+ return issue(() => "matches none of the allowed shapes");
550
+ }
551
+ }
552
+ return null;
553
+ }
554
+ function trackerDataIssue(schema, data, budget = { steps: trackerDataRecordSteps }) {
555
+ try {
556
+ const found = matches(schema, data, null, budget);
557
+ return found && {
558
+ kind: "mismatch",
559
+ path: pathText(found.at),
560
+ reason: found.reason()
561
+ };
562
+ } catch (error) {
563
+ if (error instanceof BudgetSpent) {
564
+ return {
565
+ kind: "too-complex",
566
+ path: "data",
567
+ reason: "is too complex to validate against the tracker's schema"
568
+ };
569
+ }
570
+ throw error;
571
+ }
572
+ }
573
+ function trackerDataIssues(schema, records) {
574
+ const batch = { steps: trackerDataBatchSteps };
575
+ return records.map((data) => {
576
+ const budget = { steps: Math.min(trackerDataRecordSteps, batch.steps) };
577
+ const allowance = budget.steps;
578
+ const found = trackerDataIssue(schema, data, budget);
579
+ batch.steps -= allowance - Math.max(budget.steps, 0);
580
+ return found;
581
+ });
582
+ }
583
+ function alternatives(schemas) {
584
+ return schemas.flatMap(
585
+ (s) => s.anyOf || s.oneOf || s.allOf ? alternatives([
586
+ ...s.anyOf ?? [],
587
+ ...s.oneOf ?? [],
588
+ ...s.allOf ?? []
589
+ ]) : [s]
590
+ );
591
+ }
592
+ var unconstrained = (s) => s.type === void 0 && s.properties === void 0 && s.const === void 0 && s.enum === void 0;
593
+ function trackerDataPathTypes(schema, path) {
594
+ const any = /* @__PURE__ */ new Set([
595
+ "string",
596
+ "number",
597
+ "boolean",
598
+ "null",
599
+ "object",
600
+ "array"
601
+ ]);
602
+ let current = [schema];
603
+ for (const key of path.split(".")) {
604
+ const next = [];
605
+ for (const s of alternatives(current)) {
606
+ if (unconstrained(s)) {
607
+ next.push({});
608
+ } else if (s.type !== "object") {
609
+ continue;
610
+ } else if (s.properties && Object.hasOwn(s.properties, key)) {
611
+ next.push(s.properties[key]);
612
+ } else if (s.additionalProperties === true) {
613
+ next.push({});
614
+ } else if (s.additionalProperties) {
615
+ next.push(s.additionalProperties);
616
+ }
617
+ }
618
+ if (!next.length) {
619
+ return null;
620
+ }
621
+ current = next;
622
+ }
623
+ const types = /* @__PURE__ */ new Set();
624
+ for (const s of alternatives(current)) {
625
+ if (unconstrained(s)) {
626
+ return any;
627
+ }
628
+ if (s.type) {
629
+ types.add(s.type === "integer" ? "number" : s.type);
630
+ }
631
+ for (const value of [
632
+ ...s.const !== void 0 ? [s.const] : [],
633
+ ...s.enum ?? []
634
+ ]) {
635
+ types.add(value === null ? "null" : typeof value);
636
+ }
637
+ }
638
+ return types;
639
+ }
640
+ function schemaCheckedReader(reader) {
641
+ return {
642
+ content: (reference, query) => reader.content(reference, query),
643
+ summary: (reference, query) => reader.summary(reference, query),
644
+ records: (async (reference, query) => {
645
+ const page = await reader.records(reference, query);
646
+ const source = reference.source;
647
+ const schema = source?.kind === "custom" ? source.data : void 0;
648
+ if (!schema) {
649
+ return page;
650
+ }
651
+ const issues = trackerDataIssues(
652
+ schema,
653
+ page.items.map((record2) => record2.data)
654
+ );
655
+ const items = page.items.filter((_, index) => !issues[index]);
656
+ return { ...page, items, excluded: page.items.length - items.length };
657
+ })
658
+ };
659
+ }
660
+ function whereSchemaIssue(schema, where) {
661
+ const conditions = where === void 0 ? [] : Array.isArray(where) ? where : [where];
662
+ for (const condition of conditions) {
663
+ const types = trackerDataPathTypes(schema, condition.path);
664
+ if (!types) {
665
+ return `The tracker filter reads data.${condition.path}, which the tracker's data schema does not declare`;
666
+ }
667
+ const wanted = "equals" in condition ? [typeof condition.equals] : ["number", "string"];
668
+ if (!wanted.some((type) => types.has(type))) {
669
+ return `The tracker filter compares data.${condition.path} with ${"equals" in condition ? JSON.stringify(condition.equals) : "a number"}, but the field holds ${[...types].join(" or ")}`;
670
+ }
671
+ }
672
+ return null;
673
+ }
674
+
675
+ // src/trackers.ts
676
+ import { z as z6 } from "zod";
677
+ var timestamp = z6.number().int().safe().nonnegative().max(864e13);
678
+ var count = z6.number().int().safe().nonnegative();
679
+ var externalId = z6.string().min(1).max(256);
680
+ var metric = count.nullable().default(null);
681
+ var xTweetSchema = z6.looseObject({
682
+ id: externalId,
683
+ userId: externalId,
684
+ content: z6.string(),
685
+ createdAt: z6.iso.datetime({ offset: true }),
686
+ author: z6.looseObject({
687
+ id: externalId,
688
+ username: z6.string(),
689
+ name: z6.string(),
690
+ verified: z6.boolean().nullable().default(null)
691
+ }),
692
+ likeCount: metric,
693
+ replyCount: metric,
694
+ retweetCount: metric,
695
+ quoteCount: metric,
696
+ viewCount: metric,
697
+ bookmarkCount: metric,
698
+ isReply: z6.boolean(),
699
+ isRetweet: z6.boolean(),
700
+ isQuoteTweet: z6.boolean()
701
+ });
702
+ var xContentBodySchema = z6.strictObject({
703
+ version: z6.literal(1),
704
+ id: z6.string().min(1),
705
+ authorId: z6.string().min(1),
706
+ publishedAt: timestamp,
707
+ text: z6.string(),
708
+ isReply: z6.boolean(),
709
+ isRetweet: z6.boolean(),
710
+ isQuoteTweet: z6.boolean(),
711
+ media: z6.array(z6.strictObject({ type: z6.string(), url: z6.string() })).nullable(),
712
+ mentionedAuthorIds: z6.array(z6.string().min(1)).nullable(),
713
+ videoLengthSeconds: z6.number().nonnegative().nullable(),
714
+ references: z6.strictObject({
715
+ replyId: z6.string().nullable(),
716
+ replyAuthorId: z6.string().nullable(),
717
+ quoteId: z6.string().nullable(),
718
+ quoteAuthorId: z6.string().nullable(),
719
+ repostId: z6.string().nullable(),
720
+ repostAuthorId: z6.string().nullable()
721
+ })
722
+ });
723
+ var trackerContentQuerySchema = z6.strictObject({
724
+ id: externalId,
725
+ observation: z6.string().regex(/^observation_[a-f0-9]{64}$/)
726
+ });
727
+ var trackerContentReadSchema = trackerContentQuerySchema.extend({
728
+ member: identifier
729
+ });
730
+ var attributionContext = { member: identifier, capturedAt: timestamp };
731
+ var trackerEvidenceSchema = z6.strictObject({
732
+ contentRevision: identifier,
733
+ observation: identifier
734
+ });
735
+ var trackerContentSchema = z6.strictObject({
736
+ tracker: identifier,
737
+ source: z6.literal("x"),
738
+ evidence: trackerEvidenceSchema,
739
+ content: xContentBodySchema,
740
+ observedAt: timestamp,
741
+ removed: z6.boolean(),
742
+ attribution: z6.discriminatedUnion("kind", [
743
+ z6.strictObject({
744
+ ...attributionContext,
745
+ kind: z6.literal("linked"),
746
+ account: z6.strictObject({
747
+ provider: z6.literal("x"),
748
+ issuer: z6.string().min(1),
749
+ subject: externalId,
750
+ revision: count,
751
+ linkedAt: timestamp.nullable()
752
+ })
753
+ }),
754
+ z6.strictObject({ ...attributionContext, kind: z6.literal("unlinked") }),
755
+ z6.strictObject({
756
+ ...attributionContext,
757
+ kind: z6.literal("different-author")
758
+ })
759
+ ])
760
+ });
761
+ var knownIdentityKinds = ["wallet", "x", "discord", "member"];
762
+ var appIdentityKindSchema = z6.templateLiteral([
763
+ "app:",
764
+ z6.string().regex(
765
+ /^[a-z0-9][a-z0-9_-]{0,39}$/,
766
+ "Name an app identity kind like app:telegram: lowercase letters, digits, _ or -, at most 40"
767
+ )
768
+ ]);
769
+ var identityKindSchema = z6.union([
770
+ z6.enum(knownIdentityKinds),
771
+ appIdentityKindSchema
772
+ ]);
773
+ var isAppIdentityKind = (kind) => kind.startsWith("app:");
774
+ var openIdentityKindSchema = z6.string().min(1).max(64);
775
+ var memberIdentitySchema = z6.object({
776
+ kind: openIdentityKindSchema,
777
+ /** The stable user ID for `x` and `discord`; the subject your app signed the member in with for `app:<name>`. */
778
+ subject: externalId,
779
+ /**
780
+ * The link's revision. It grows when the member selects another X or Discord account, or on
781
+ * each app identity unlink and relink. App identities never move between members.
782
+ */
783
+ revision: count,
784
+ /** The latest link time, refreshed on app identity relink; null when the link time is unknown. */
785
+ linkedAt: timestamp.nullable()
786
+ });
787
+ var accountRoleSchema = z6.string().regex(
788
+ /^[a-zA-Z][a-zA-Z0-9_]{0,39}$/,
789
+ "Name roles like author or recipient: a letter, then letters, digits or underscores"
790
+ );
791
+ var xAccountRoles = ["author", "inReplyTo"];
792
+ var distinct = (values) => new Set(values).size === values.length;
793
+ var contentMetricNameSchema = z6.string().regex(
794
+ /^[a-z][a-zA-Z0-9]{0,39}$/,
795
+ "Name metrics like likes or watchTime: a lowercase letter, then letters or digits"
796
+ );
797
+ var xContentMetrics = [
798
+ "likes",
799
+ "replies",
800
+ "reposts",
801
+ "quotes",
802
+ "views",
803
+ "bookmarks"
804
+ ];
805
+ var customContentSchema = z6.strictObject({
806
+ metrics: z6.array(contentMetricNameSchema).max(10).refine(distinct, "List each metric once")
807
+ });
808
+ var xSearchSourceSchema = z6.object({
809
+ kind: z6.literal("x-search"),
810
+ query: z6.string().trim().min(1).max(2e3)
811
+ }).strict();
812
+ var customSourceSchema = z6.object({
813
+ kind: z6.literal("custom"),
814
+ namespace: identifier,
815
+ /**
816
+ * The identity kinds a record's author and named accounts can be, attributed to members
817
+ * through verified links: `wallet`, `x`, `discord`, `member`, or your app's own `app:<name>`.
818
+ * Omitted when authors are opaque IDs, which no quest can pay.
819
+ */
820
+ identities: z6.array(identityKindSchema).min(1).max(8).refine(distinct, "List each identity kind once").optional(),
821
+ /** Roles of the named accounts records can carry besides their author, such as `recipient`. */
822
+ accounts: z6.array(accountRoleSchema).min(1).max(10).refine(distinct, "List each account role once").refine(
823
+ (roles) => !roles.includes("author"),
824
+ "author is every record's own role; name other accounts"
825
+ ).optional(),
826
+ /**
827
+ * The schema every record's `data` matches, which ingestion enforces. `customSource()`
828
+ * requires it. Trackers published before typed data have none, and take no records until
829
+ * they are published with one.
830
+ */
831
+ data: trackerDataSchemaSchema.optional(),
832
+ /**
833
+ * The content its records carry: each record's `data` is `{ body, metrics? }`, and quests can
834
+ * use the tracker with `content()`. `customSource(namespace, { content })` sets it with the
835
+ * matching `data` schema.
836
+ */
837
+ content: customContentSchema.optional()
838
+ }).strict().refine(
839
+ (source) => !source.content || source.data?.properties?.body?.type === "object" && (source.data.required ?? []).includes("body"),
840
+ "A content source's data schema has a required object body"
841
+ ).refine(
842
+ (source) => !source.accounts || source.identities,
843
+ "Named accounts need identities"
844
+ );
845
+ var trackerSourceSchema = z6.discriminatedUnion("kind", [
846
+ xSearchSourceSchema,
847
+ customSourceSchema,
848
+ discordMessagesSourceSchema,
849
+ discordReactionsSourceSchema
850
+ ]);
851
+ var trackerSourceKinds = [
852
+ "x-search",
853
+ "custom",
854
+ "discord-messages",
855
+ "discord-reactions"
856
+ ];
857
+ function sourceIdentities(source) {
858
+ if (!isKnownTrackerSource(source)) {
859
+ return void 0;
860
+ }
861
+ switch (source.kind) {
862
+ case "x-search":
863
+ return ["x"];
864
+ case "discord-messages":
865
+ case "discord-reactions":
866
+ return ["discord"];
867
+ case "custom":
868
+ return source.identities;
869
+ }
870
+ }
871
+ function sourceContent(source) {
872
+ switch (source.kind) {
873
+ case "x-search":
874
+ return { metrics: xContentMetrics };
875
+ case "custom":
876
+ return source.content;
877
+ case "discord-messages":
878
+ case "discord-reactions":
879
+ return void 0;
880
+ }
881
+ }
882
+ var windowSchema = z6.object({ start: timestamp, end: timestamp.optional() }).strict().refine(
883
+ (w) => w.end === void 0 || w.end > w.start,
884
+ "End must follow start"
885
+ );
886
+ var trackerDefinitionSchema = z6.object({
887
+ key: identifier,
888
+ title: z6.string().trim().min(1).max(120),
889
+ source: trackerSourceSchema,
890
+ window: windowSchema,
891
+ refreshSeconds: z6.number().int().min(300).max(86400).default(21600),
892
+ maxPages: z6.number().int().min(1).max(1e3).default(60)
893
+ }).strict();
894
+ var trackerArtifactSchema = z6.union([
895
+ trackerDefinitionSchema,
896
+ z6.object({ code: z6.string().min(1).max(2e6) }).strict()
897
+ ]);
898
+ var knownTrackerSourceResponseSchema = z6.discriminatedUnion("kind", [
899
+ z6.object(xSearchSourceSchema.shape),
900
+ z6.object({
901
+ ...customSourceSchema.shape,
902
+ identities: z6.array(openIdentityKindSchema).optional()
903
+ }),
904
+ z6.object(discordMessagesSourceSchema.shape),
905
+ z6.object(discordReactionsSourceSchema.shape)
906
+ ]);
907
+ var trackerSourceResponseSchema = z6.union([
908
+ knownTrackerSourceResponseSchema,
909
+ z6.object({
910
+ kind: z6.string().min(1).refine(
911
+ (kind) => !trackerSourceKinds.some((known) => known === kind),
912
+ "Known source kinds must match their schema"
913
+ )
914
+ }).catchall(z6.json())
915
+ ]);
916
+ function isKnownTrackerSource(source) {
917
+ return knownTrackerSourceResponseSchema.safeParse(source).success;
918
+ }
919
+ var trackerDefinitionResponseSchema = z6.object({
920
+ ...trackerDefinitionSchema.shape,
921
+ source: trackerSourceResponseSchema,
922
+ window: z6.object(windowSchema.shape)
923
+ });
924
+ var publishedTrackerSchema = z6.object({
925
+ id: identifier,
926
+ version: identifier,
927
+ definition: trackerDefinitionResponseSchema,
928
+ publishedAt: timestamp,
929
+ actor: z6.string().nullable()
930
+ });
931
+ var trackerStatusSchema = z6.object({
932
+ archivedAt: z6.number().int().nonnegative().nullable().optional(),
933
+ published: publishedTrackerSchema,
934
+ paused: z6.boolean(),
935
+ state: z6.enum(["idle", "syncing", "error", "complete"]),
936
+ lastStartedAt: timestamp.nullable(),
937
+ lastCompletedAt: timestamp.nullable(),
938
+ nextSyncAt: timestamp.nullable(),
939
+ coverage: z6.enum(["unknown", "partial", "complete"]),
940
+ error: z6.string().nullable(),
941
+ records: count
942
+ });
943
+ var trackerControlSchema = z6.object({
944
+ actionId: identifier,
945
+ action: z6.enum(["pause", "resume", "refresh"])
946
+ }).strict();
947
+ var trackerAccountSchema = z6.strictObject({
948
+ kind: identityKindSchema.optional(),
949
+ id: externalId
950
+ });
951
+ var trackerRecordInputSchema = z6.object({
952
+ id: externalId,
953
+ occurredAt: timestamp,
954
+ observedAt: timestamp,
955
+ author: z6.object({
956
+ id: externalId,
957
+ verified: z6.boolean().nullable().default(null),
958
+ /** The author's identity kind; needed when the source names more than one. */
959
+ kind: identityKindSchema.optional()
960
+ }).strict().nullable().default(null),
961
+ /** Named accounts besides the author, by the roles the custom source declares. */
962
+ accounts: z6.record(accountRoleSchema, trackerAccountSchema).refine(
963
+ (accounts) => Object.keys(accounts).length <= 10,
964
+ "At most 10 accounts"
965
+ ).optional(),
966
+ data: z6.record(z6.string(), z6.json()),
967
+ removed: z6.boolean().default(false)
968
+ }).strict().refine(
969
+ (v) => new TextEncoder().encode(JSON.stringify(v.data)).byteLength <= 131072,
970
+ "Record exceeds 128 KB"
971
+ );
972
+ var trackerRecordAccountSchema = z6.object({
973
+ kind: openIdentityKindSchema.optional(),
974
+ id: z6.string()
975
+ });
976
+ var trackerRecordSchema = z6.object({
977
+ id: z6.string(),
978
+ occurredAt: timestamp,
979
+ observedAt: timestamp,
980
+ author: z6.object({
981
+ id: z6.string(),
982
+ verified: z6.boolean().nullable().default(null),
983
+ kind: openIdentityKindSchema.optional()
984
+ }).nullable().default(null),
985
+ accounts: z6.record(z6.string(), trackerRecordAccountSchema).optional(),
986
+ data: z6.record(z6.string(), z6.json()),
987
+ removed: z6.boolean().default(false),
988
+ source: z6.string(),
989
+ firstSeenAt: timestamp,
990
+ /** Present only when includeEvidence is true; custom sources have no X evidence. */
991
+ evidence: trackerEvidenceSchema.nullable().optional()
992
+ });
993
+ var trackerIngestSchema = z6.object({
994
+ actionId: identifier,
995
+ records: z6.array(trackerRecordInputSchema).min(1).max(100)
996
+ }).strict();
997
+ var trackerIngestResultSchema = z6.object({
998
+ stored: count,
999
+ /** Tracker-trigger decisions this ingest caused. Absent from servers without tracker triggers. */
1000
+ admissions: z6.object({
1001
+ admitted: count,
1002
+ skipped: count,
1003
+ /**
1004
+ * Observations a quest's firing mode selected but its `where` filter did not match, counted
1005
+ * per quest like `admitted` and `skipped`. They record no outcome. Present only when
1006
+ * nonzero.
1007
+ */
1008
+ filtered: count.optional()
1009
+ }).optional()
1010
+ });
1011
+ var trackerOutcomeFields = {
1012
+ /** Stable quest ID. */
1013
+ quest: identifier,
1014
+ /** Stable tracker ID. */
1015
+ tracker: identifier,
1016
+ record: externalId,
1017
+ observedAt: timestamp,
1018
+ /** The release admitted, or the one active when the observation was skipped. */
1019
+ release: identifier,
1020
+ /** The account attribution resolved or failed to resolve, such as a CAIP-10 wallet ID. */
1021
+ account: z6.string().nullable(),
1022
+ createdAt: timestamp,
1023
+ updatedAt: timestamp,
1024
+ /** Null for automatic decisions; the staff actor after a retry. */
1025
+ actor: z6.string().nullable()
1026
+ };
1027
+ var trackerSkipCodes = [
1028
+ /** The quest is paused or no longer active. Catch-up after a pause is an operator decision. */
1029
+ "quest-paused",
1030
+ /** The record occurred before the quest was published, and the quest counts from activation. */
1031
+ "before-activation",
1032
+ /** The record occurred outside the tracker's window. */
1033
+ "outside-window",
1034
+ /** The record's occurrence time is later than the decision. */
1035
+ "future-record",
1036
+ /** The record is marked removed. */
1037
+ "record-removed",
1038
+ /**
1039
+ * The record's data does not match the tracker's current data schema, such as a record stored
1040
+ * before the schema changed. Staff can retry it once the schema accepts the data.
1041
+ */
1042
+ "invalid-record-data",
1043
+ /** The captured body of this observation cannot be read. */
1044
+ "content-unavailable",
1045
+ /** The record has no account in the beneficiary role, such as a post that is not a reply. */
1046
+ "no-account",
1047
+ /**
1048
+ * The beneficiary account is the record's author account, such as a reply to oneself, or both
1049
+ * belong to the same member. A different account is judged once it resolves to a member, after
1050
+ * `unlinked-account` and `ambiguous-account`.
1051
+ */
1052
+ "beneficiary-is-author",
1053
+ /** No member has verified the beneficiary account. Decided again when a member links it. */
1054
+ "unlinked-account",
1055
+ /**
1056
+ * More than one member has the beneficiary account. Decided again when a conflicting link is
1057
+ * removed.
1058
+ */
1059
+ "ambiguous-account",
1060
+ /** The attributed member has not joined the project. Decided again when the member joins. */
1061
+ "not-joined",
1062
+ /** The quest completes once, or pays one streak milestone, and the member already has it. */
1063
+ "already-completed",
1064
+ /**
1065
+ * The quest requires enrollment and the member has not enrolled. Decided again when the member
1066
+ * enrolls.
1067
+ */
1068
+ "not-enrolled",
1069
+ /** The record occurred before the member enrolled, and the quest counts from enrollment. */
1070
+ "before-enrollment",
1071
+ /**
1072
+ * The record occurred before the member linked the account it pays (an unknown link time counts
1073
+ * as before) or before the member enrolled, and the quest's `historical` policy has not released
1074
+ * it. A reviewer's retry releases it; under `historical: "claim"`, so does the member's claim.
1075
+ */
1076
+ "historical",
1077
+ /** A prerequisite quest was not complete when the record occurred. */
1078
+ "prerequisites-incomplete"
1079
+ ];
1080
+ var trackerOutcomeSchema = z6.discriminatedUnion("state", [
1081
+ z6.strictObject({
1082
+ ...trackerOutcomeFields,
1083
+ state: z6.literal("admitted"),
1084
+ code: z6.null(),
1085
+ reason: z6.null(),
1086
+ /** The attributed member. */
1087
+ member: identifier,
1088
+ /** The admitted attempt. Its evaluation, decision and rewards live on the attempt. */
1089
+ attempt: identifier
1090
+ }),
1091
+ z6.strictObject({
1092
+ ...trackerOutcomeFields,
1093
+ state: z6.literal("skipped"),
1094
+ /** Why the observation was skipped, as one of `trackerSkipCodes`. */
1095
+ code: z6.string().min(1),
1096
+ /** Why the observation was skipped, for people. */
1097
+ reason: z6.string(),
1098
+ /** The attributed member, when attribution got that far. */
1099
+ member: identifier.nullable(),
1100
+ attempt: identifier.nullable()
1101
+ })
1102
+ ]);
1103
+ var trackerOutcomeQuerySchema = z6.strictObject({
1104
+ /** Quest key or ID. */
1105
+ quest: identifier.optional(),
1106
+ record: externalId.optional(),
1107
+ member: identifier.optional(),
1108
+ state: z6.enum(["admitted", "skipped"]).optional(),
1109
+ /** Only skips with this code, such as `unlinked-account`. */
1110
+ code: z6.string().min(1).max(100).optional(),
1111
+ limit: z6.coerce.number().int().min(1).max(100).default(25),
1112
+ /** Opaque cursor from `next`: older outcomes. */
1113
+ before: z6.string().max(512).optional()
1114
+ });
1115
+ var trackerOutcomePageSchema = z6.strictObject({
1116
+ /** Newest first. */
1117
+ items: z6.array(trackerOutcomeSchema).max(100),
1118
+ next: z6.string().nullable()
1119
+ });
1120
+ var trackerOutcomeRetrySchema = z6.strictObject({
1121
+ actionId: identifier,
1122
+ /** Quest key or ID. */
1123
+ quest: identifier,
1124
+ record: externalId,
1125
+ observedAt: timestamp
1126
+ });
1127
+ var booleanQuery = z6.union([
1128
+ z6.boolean(),
1129
+ z6.enum(["true", "false"]).transform((v) => v === "true")
1130
+ ]);
1131
+ var trackerQuerySchema = z6.object({
1132
+ author: externalId.optional(),
1133
+ member: identifier.optional(),
1134
+ verified: booleanQuery.optional(),
1135
+ since: z6.coerce.number().int().safe().nonnegative().optional(),
1136
+ until: z6.coerce.number().int().safe().nonnegative().optional(),
1137
+ removed: booleanQuery.default(false),
1138
+ minLikes: z6.coerce.number().int().safe().nonnegative().optional(),
1139
+ minViews: z6.coerce.number().int().safe().nonnegative().optional(),
1140
+ limit: z6.coerce.number().int().min(1).max(100).default(25),
1141
+ cursor: z6.string().max(2048).optional(),
1142
+ includeEvidence: booleanQuery.optional()
1143
+ }).strict().refine(
1144
+ (q) => q.since === void 0 || q.until === void 0 || q.until > q.since,
1145
+ "Until must follow since"
1146
+ );
1147
+ var trackerPageSchema = z6.object({
1148
+ tracker: identifier,
1149
+ items: z6.array(trackerRecordSchema),
1150
+ nextCursor: z6.string().nullable(),
1151
+ total: count,
1152
+ status: trackerStatusSchema
1153
+ });
1154
+ var trackerSummarySchema = z6.object({
1155
+ records: count,
1156
+ authors: count,
1157
+ metrics: z6.object({
1158
+ likes: count,
1159
+ replies: count,
1160
+ reposts: count,
1161
+ quotes: count,
1162
+ views: count,
1163
+ bookmarks: count
1164
+ }),
1165
+ missingMetrics: count,
1166
+ status: trackerStatusSchema
1167
+ });
1168
+ var trackerPreviewLimits = {
1169
+ pages: 3,
1170
+ posts: 100,
1171
+ days: 30
1172
+ };
1173
+ var trackerPreviewInputSchema = z6.object({
1174
+ query: xSearchSourceSchema.shape.query,
1175
+ /** Start of the searched window. The window ends when the sample is fetched. */
1176
+ since: timestamp
1177
+ }).strict();
1178
+ var trackerPreviewSchema = z6.object({
1179
+ query: z6.string(),
1180
+ since: timestamp,
1181
+ fetchedAt: timestamp,
1182
+ pages: count,
1183
+ /** Every match in the sample, newest first, verified or not. */
1184
+ posts: z6.array(xTweetSchema).max(trackerPreviewLimits.posts),
1185
+ /** X had more matches than the sample holds. */
1186
+ more: z6.boolean()
1187
+ });
1188
+
1189
+ // src/content.ts
1190
+ import { z as z7 } from "zod";
1191
+ var contentQualificationDecisionSchema = z7.strictObject({
1192
+ kind: z7.enum([
1193
+ "accept",
1194
+ "reject",
1195
+ "review",
1196
+ "defer",
1197
+ "progress",
1198
+ "superseded"
1199
+ ]),
1200
+ reason: z7.string().nullable()
1201
+ });
1202
+ var contentQualificationQuerySchema = z7.strictObject({
1203
+ quest: identifier,
1204
+ member: identifier.optional(),
1205
+ /** A content item's record ID in the quest's tracker. */
1206
+ content: z7.string().min(1).max(256).optional(),
1207
+ cursor: pageCursorSchema.optional()
1208
+ });
1209
+ var contentQualificationSchema = z7.strictObject({
1210
+ quest: identifier,
1211
+ /** The content item's record ID in the quest's tracker. */
1212
+ content: z7.string(),
1213
+ member: identifier,
1214
+ release: identifier,
1215
+ attempt: identifier,
1216
+ revision: identifier,
1217
+ observation: identifier,
1218
+ current: z7.boolean(),
1219
+ state: z7.enum([
1220
+ "pending",
1221
+ "qualified",
1222
+ "unqualified",
1223
+ "needs-review",
1224
+ "failed",
1225
+ "superseded",
1226
+ "stale",
1227
+ "blocked",
1228
+ "unavailable"
1229
+ ]),
1230
+ reason: z7.string().nullable(),
1231
+ reward: z7.strictObject({
1232
+ attempt: identifier.nullable(),
1233
+ completion: identifier.nullable(),
1234
+ state: z7.enum(["unresolved", "awarded", "excluded"])
1235
+ })
1236
+ });
1237
+ var contentQualificationPageSchema = z7.strictObject({
1238
+ items: z7.array(contentQualificationSchema),
1239
+ nextCursor: pageCursorSchema.nullable()
1240
+ });
1241
+ var contentMetricSchema = contentMetricNameSchema;
1242
+ var contentMetricsSchema = z7.record(
1243
+ contentMetricSchema,
1244
+ z7.number().int().safe().nonnegative()
1245
+ );
1246
+ var contentPerformancePolicySchema = z7.strictObject({
1247
+ metrics: z7.array(contentMetricSchema).min(1).max(10).refine(
1248
+ (values) => new Set(values).size === values.length,
1249
+ "Metrics must be unique"
1250
+ ),
1251
+ maxAgeMs: z7.number().int().positive().max(864e5).default(36e5)
1252
+ });
1253
+
1254
+ // src/counters.ts
1255
+ import { z as z8 } from "zod";
1256
+ var day = 864e5;
1257
+ var counterGoalSchema = z8.object({
1258
+ kind: z8.literal("count"),
1259
+ count: z8.number().int().min(1).max(1e4)
1260
+ }).strict();
1261
+ var counterWindowSchema = z8.discriminatedUnion("kind", [
1262
+ z8.object({ kind: z8.literal("lifetime") }).strict(),
1263
+ z8.object({
1264
+ kind: z8.literal("calendar"),
1265
+ period: z8.enum(["day", "week", "month"]),
1266
+ latenessMs: z8.number().int().min(0).max(90 * day).default(7 * day)
1267
+ }).strict(),
1268
+ z8.object({
1269
+ kind: z8.literal("rolling"),
1270
+ durationMs: z8.number().int().min(1).max(365 * day)
1271
+ }).strict()
1272
+ ]);
1273
+ var counterPolicySchema = z8.object({
1274
+ kind: z8.literal("progress"),
1275
+ goal: counterGoalSchema,
1276
+ window: counterWindowSchema,
1277
+ repeat: z8.enum(["once", "repeat"]).default("once")
1278
+ }).strict();
1279
+ var achievementBase = z8.object({
1280
+ id: identifier,
1281
+ ordinal: z8.number().int().positive(),
1282
+ achievedAt: z8.number().int(),
1283
+ window: z8.string()
1284
+ });
1285
+ var counterAchievementSchema = z8.discriminatedUnion("status", [
1286
+ achievementBase.extend({
1287
+ status: z8.literal("revoked"),
1288
+ completion: identifier,
1289
+ revokedAt: z8.number().int()
1290
+ }),
1291
+ achievementBase.extend({
1292
+ status: z8.literal("awarded"),
1293
+ completion: identifier
1294
+ }),
1295
+ achievementBase.extend({
1296
+ status: z8.literal("budget-exhausted"),
1297
+ budget: identifier
1298
+ })
1299
+ ]);
1300
+ var counterProgressSchema = z8.object({
1301
+ goal: z8.number().int().positive(),
1302
+ current: z8.number().int().nonnegative(),
1303
+ window: z8.object({
1304
+ key: z8.string(),
1305
+ start: z8.number().int().nullable(),
1306
+ end: z8.number().int().nullable()
1307
+ }),
1308
+ repeat: z8.enum(["once", "repeat"]),
1309
+ settled: z8.number().int().nonnegative(),
1310
+ latest: counterAchievementSchema.nullable()
1311
+ });
1312
+ var counterContributionSchema = z8.object({
1313
+ id: identifier,
1314
+ distinct: z8.string(),
1315
+ attempt: identifier,
1316
+ occurredAt: z8.number().int(),
1317
+ recordedAt: z8.number().int(),
1318
+ window: z8.string(),
1319
+ status: z8.enum(["counted", "late", "future", "excluded"]),
1320
+ achievement: counterAchievementSchema.nullable(),
1321
+ reason: z8.string().nullable()
1322
+ });
1323
+ var counterHistorySchema = z8.object({
1324
+ items: z8.array(counterContributionSchema),
1325
+ nextCursor: z8.string().nullable()
1326
+ });
1327
+ var counterModerationSchema = z8.object({
1328
+ actionId: z8.uuid(),
1329
+ excluded: z8.boolean(),
1330
+ reason: z8.string().trim().min(1).max(2e3)
1331
+ }).strict();
1332
+ var counterHistoryQuerySchema = z8.object({
1333
+ cursor: z8.string().max(2e3).optional(),
1334
+ limit: z8.coerce.number().int().min(1).max(100).optional()
1335
+ }).strict();
1336
+ var counterModerationResultSchema = z8.object({ excluded: z8.boolean() });
1337
+
1338
+ // src/calendar.ts
1339
+ import { z as z9 } from "zod";
1340
+ var timestamp2 = z9.number().int().safe();
1341
+ var fixedOffset = /^(?:[+-]|(?:Etc\/)?GMT[+-]\d|(?:EST|MST|HST)$)/i;
1342
+ function canonicalTimeZone(zone) {
1343
+ let resolved;
1344
+ try {
1345
+ resolved = new Intl.DateTimeFormat("en", {
1346
+ timeZone: zone
1347
+ }).resolvedOptions().timeZone;
1348
+ } catch {
1349
+ return null;
1350
+ }
1351
+ if (resolved === "UTC") {
1352
+ return "UTC";
1353
+ }
1354
+ return fixedOffset.test(zone) || fixedOffset.test(resolved) ? null : resolved;
1355
+ }
1356
+ var timeZoneSchema = z9.string().min(1).max(100).transform((zone, ctx) => {
1357
+ const canonical = canonicalTimeZone(zone);
1358
+ if (canonical === null) {
1359
+ ctx.addIssue({
1360
+ code: "custom",
1361
+ message: fixedOffset.test(zone) ? "Use a named IANA timezone, such as Europe/Budapest or UTC. Fixed offsets have no daylight-saving rules." : "Use an IANA timezone name, such as Europe/Budapest or UTC"
1362
+ });
1363
+ return z9.NEVER;
1364
+ }
1365
+ return canonical;
1366
+ });
1367
+ var timeZoneNameSchema = z9.string().min(1).max(100);
1368
+ var movedTimeZone = (what) => `${what} no longer take a timeZone: they follow the project calendar. Set calendar.timeZone in relay.json or in Console settings.`;
1369
+ var record = (value) => typeof value === "object" && value !== null;
1370
+ function refuseStreakTimeZone(value, ctx) {
1371
+ if (record(value) && value.kind === "streak" && "timeZone" in value) {
1372
+ ctx.addIssue({
1373
+ code: "custom",
1374
+ path: ["timeZone"],
1375
+ message: movedTimeZone("Streaks")
1376
+ });
1377
+ }
1378
+ return value;
1379
+ }
1380
+ function refuseWindowTimeZone(value, ctx) {
1381
+ const window = record(value) ? value.window : void 0;
1382
+ if (record(window) && window.kind === "calendar" && "timeZone" in window) {
1383
+ ctx.addIssue({
1384
+ code: "custom",
1385
+ path: ["window", "timeZone"],
1386
+ message: movedTimeZone("Calendar leaderboard windows")
1387
+ });
1388
+ }
1389
+ return value;
1390
+ }
1391
+ var calendarPeriodSchema = z9.enum(["lifetime", "day", "week", "month"]);
1392
+ var projectCalendarSchema = z9.object({
1393
+ /** The timezone of the current calendar day. */
1394
+ timeZone: timeZoneNameSchema,
1395
+ /** The current calendar date, such as `2026-10-01`. */
1396
+ today: z9.string(),
1397
+ /** When the current calendar day ends, in epoch milliseconds. */
1398
+ nextBoundary: timestamp2,
1399
+ /** A change that takes effect at the next day boundary, or null. */
1400
+ pending: z9.object({ timeZone: timeZoneNameSchema, effectiveAt: timestamp2 }).nullable(),
1401
+ /** The `calendar.timeZone` the last deployment that declared one set, or null. */
1402
+ declared: timeZoneNameSchema.nullable(),
1403
+ /**
1404
+ * A stored timezone the calendar no longer accepts, such as a fixed offset a streak named before
1405
+ * v1. The calendar reads it as UTC until an operator chooses a timezone. Null otherwise.
1406
+ */
1407
+ unsupported: z9.string().nullable().default(null)
1408
+ });
1409
+ var projectCalendarInputSchema = z9.object({
1410
+ actionId: identifier,
1411
+ timeZone: timeZoneSchema,
1412
+ reason: z9.string().trim().min(1).max(500)
1413
+ }).strict();
1414
+ var projectCalendarDeclarationSchema = z9.object({ timeZone: timeZoneSchema }).strict();
1415
+
1416
+ // src/streaks.ts
1417
+ import { z as z10 } from "zod";
1418
+ var streakPolicySchema = z10.object({
1419
+ kind: z10.literal("streak"),
1420
+ days: z10.number().int().min(1).max(3650)
1421
+ });
1422
+ var streakProgressSchema = z10.object({
1423
+ goal: z10.number().int().positive(),
1424
+ current: z10.number().int().nonnegative(),
1425
+ best: z10.number().int().nonnegative(),
1426
+ today: z10.string(),
1427
+ todayQualified: z10.boolean(),
1428
+ timeZone: timeZoneNameSchema,
1429
+ nextBoundary: z10.number().int(),
1430
+ pendingTimeZone: z10.object({
1431
+ timeZone: timeZoneNameSchema,
1432
+ effectiveAt: z10.number().int()
1433
+ }).nullable(),
1434
+ days: z10.array(
1435
+ z10.object({
1436
+ day: z10.number().int(),
1437
+ date: z10.string(),
1438
+ // The zone the day was recorded in, as stored: days from before v1 can name a fixed offset.
1439
+ timeZone: z10.string(),
1440
+ occurredAt: z10.number().int()
1441
+ })
1442
+ ),
1443
+ milestone: z10.discriminatedUnion("status", [
1444
+ z10.object({ status: z10.literal("pending") }),
1445
+ z10.object({
1446
+ status: z10.literal("awarded"),
1447
+ completion: z10.string(),
1448
+ achievedAt: z10.number().int()
1449
+ }),
1450
+ z10.object({
1451
+ status: z10.literal("budget-exhausted"),
1452
+ budget: z10.string(),
1453
+ achievedAt: z10.number().int()
1454
+ })
1455
+ ])
1456
+ });
1457
+
1458
+ // src/tracker-triggers.ts
1459
+ import { z as z11 } from "zod";
1460
+ var timestamp3 = z11.number().int().safe().nonnegative().max(864e13);
1461
+ var count2 = z11.number().int().safe().nonnegative();
1462
+ var trackerTriggerModeSchema = z11.enum([
1463
+ "new-record",
1464
+ "new-observation",
1465
+ "data-changed"
1466
+ ]);
1467
+ function defaultTriggerMode(source) {
1468
+ return source === "custom" ? "new-observation" : "new-record";
1469
+ }
1470
+ var trackerBoundSchema = z11.union([
1471
+ z11.number().finite(),
1472
+ z11.strictObject({ setting: z11.string().regex(/^[a-zA-Z][a-zA-Z0-9_]*$/) })
1473
+ ]);
1474
+ var dataPath = z11.string().max(200).regex(
1475
+ /^[^.\s]+(\.[^.\s]+)*$/,
1476
+ "Use dot-separated keys, such as metrics.likes"
1477
+ );
1478
+ var trackerConditionSchema = z11.union([
1479
+ z11.strictObject({
1480
+ path: dataPath,
1481
+ equals: z11.union([z11.string().max(1e3), z11.number().finite(), z11.boolean()])
1482
+ }),
1483
+ z11.strictObject({
1484
+ path: dataPath,
1485
+ gt: trackerBoundSchema.optional(),
1486
+ gte: trackerBoundSchema.optional(),
1487
+ lt: trackerBoundSchema.optional(),
1488
+ lte: trackerBoundSchema.optional()
1489
+ }).refine(
1490
+ (where) => [where.gt, where.gte, where.lt, where.lte].some(
1491
+ (bound2) => bound2 !== void 0
1492
+ ),
1493
+ "Compare with equals, gt, gte, lt or lte"
1494
+ )
1495
+ ]);
1496
+ var trackerWhereSchema = z11.union([
1497
+ trackerConditionSchema,
1498
+ z11.array(trackerConditionSchema).min(1).max(10)
1499
+ ]);
1500
+ function whereConditions(where) {
1501
+ return where === void 0 ? [] : Array.isArray(where) ? where : [where];
1502
+ }
1503
+ function whereSettings(where) {
1504
+ return whereConditions(where).flatMap(
1505
+ (condition) => "equals" in condition ? [] : [condition.gt, condition.gte, condition.lt, condition.lte].flatMap(
1506
+ (bound2) => typeof bound2 === "object" ? [bound2.setting] : []
1507
+ )
1508
+ );
1509
+ }
1510
+ var triggerEnrollmentSchema = z11.enum(["none", "required"]);
1511
+ var triggerSinceSchema = z11.enum(["activation", "window", "enrollment"]);
1512
+ var triggerHistoricalSchema = z11.enum(["staff", "claim", "automatic"]);
1513
+ var trackerTriggerPolicySchema = z11.strictObject({
1514
+ /** The tracker's authoring key; publication binds it to the tracker's stable ID. */
1515
+ tracker: identifier,
1516
+ /**
1517
+ * The tracker's source kind, one of `trackerSourceKinds` today. An open string, so readers of
1518
+ * releases keep parsing them when a later Relay adds a managed source.
1519
+ */
1520
+ source: z11.string().min(1).max(100),
1521
+ /** Which observations fire. */
1522
+ on: trackerTriggerModeSchema,
1523
+ where: trackerWhereSchema.optional(),
1524
+ /**
1525
+ * The record account the quest pays: `author`, `inReplyTo` for an X post, `messageAuthor` for a
1526
+ * Discord reaction, or a named account of a custom record. Relay attributes it through
1527
+ * verified links; evaluators cannot redirect it.
1528
+ */
1529
+ beneficiary: accountRoleSchema,
1530
+ /** Absent means `"none"`. */
1531
+ enrollment: triggerEnrollmentSchema.optional(),
1532
+ /** Absent means `"activation"`. */
1533
+ since: triggerSinceSchema.optional(),
1534
+ /** Absent means `"staff"`, or `"claim"` on a content quest. */
1535
+ historical: triggerHistoricalSchema.optional(),
1536
+ /**
1537
+ * A content quest (`content({ tracker })`): one completion per content item, a content stage
1538
+ * that re-evaluates edits and runs `performance`, firing on each new record and paying its
1539
+ * author.
1540
+ */
1541
+ content: z11.literal(true).optional()
1542
+ }).refine(
1543
+ (policy) => policy.since !== "enrollment" || policy.enrollment === "required",
1544
+ 'since: "enrollment" needs enrollment: "required"'
1545
+ );
1546
+ function triggerMode(policy) {
1547
+ return policy.on;
1548
+ }
1549
+ function triggerAdmission(policy) {
1550
+ return {
1551
+ enrollment: policy.enrollment ?? "none",
1552
+ since: policy.since ?? "activation",
1553
+ historical: policy.historical ?? (policy.content ? "claim" : "staff")
1554
+ };
1555
+ }
1556
+ function beneficiaryRole(policy) {
1557
+ return policy.beneficiary;
1558
+ }
1559
+ var xLink = {
1560
+ issuer: z11.string().min(1),
1561
+ /** The account's stable user ID. */
1562
+ subject: z11.string().min(1).max(256),
1563
+ /** The member's account selection revision. */
1564
+ revision: count2,
1565
+ /** When the member linked the account; null when unknown. */
1566
+ linkedAt: timestamp3.nullable()
1567
+ };
1568
+ var trackerAttributionSchema = z11.object({
1569
+ member: identifier,
1570
+ capturedAt: timestamp3,
1571
+ account: z11.union([
1572
+ z11.object({
1573
+ provider: z11.literal("wallet"),
1574
+ /** Canonical CAIP-10 account ID, as the record names it. */
1575
+ id: z11.string().min(5).max(256),
1576
+ /** The wallet link's revision. */
1577
+ revision: count2,
1578
+ /** When the member verified the wallet. */
1579
+ linkedAt: timestamp3.nullable()
1580
+ }),
1581
+ z11.object({ provider: z11.literal("x"), ...xLink }),
1582
+ z11.object({ provider: z11.literal("discord"), ...xLink }),
1583
+ z11.object({
1584
+ provider: z11.literal("member"),
1585
+ /** The member ID the record names. */
1586
+ id: identifier
1587
+ }),
1588
+ z11.object({
1589
+ /** Your app's identity kind, such as `app:telegram`. */
1590
+ provider: appIdentityKindSchema,
1591
+ /** The subject your app signed the member in with, as the record names it. */
1592
+ subject: z11.string().min(1).max(256),
1593
+ /** The identity's revision in the project. */
1594
+ revision: count2,
1595
+ /** When the identity was linked to the member. */
1596
+ linkedAt: timestamp3.nullable()
1597
+ }),
1598
+ /** A kind a later Relay adds. */
1599
+ z11.object({ provider: z11.string().min(1) })
1600
+ ])
1601
+ });
1602
+ var trackerTriggerRecordSchema = z11.object({
1603
+ id: z11.string().min(1).max(256),
1604
+ source: z11.string(),
1605
+ occurredAt: timestamp3,
1606
+ observedAt: timestamp3,
1607
+ firstSeenAt: timestamp3,
1608
+ author: z11.object({
1609
+ id: z11.string().min(1).max(256),
1610
+ verified: z11.boolean().nullable(),
1611
+ kind: openIdentityKindSchema.optional()
1612
+ }).nullable(),
1613
+ accounts: z11.record(accountRoleSchema, trackerRecordAccountSchema).optional(),
1614
+ data: z11.record(z11.string(), z11.json()),
1615
+ removed: z11.boolean()
1616
+ });
1617
+ var trackerContentStageSchema = z11.object({
1618
+ /** The body's revision: the hash of its canonical JSON. Edits make a new one. */
1619
+ revision: identifier,
1620
+ /** The captured observation that carried this body. */
1621
+ observation: identifier,
1622
+ /** The body: an X post's normalized body, or a custom record's `data.body`. */
1623
+ body: z11.record(z11.string(), z11.json())
1624
+ });
1625
+ var trackerTriggerContextSchema = z11.object({
1626
+ /** The tracker's stable ID. */
1627
+ tracker: identifier,
1628
+ /** The tracker's authoring key. */
1629
+ key: identifier,
1630
+ /** The record account the attempt pays, as the quest's release names it. */
1631
+ beneficiary: accountRoleSchema,
1632
+ record: trackerTriggerRecordSchema,
1633
+ /**
1634
+ * The content this observation carries, when the tracker's source declares content: its body,
1635
+ * the body's revision, and the captured observation. On a content quest's stage attempts, the
1636
+ * revision being evaluated.
1637
+ */
1638
+ content: trackerContentStageSchema.optional(),
1639
+ attribution: trackerAttributionSchema,
1640
+ /**
1641
+ * When the member enrolled in the quest. Present only on quests that require enrollment.
1642
+ */
1643
+ enrolledAt: timestamp3.optional()
1644
+ });
1645
+
1646
+ // src/completion.ts
1647
+ import { z as z12 } from "zod";
1648
+ var name = z12.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,199}$/);
1649
+ var completionPolicySchema = z12.discriminatedUnion("kind", [
1650
+ streakPolicySchema,
1651
+ counterPolicySchema,
1652
+ z12.object({ kind: z12.literal("once") }).strict(),
1653
+ z12.object({ kind: z12.literal("keyed") }).strict()
1654
+ ]);
1655
+ var completionKeySchema = z12.string().min(1).max(500);
1656
+ var budgetSchema = z12.object({
1657
+ id: name,
1658
+ scope: z12.enum(["member", "project"]),
1659
+ /**
1660
+ * The project calendar period of the attempt's eligibility time that one bucket covers:
1661
+ * `"day"`, `"week"` (ISO, starting on Monday) or `"month"` in the project timezone.
1662
+ * `"lifetime"` never resets.
1663
+ */
1664
+ period: calendarPeriodSchema,
1665
+ limit: z12.number().int().positive().max(Number.MAX_SAFE_INTEGER),
1666
+ cost: z12.union([
1667
+ z12.number().int().positive().max(Number.MAX_SAFE_INTEGER),
1668
+ z12.object({ balance: name }).strict()
1669
+ ])
1670
+ }).strict();
1671
+
1672
+ // src/integrations.ts
1673
+ import { z as z13 } from "zod";
1674
+ var evaluatorIntegrationProviderSchema = z13.enum(["discord", "x"]);
1675
+ var integrationProviderSchema = z13.enum(["discord"]);
1676
+ var discordServerSchema = z13.object({
1677
+ id: z13.string().regex(/^[0-9]{1,20}$/),
1678
+ name: z13.string().min(1),
1679
+ icon: z13.string().nullable()
1680
+ });
1681
+ var projectIntegrationSchema = z13.object({
1682
+ provider: integrationProviderSchema,
1683
+ configured: z13.boolean(),
1684
+ status: z13.enum(["disconnected", "ready", "attention"]),
1685
+ revision: z13.number().int().nonnegative(),
1686
+ server: discordServerSchema.nullable(),
1687
+ issue: z13.string().nullable(),
1688
+ connectedAt: z13.number().default(0)
1689
+ });
1690
+
1691
+ // src/submission-input.ts
1692
+ import { z as z14 } from "zod";
1693
+ var textOptionsSchema = z14.object({
1694
+ required: z14.boolean().default(true),
1695
+ minLength: z14.number().int().min(0).max(1e4).default(1),
1696
+ maxLength: z14.number().int().min(1).max(1e4).default(1e4)
1697
+ }).strict().refine(
1698
+ (v) => v.minLength <= v.maxLength,
1699
+ "minLength must not exceed maxLength"
1700
+ );
1701
+ var hostSchema = z14.string().min(1).max(253).refine((host) => {
1702
+ if (!/^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/i.test(host) || host.includes("..")) {
1703
+ return false;
1704
+ }
1705
+ try {
1706
+ const url = new URL(`https://${host}`);
1707
+ return url.hostname === host.toLowerCase() && !url.port && !url.username && !url.password && url.pathname === "/" && !url.search && !url.hash;
1708
+ } catch {
1709
+ return false;
1710
+ }
1711
+ }, "Use a hostname without a scheme, path, port, or wildcard");
1712
+ var urlOptionsSchema = z14.object({
1713
+ required: z14.boolean().default(true),
1714
+ allowedHosts: z14.array(hostSchema).min(1).max(100).optional()
1715
+ }).strict();
1716
+ var textEvidenceSchema = z14.object({ kind: z14.literal("text"), value: z14.string().max(1e4) }).strict();
1717
+ var urlEvidenceSchema = z14.object({ kind: z14.literal("url"), value: z14.string().max(2048) }).strict();
1718
+ var valueEvidenceSchema = z14.discriminatedUnion("kind", [
1719
+ textEvidenceSchema,
1720
+ urlEvidenceSchema
1721
+ ]);
1722
+ function validateSubmissionValue(input, contract) {
1723
+ const maximum = input.kind === "text" ? 1e4 : 2048;
1724
+ if (input.value.length > maximum) {
1725
+ return `Enter no more than ${maximum} characters`;
1726
+ }
1727
+ if (input.kind !== contract.input) {
1728
+ return `This quest requires ${contract.input} input`;
1729
+ }
1730
+ if (!input.value.trim()) {
1731
+ return contract.constraints.required ? "This field is required" : null;
1732
+ }
1733
+ if (contract.input === "text") {
1734
+ if (input.value.length < contract.constraints.minLength) {
1735
+ return `Enter at least ${contract.constraints.minLength} characters`;
1736
+ }
1737
+ if (input.value.length > contract.constraints.maxLength) {
1738
+ return `Enter no more than ${contract.constraints.maxLength} characters`;
1739
+ }
1740
+ return null;
1741
+ }
1742
+ const url = parseHttpUrl(input.value);
1743
+ if (!url) {
1744
+ return "Enter a valid HTTP or HTTPS URL without credentials";
1745
+ }
1746
+ if (contract.constraints.allowedHosts && !contract.constraints.allowedHosts.some(
1747
+ (host) => host.toLowerCase() === url.hostname.toLowerCase()
1748
+ )) {
1749
+ return `Use a URL hosted on: ${contract.constraints.allowedHosts.join(", ")}`;
1750
+ }
1751
+ return null;
1752
+ }
1753
+ function parseHttpUrl(value) {
1754
+ if (value !== value.trim() || /[\\\s]/.test(value) || !/^https?:\/\//i.test(value)) {
1755
+ return null;
1756
+ }
1757
+ try {
1758
+ const url = new URL(value);
1759
+ return ["http:", "https:"].includes(url.protocol) && !url.username && !url.password ? url : null;
1760
+ } catch {
1761
+ return null;
1762
+ }
1763
+ }
1764
+ function xPostId(value) {
1765
+ const url = parseHttpUrl(value);
1766
+ if (!url || url.port || ![
1767
+ "x.com",
1768
+ "www.x.com",
1769
+ "twitter.com",
1770
+ "www.twitter.com",
1771
+ "mobile.twitter.com"
1772
+ ].includes(url.hostname)) {
1773
+ return null;
1774
+ }
1775
+ return /^\/(?:[A-Za-z0-9_]+|i\/web)\/status\/([0-9]{1,20})\/?$/.exec(
1776
+ url.pathname
1777
+ )?.[1] ?? null;
1778
+ }
1779
+
1780
+ // src/quiz.ts
1781
+ import { z as z15 } from "zod";
1782
+ var quizId = z15.string().regex(/^[a-zA-Z0-9_-]+$/).max(100);
1783
+ var quizChoiceSchema = z15.object({ id: quizId, label: z15.string().trim().min(1).max(500) }).strict();
1784
+ var quizQuestionSchema = z15.object({
1785
+ id: quizId,
1786
+ prompt: z15.string().trim().min(1).max(1e3),
1787
+ choices: z15.array(quizChoiceSchema).min(2).max(8).refine(
1788
+ (choices) => new Set(choices.map((choice) => choice.id)).size === choices.length,
1789
+ "Choice IDs must be unique"
1790
+ )
1791
+ }).strict();
1792
+ var quizQuestionsSchema = z15.array(quizQuestionSchema).min(1).max(20).refine(
1793
+ (questions) => new Set(questions.map((question) => question.id)).size === questions.length,
1794
+ "Question IDs must be unique"
1795
+ );
1796
+ var quizContentSchema = z15.array(
1797
+ quizQuestionSchema.extend({ correct: quizId }).refine(
1798
+ (question) => question.choices.some((choice) => choice.id === question.correct),
1799
+ "Choose a correct answer from the available choices"
1800
+ )
1801
+ ).min(1).max(20).refine(
1802
+ (questions) => new Set(questions.map((question) => question.id)).size === questions.length,
1803
+ "Question IDs must be unique"
1804
+ );
1805
+
1806
+ // src/resources.ts
1807
+ import { z as z16 } from "zod";
1808
+ var resourceSourceSchema = z16.union([
1809
+ z16.strictObject({
1810
+ provider: z16.literal("domino"),
1811
+ resource: z16.literal("point-ledger")
1812
+ }),
1813
+ discordResourceSourceSchema
1814
+ ]);
1815
+ var resourceRequestSchema = z16.object({
1816
+ source: resourceSourceSchema,
1817
+ query: z16.string().max(100).optional(),
1818
+ cursor: z16.string().regex(/^\d{1,6}$/).optional(),
1819
+ ids: z16.array(z16.string().min(1).max(100)).max(50).optional()
1820
+ }).strict();
1821
+ var resourceOptionsSchema = z16.object({
1822
+ revision: z16.number().int(),
1823
+ options: z16.array(
1824
+ z16.object({
1825
+ id: z16.string(),
1826
+ label: z16.string(),
1827
+ description: z16.string().optional(),
1828
+ group: z16.string().optional(),
1829
+ disabledReason: z16.string().optional()
1830
+ })
1831
+ ),
1832
+ cursor: z16.string().nullable()
1833
+ });
1834
+
1835
+ // src/settings.ts
1836
+ import { z as z18 } from "zod";
1837
+
1838
+ // src/setting-values.ts
1839
+ import { z as z17 } from "zod";
1840
+ var settingInstant = z17.iso.datetime({ offset: true }).transform((value) => new Date(value).toISOString());
1841
+ var settingResourceId = z17.union([
1842
+ z17.literal(""),
1843
+ z17.string().regex(/^\S{1,200}$/)
1844
+ ]);
1845
+
1846
+ // src/settings.ts
1847
+ var base = { label: z18.string().min(1), description: z18.string().optional() };
1848
+ var settingFieldSchema = z18.discriminatedUnion("kind", [
1849
+ z18.object({
1850
+ ...base,
1851
+ kind: z18.literal("point-ledger"),
1852
+ default: identifier.or(z18.literal(""))
1853
+ }).strict(),
1854
+ z18.object({ ...base, kind: z18.literal("datetime"), default: settingInstant }).strict(),
1855
+ z18.object({
1856
+ ...base,
1857
+ kind: z18.literal("resource"),
1858
+ default: settingResourceId,
1859
+ source: resourceSourceSchema
1860
+ }).strict(),
1861
+ z18.object({ ...base, kind: z18.literal("quiz"), default: quizContentSchema }).strict(),
1862
+ z18.object({
1863
+ ...base,
1864
+ kind: z18.literal("text"),
1865
+ default: z18.string(),
1866
+ minLength: z18.number().int().nonnegative(),
1867
+ maxLength: z18.number().int().positive(),
1868
+ multiline: z18.boolean()
1869
+ }).strict(),
1870
+ z18.object({
1871
+ ...base,
1872
+ kind: z18.literal("integer"),
1873
+ default: z18.number().int(),
1874
+ min: z18.number().int(),
1875
+ max: z18.number().int()
1876
+ }).strict(),
1877
+ z18.object({ ...base, kind: z18.literal("boolean"), default: z18.boolean() }).strict(),
1878
+ z18.object({
1879
+ ...base,
1880
+ kind: z18.literal("choice"),
1881
+ default: z18.string(),
1882
+ options: z18.array(z18.string().min(1)).min(1)
1883
+ }).strict()
1884
+ ]);
1885
+ var settingsFieldsSchema = z18.record(
1886
+ z18.string().regex(/^[a-zA-Z][a-zA-Z0-9_]*$/),
1887
+ settingFieldSchema
1888
+ );
1889
+ var settingsValuesSchema = z18.record(
1890
+ z18.string(),
1891
+ z18.union([z18.string(), z18.number().finite(), z18.boolean(), quizContentSchema])
1892
+ );
1893
+ function parseSettings(fields, input) {
1894
+ const shape = {};
1895
+ for (const [key, field] of Object.entries(fields)) {
1896
+ switch (field.kind) {
1897
+ case "point-ledger":
1898
+ shape[key] = settingResourceId.default(field.default);
1899
+ break;
1900
+ case "datetime":
1901
+ shape[key] = settingInstant.default(field.default);
1902
+ break;
1903
+ case "resource":
1904
+ shape[key] = settingResourceId.default(field.default);
1905
+ break;
1906
+ case "quiz":
1907
+ shape[key] = quizContentSchema.default(field.default);
1908
+ break;
1909
+ case "text":
1910
+ shape[key] = z18.string().min(field.minLength).max(field.maxLength).default(field.default);
1911
+ break;
1912
+ case "integer":
1913
+ shape[key] = z18.number().int().min(field.min).max(field.max).default(field.default);
1914
+ break;
1915
+ case "boolean":
1916
+ shape[key] = z18.boolean().default(field.default);
1917
+ break;
1918
+ case "choice":
1919
+ shape[key] = z18.enum(field.options).default(field.default);
1920
+ break;
1921
+ }
1922
+ }
1923
+ return settingsValuesSchema.parse(z18.object(shape).strict().parse(input));
1924
+ }
1925
+ function missingResourceSettings(fields, values) {
1926
+ return Object.entries(fields).filter(
1927
+ ([key, field]) => (field.kind === "resource" || field.kind === "point-ledger") && !values[key]
1928
+ ).map(([key]) => key);
1929
+ }
1930
+ function compatibleSettingKinds(previous, next) {
1931
+ return previous.kind === next.kind || previous.kind === "resource" && previous.source.provider === "domino" && next.kind === "point-ledger" || next.kind === "resource" && next.source.provider === "domino" && previous.kind === "point-ledger" || previous.kind === "text" && (next.kind === "resource" || next.kind === "datetime" || next.kind === "point-ledger");
1932
+ }
1933
+
1934
+ // src/authoring-identity.ts
1935
+ var authoringIdentityShape = { key: identifier };
1936
+ function authoringKey(input) {
1937
+ if ("id" in input) {
1938
+ throw new Error("Authoring definitions use key, not id");
1939
+ }
1940
+ return identifier.parse(input.key);
1941
+ }
1942
+
1943
+ // src/campaigns.ts
1944
+ import { z as z19 } from "zod";
1945
+ var timestamp4 = z19.number().int().safe().nonnegative();
1946
+ var availabilityWindowSchema = z19.object({ from: timestamp4, until: timestamp4 }).strict().refine((window) => window.until > window.from, {
1947
+ message: "Window end must follow its start",
1948
+ path: ["until"]
1949
+ });
1950
+ var campaignDefinitionSchema = z19.object({
1951
+ key: identifier,
1952
+ title: z19.string().trim().min(1).max(120),
1953
+ window: availabilityWindowSchema.optional(),
1954
+ enrollment: z19.enum(["none", "required"]).default("none")
1955
+ }).strict();
1956
+ var campaignAuthoringSchema = campaignDefinitionSchema.omit({ key: true, title: true }).extend({
1957
+ ...authoringIdentityShape,
1958
+ title: z19.string().trim().min(1).max(120).optional()
1959
+ }).strict().transform((value) => {
1960
+ const normalized = value;
1961
+ return campaignDefinitionSchema.parse({
1962
+ ...normalized,
1963
+ title: value.title ?? normalized.key
1964
+ });
1965
+ });
1966
+ function defineCampaign(input) {
1967
+ return campaignAuthoringSchema.parse(input);
1968
+ }
1969
+ var campaignViewSchema = campaignDefinitionSchema.extend({
1970
+ enrolledAt: timestamp4.nullable(),
1971
+ withdrawnAt: timestamp4.nullable().default(null),
1972
+ withdrawalReason: z19.string().nullable().default(null)
1973
+ });
1974
+ var campaignEnrollmentInputSchema = z19.object({ actionId: identifier, campaign: identifier }).strict();
1975
+ var memberCampaignEnrollmentInputSchema = campaignEnrollmentInputSchema.extend({ member: identifier });
1976
+ var campaignWithdrawalInputSchema = campaignEnrollmentInputSchema;
1977
+ var memberCampaignWithdrawalInputSchema = campaignWithdrawalInputSchema.extend({
1978
+ member: identifier,
1979
+ reason: z19.string().trim().min(1).max(500)
1980
+ });
1981
+ var campaignEnrollmentSchema = z19.object({
1982
+ campaign: identifier,
1983
+ member: identifier,
1984
+ enrolledAt: timestamp4,
1985
+ withdrawnAt: timestamp4.nullable().default(null),
1986
+ withdrawalReason: z19.string().nullable().default(null)
1987
+ });
1988
+
1989
+ // src/resource-handle.ts
1990
+ import { z as z20 } from "zod";
1991
+ function resourceHandle(_kind, definition) {
1992
+ return definition;
1993
+ }
1994
+ var ledgerSettingSchema = identifier.or(z20.literal("")).brand();
1995
+ function ledgerKey(ledger) {
1996
+ return typeof ledger === "string" ? ledger : ledger.key;
1997
+ }
1998
+
1999
+ // src/groups.ts
2000
+ import { z as z21 } from "zod";
2001
+ var projectGroupSchema = z21.object({
2002
+ key: identifier,
2003
+ title: z21.string().trim().min(1).max(120)
2004
+ }).strict();
2005
+ var projectGroupAuthoringSchema = projectGroupSchema.omit({ key: true, title: true }).extend({
2006
+ ...authoringIdentityShape,
2007
+ title: z21.string().trim().min(1).max(120).optional()
2008
+ }).strict().transform((value) => {
2009
+ return projectGroupSchema.parse({
2010
+ ...value,
2011
+ title: value.title ?? value.key
2012
+ });
2013
+ });
2014
+ function defineGroup(input) {
2015
+ return resourceHandle("group", projectGroupAuthoringSchema.parse(input));
2016
+ }
2017
+ function projectGroupKey(group) {
2018
+ return identifier.parse(group.key);
2019
+ }
2020
+
2021
+ // src/prerequisites.ts
2022
+ import { z as z22 } from "zod";
2023
+ var amount = z22.number().int().safe().nonnegative();
2024
+ var threshold = amount.positive();
2025
+ var completionPrerequisiteSchema = z22.discriminatedUnion("scope", [
2026
+ z22.object({
2027
+ kind: z22.literal("completion"),
2028
+ quest: identifier,
2029
+ scope: z22.literal("ever")
2030
+ }).strict(),
2031
+ z22.object({
2032
+ kind: z22.literal("completion"),
2033
+ quest: identifier,
2034
+ scope: z22.literal("period"),
2035
+ period: calendarPeriodSchema.exclude(["lifetime"])
2036
+ }).strict()
2037
+ ]);
2038
+ var balancePrerequisiteSchema = z22.object({
2039
+ kind: z22.literal("balance"),
2040
+ balance: identifier,
2041
+ minimum: threshold
2042
+ }).strict();
2043
+ var groupPrerequisiteSchema = z22.object({ kind: z22.literal("group"), group: identifier, title: z22.string() }).strict();
2044
+ var prerequisiteSchema = z22.discriminatedUnion("kind", [
2045
+ completionPrerequisiteSchema,
2046
+ balancePrerequisiteSchema,
2047
+ groupPrerequisiteSchema
2048
+ ]);
2049
+ var missingPrerequisiteSchema = z22.union([
2050
+ z22.object({
2051
+ kind: z22.literal("completion"),
2052
+ quest: identifier,
2053
+ title: z22.string(),
2054
+ scope: z22.literal("ever")
2055
+ }),
2056
+ z22.object({
2057
+ kind: z22.literal("completion"),
2058
+ quest: identifier,
2059
+ title: z22.string(),
2060
+ scope: z22.literal("period"),
2061
+ period: calendarPeriodSchema.exclude(["lifetime"]),
2062
+ resetsAt: z22.number().int().safe()
2063
+ }),
2064
+ z22.object({
2065
+ kind: z22.literal("balance"),
2066
+ balance: identifier,
2067
+ title: z22.string(),
2068
+ minimum: threshold,
2069
+ current: amount
2070
+ }),
2071
+ z22.object({
2072
+ kind: z22.literal("group"),
2073
+ group: identifier,
2074
+ title: z22.string()
2075
+ })
2076
+ ]);
2077
+ function completed(quest, options = {}) {
2078
+ const reference = quest.key;
2079
+ return completionPrerequisiteSchema.parse({
2080
+ kind: "completion",
2081
+ quest: reference,
2082
+ scope: options.scope ?? "ever",
2083
+ ..."period" in options ? { period: options.period } : {}
2084
+ });
2085
+ }
2086
+ function balanceAtLeast(balance, minimum) {
2087
+ return balancePrerequisiteSchema.parse({
2088
+ kind: "balance",
2089
+ balance: ledgerKey(balance),
2090
+ minimum
2091
+ });
2092
+ }
2093
+ function inGroup(group) {
2094
+ return groupPrerequisiteSchema.parse({
2095
+ kind: "group",
2096
+ group: projectGroupKey(group),
2097
+ title: group.title
2098
+ });
2099
+ }
2100
+
2101
+ // src/schema.ts
2102
+ import { z as z23 } from "zod";
2103
+ var pointsRewardSchema = z23.object({
2104
+ kind: z23.literal("points").default("points"),
2105
+ balance: identifier,
2106
+ amount: z23.number().int().min(0).max(1e4)
2107
+ }).strict();
2108
+ var tieredRewardDefinitionSchema = z23.object({
2109
+ id: identifier,
2110
+ title: z23.string().min(1).max(120),
2111
+ tiers: z23.array(
2112
+ z23.object({ id: identifier, title: z23.string().min(1).max(120) }).strict()
2113
+ ).min(1).max(20).refine(
2114
+ (tiers) => new Set(tiers.map((t) => t.id)).size === tiers.length,
2115
+ "Tier IDs must be unique"
2116
+ ),
2117
+ inventory: z23.object({ kind: z23.literal("untracked") }).strict(),
2118
+ fulfillment: z23.discriminatedUnion("kind", [
2119
+ z23.object({ kind: z23.literal("staff-handover") }).strict(),
2120
+ z23.object({ kind: z23.literal("automatic") }).strict()
2121
+ ])
2122
+ }).strict();
2123
+ var tieredRewardReferenceSchema = z23.object({
2124
+ id: identifier,
2125
+ key: identifier.nullable()
2126
+ });
2127
+ var tierRewardSchema = z23.object({
2128
+ kind: z23.literal("tier"),
2129
+ reward: tieredRewardDefinitionSchema,
2130
+ tier: identifier
2131
+ }).strict().refine(
2132
+ (value) => value.reward.tiers.some((t) => t.id === value.tier),
2133
+ "Unknown reward tier"
2134
+ );
2135
+ var integrationRewardSchema = discordRewardSchema;
2136
+ var rewardSchema = z23.union([
2137
+ pointsRewardSchema,
2138
+ tierRewardSchema,
2139
+ integrationRewardSchema
2140
+ ]);
2141
+ function rewardKey(reward) {
2142
+ if (reward.kind === "integration") {
2143
+ return `integration:${reward.provider}:${reward.action}:${reward.roleId}`;
2144
+ }
2145
+ return reward.kind === "points" ? "points:" + reward.balance : "tier:" + reward.reward.id;
2146
+ }
2147
+ var triggerSchema = z23.union([
2148
+ z23.object({
2149
+ kind: z23.literal("manual"),
2150
+ input: z23.literal("text"),
2151
+ constraints: textOptionsSchema,
2152
+ actor: z23.enum(["member", "staff"]).optional()
2153
+ }).strict(),
2154
+ z23.object({
2155
+ kind: z23.literal("manual"),
2156
+ input: z23.literal("url"),
2157
+ constraints: urlOptionsSchema,
2158
+ actor: z23.enum(["member", "staff"]).optional()
2159
+ }).strict(),
2160
+ z23.object({
2161
+ kind: z23.literal("manual"),
2162
+ input: z23.enum(["photo", "quiz", "none"]),
2163
+ actor: z23.enum(["member", "staff"]).optional()
2164
+ }).strict(),
2165
+ z23.object({
2166
+ kind: z23.literal("automatic"),
2167
+ tracker: trackerTriggerPolicySchema.optional()
2168
+ }).strict()
2169
+ ]);
2170
+ var triggerResponseSchema = z23.union(
2171
+ triggerSchema.options.map((option) => option.strip())
2172
+ );
2173
+ var photoResultSchema = z23.object({
2174
+ kind: z23.enum(["pass", "fail", "unclear"]),
2175
+ reason: z23.string().min(1).max(2e3)
2176
+ }).strict();
2177
+ var textReviewInputSchema = z23.object({
2178
+ text: z23.string().min(1).max(16e3).refine((value) => value.trim().length > 0, "Text must not be blank"),
2179
+ criteria: z23.string().trim().min(1).max(2e3)
2180
+ }).strict();
2181
+ var textResultSchema = photoResultSchema;
2182
+ var deferPolicy = {
2183
+ minRetryAfterMs: 1e3,
2184
+ maxRetryAfterMs: 36e5,
2185
+ retryAfterMs: 6e4,
2186
+ horizonMs: 864e5,
2187
+ maxDefers: 100
2188
+ };
2189
+ var evaluatorProgressSchema = z23.object({
2190
+ current: z23.number().finite().nonnegative(),
2191
+ target: z23.number().finite().positive(),
2192
+ reason: z23.string().min(1).max(2e3)
2193
+ }).refine((value) => value.current <= value.target, {
2194
+ message: "Progress current must not exceed target"
2195
+ });
2196
+ var decisionSchema = z23.discriminatedUnion("kind", [
2197
+ z23.strictObject({
2198
+ kind: z23.literal("defer"),
2199
+ reason: z23.string().min(1).max(2e3),
2200
+ retryAfterMs: z23.number().int().min(deferPolicy.minRetryAfterMs).max(deferPolicy.maxRetryAfterMs).optional(),
2201
+ /** Absolute Unix milliseconds; the platform can only shorten its existing deadline. */
2202
+ until: z23.number().int().safe().nonnegative().optional()
2203
+ }),
2204
+ evaluatorProgressSchema.safeExtend({ kind: z23.literal("progress") }).strict(),
2205
+ z23.object({
2206
+ kind: z23.literal("accept"),
2207
+ rewards: z23.array(rewardSchema).max(10),
2208
+ completionKey: completionKeySchema.optional()
2209
+ }).strict(),
2210
+ z23.object({
2211
+ kind: z23.literal("reject"),
2212
+ reason: z23.string().min(1).max(2e3),
2213
+ /** The evaluator asked for human review, but review is off for the quest, so this is a reject. */
2214
+ requestedReview: z23.literal(true).optional()
2215
+ }).strict(),
2216
+ z23.object({
2217
+ kind: z23.literal("review"),
2218
+ reason: z23.string().min(1).max(2e3),
2219
+ rewards: z23.array(rewardSchema).max(10).optional(),
2220
+ completionKey: completionKeySchema.optional()
2221
+ }).strict()
2222
+ ]);
2223
+ var reviewModeSchema = z23.enum(["workers-ai"]);
2224
+ var storedReviewModeSchema = z23.enum([
2225
+ "fixture-pass",
2226
+ "fixture-fail",
2227
+ "fixture-unclear",
2228
+ "fixture-error",
2229
+ "workers-ai"
2230
+ ]);
2231
+ var rewardBundleSchema = z23.array(rewardSchema).max(10).refine(
2232
+ (rewards) => new Set(rewards.map(rewardKey)).size === rewards.length,
2233
+ "Use one entry per balance or shared reward"
2234
+ );
2235
+ var mediaUrlSchema = z23.string().max(2e3).refine((value) => {
2236
+ if (/^\/(?!\/)[^\\\s]*$/.test(value)) {
2237
+ return true;
2238
+ }
2239
+ try {
2240
+ return new URL(value).protocol === "https:";
2241
+ } catch {
2242
+ return false;
2243
+ }
2244
+ }, "Use an HTTPS URL or a same-site path beginning with /");
2245
+ var questPresentationSchema = z23.object({
2246
+ quiz: quizQuestionsSchema.optional(),
2247
+ instructions: z23.string().max(4e3).optional(),
2248
+ video: z23.object({
2249
+ url: mediaUrlSchema,
2250
+ poster: mediaUrlSchema.optional(),
2251
+ captions: z23.object({
2252
+ url: mediaUrlSchema,
2253
+ language: z23.string().min(2).max(20),
2254
+ label: z23.string().min(1).max(80)
2255
+ }).strict().optional()
2256
+ }).strict().optional()
2257
+ }).strict();
2258
+ var questProfileSchema = z23.object({ visible: z23.boolean() }).strict();
2259
+ var evaluatorProtocol = 2;
2260
+ var evaluatorProtocolSchema = z23.literal(evaluatorProtocol);
2261
+ var questDescriptionSchema = z23.object({
2262
+ quest: identifier,
2263
+ evaluatorProtocol: evaluatorProtocolSchema,
2264
+ title: z23.string().min(1).max(120),
2265
+ presentation: questPresentationSchema.default({}),
2266
+ integrations: z23.array(evaluatorIntegrationProviderSchema).max(10).default([]),
2267
+ fields: settingsFieldsSchema,
2268
+ values: settingsValuesSchema,
2269
+ rewards: rewardBundleSchema,
2270
+ humanReview: z23.boolean(),
2271
+ trigger: triggerSchema,
2272
+ performance: contentPerformancePolicySchema.optional(),
2273
+ requires: z23.array(prerequisiteSchema).max(30).default([]),
2274
+ campaign: campaignDefinitionSchema.optional(),
2275
+ availability: availabilityWindowSchema.optional(),
2276
+ completion: z23.preprocess(refuseStreakTimeZone, completionPolicySchema),
2277
+ visibility: z23.enum(["visible", "hidden"]).default("visible"),
2278
+ /** Whether completions show on participant profiles (`/v1/profiles/:id/completions`). */
2279
+ profile: questProfileSchema.default({ visible: false }),
2280
+ budgets: z23.array(budgetSchema).max(20).default([])
2281
+ }).strict();
2282
+ var artifactSchema = z23.object({ code: z23.string().min(1).max(1e6) }).strict();
2283
+ var releaseSchema = artifactSchema.extend({
2284
+ settings: settingsValuesSchema,
2285
+ provider: reviewModeSchema,
2286
+ expectedRelease: identifier.nullable().optional(),
2287
+ settingRenames: z23.record(z23.string(), z23.string()).optional()
2288
+ }).strict();
2289
+ var batchReleaseSchema = z23.object({ releases: z23.array(releaseSchema).min(1).max(50) }).strict();
2290
+ var questSettingsInputSchema = z23.object({
2291
+ quest: identifier,
2292
+ expectedRelease: identifier,
2293
+ set: settingsValuesSchema,
2294
+ reset: z23.array(z23.string())
2295
+ }).strict();
2296
+ var storedQuestDescriptionSchema = questDescriptionSchema.extend({
2297
+ completion: completionPolicySchema
2298
+ });
2299
+ var publishedReleaseSchema = storedQuestDescriptionSchema.extend({
2300
+ key: identifier.optional(),
2301
+ code: z23.string(),
2302
+ provider: storedReviewModeSchema,
2303
+ id: identifier,
2304
+ createdAt: z23.number(),
2305
+ origin: z23.object({ typeVersion: identifier }).strict().optional(),
2306
+ lifecycle: z23.enum(["active", "paused", "archived"]).default("active"),
2307
+ configuration: z23.object({
2308
+ defaults: settingsValuesSchema,
2309
+ overrides: settingsValuesSchema,
2310
+ preserved: z23.array(z23.string())
2311
+ }).strict().optional()
2312
+ });
2313
+ var templateSchema = z23.object({
2314
+ code: z23.string(),
2315
+ definition: questDescriptionSchema
2316
+ });
2317
+ var quizAnswersSchema = z23.record(identifier, identifier).refine(
2318
+ (answers) => Object.keys(answers).length > 0 && Object.keys(answers).length <= 50,
2319
+ "Provide between 1 and 50 answers"
2320
+ ).transform(
2321
+ (answers) => Object.fromEntries(
2322
+ Object.entries(answers).sort(([a], [b]) => a.localeCompare(b))
2323
+ )
2324
+ );
2325
+ var quizEvidenceSchema = z23.object({
2326
+ kind: z23.literal("quiz"),
2327
+ release: identifier.optional(),
2328
+ answers: quizAnswersSchema
2329
+ }).strict();
2330
+ var submissionEvidenceSchema = z23.union([
2331
+ quizEvidenceSchema,
2332
+ textEvidenceSchema,
2333
+ urlEvidenceSchema
2334
+ ]);
2335
+ var submitSchema = z23.object({
2336
+ actionId: identifier,
2337
+ quest: identifier,
2338
+ member: identifier,
2339
+ evidence: identifier.optional(),
2340
+ input: submissionEvidenceSchema.optional(),
2341
+ release: identifier.optional(),
2342
+ faultAfterReview: z23.boolean().optional()
2343
+ }).strict();
2344
+ var AttemptStatus = {
2345
+ Queued: "queued",
2346
+ Evaluating: "evaluating",
2347
+ Deferred: "deferred",
2348
+ Accepted: "accepted",
2349
+ Progressed: "progressed",
2350
+ Rejected: "rejected",
2351
+ NeedsReview: "needs-review",
2352
+ Failed: "failed"
2353
+ };
2354
+ var attemptStatusSchema = z23.string();
2355
+ var attemptSchema = z23.object({
2356
+ id: identifier,
2357
+ release: identifier,
2358
+ quest: identifier,
2359
+ member: identifier,
2360
+ evidence: identifier.nullable(),
2361
+ input: submissionEvidenceSchema.optional(),
2362
+ status: attemptStatusSchema,
2363
+ reason: z23.string().nullable(),
2364
+ retries: z23.number(),
2365
+ generation: z23.number(),
2366
+ completion: z23.string().nullable(),
2367
+ reviewRewards: rewardBundleSchema.nullable().default(null),
2368
+ /** Scheduled reruns advance this number; failure retries preserve it. */
2369
+ evaluationRun: z23.number().int().nonnegative().default(0),
2370
+ deferCount: z23.number().int().nonnegative().default(0),
2371
+ deferUntil: z23.number().int().safe().nullable().default(null),
2372
+ nextEvaluationAt: z23.number().int().safe().nullable().default(null),
2373
+ /** Open code: consumers must tolerate new values. */
2374
+ code: z23.string().nullable().default(null),
2375
+ progress: evaluatorProgressSchema.nullable().default(null),
2376
+ /**
2377
+ * The evaluator asked for human review of a quest with review off, so Domino rejected the attempt
2378
+ * with the evaluator's reason. Only set on a rejected attempt.
2379
+ */
2380
+ requestedReview: z23.boolean().default(false),
2381
+ createdAt: z23.number()
2382
+ });
2383
+ var eventSchema = z23.object({
2384
+ id: z23.number(),
2385
+ attempt: z23.string().nullable(),
2386
+ kind: z23.string(),
2387
+ detail: z23.string(),
2388
+ actor: z23.string().nullable().default(null),
2389
+ at: z23.number()
2390
+ });
2391
+ var pickupSelectionSchema = z23.object({
2392
+ item: identifier,
2393
+ revision: z23.number().int().nonnegative()
2394
+ }).strict();
2395
+ var pickupAllocationSchema = z23.object({
2396
+ item: identifier,
2397
+ label: z23.string().min(1).max(80)
2398
+ }).strict();
2399
+ var pickupPolicySchema = z23.discriminatedUnion("kind", [
2400
+ z23.object({ kind: z23.literal("untracked") }).strict(),
2401
+ z23.object({
2402
+ kind: z23.literal("at-pickup"),
2403
+ tiers: z23.array(
2404
+ z23.object({
2405
+ tier: identifier,
2406
+ variants: z23.array(pickupAllocationSchema).min(1).max(100)
2407
+ }).strict()
2408
+ ).min(1).max(100)
2409
+ }).strict()
2410
+ ]);
2411
+ var pickupCatalogSchema = z23.object({
2412
+ reward: tieredRewardDefinitionSchema,
2413
+ revision: z23.number().int().nonnegative(),
2414
+ policy: pickupPolicySchema
2415
+ });
2416
+ var pickupAvailabilitySchema = z23.discriminatedUnion("kind", [
2417
+ z23.object({ kind: z23.literal("untracked") }).strict(),
2418
+ z23.object({
2419
+ kind: z23.literal("at-pickup"),
2420
+ revision: z23.number().int().nonnegative(),
2421
+ variants: z23.array(
2422
+ pickupAllocationSchema.extend({
2423
+ available: z23.number().int().nonnegative()
2424
+ })
2425
+ )
2426
+ }).strict()
2427
+ ]);
2428
+ var configurePickupSchema = z23.object({
2429
+ reward: identifier,
2430
+ revision: z23.number().int().nonnegative(),
2431
+ actionId: identifier,
2432
+ policy: z23.discriminatedUnion("kind", [
2433
+ z23.object({ kind: z23.literal("untracked") }).strict(),
2434
+ z23.object({
2435
+ kind: z23.literal("at-pickup"),
2436
+ tiers: z23.array(
2437
+ z23.object({
2438
+ tier: identifier,
2439
+ variants: z23.array(
2440
+ pickupAllocationSchema.extend({
2441
+ item: identifier.optional()
2442
+ })
2443
+ ).min(1).max(100)
2444
+ }).strict()
2445
+ ).min(1).max(100)
2446
+ }).strict()
2447
+ ])
2448
+ }).strict();
2449
+ var entitlementRecoverySchema = z23.object({
2450
+ completion: identifier,
2451
+ reason: z23.string(),
2452
+ flaggedAt: z23.number(),
2453
+ /** Null means no accepted completion currently earns this reward. */
2454
+ remainingTier: identifier.nullable()
2455
+ });
2456
+ var entitlementBase = {
2457
+ id: identifier,
2458
+ member: identifier,
2459
+ reward: tieredRewardDefinitionSchema,
2460
+ earnedTier: identifier,
2461
+ tier: identifier,
2462
+ revision: z23.number().int().positive()
2463
+ };
2464
+ var entitlementStateSchema = z23.discriminatedUnion("status", [
2465
+ z23.object({ ...entitlementBase, status: z23.literal("available") }).strict(),
2466
+ z23.object({
2467
+ ...entitlementBase,
2468
+ status: z23.literal("handing-over"),
2469
+ handover: identifier,
2470
+ startedAt: z23.number(),
2471
+ allocation: pickupAllocationSchema.optional()
2472
+ }).strict(),
2473
+ z23.object({
2474
+ ...entitlementBase,
2475
+ status: z23.literal("collected"),
2476
+ handover: identifier,
2477
+ startedAt: z23.number(),
2478
+ allocation: pickupAllocationSchema.optional(),
2479
+ collectedAt: z23.number(),
2480
+ recovery: entitlementRecoverySchema.optional()
2481
+ }).strict(),
2482
+ // An operator voided it: it can no longer be handed over. A quest grant of the same reward to
2483
+ // the member (the same grant key) makes it available again; a voided referral reward stays void.
2484
+ z23.object({
2485
+ ...entitlementBase,
2486
+ status: z23.literal("void"),
2487
+ voidedAt: z23.number()
2488
+ }).strict()
2489
+ ]);
2490
+ var tieredRewardReadSchema = z23.object({
2491
+ id: identifier,
2492
+ title: z23.string(),
2493
+ tiers: z23.array(z23.object({ id: identifier, title: z23.string() }).loose()),
2494
+ inventory: z23.object({ kind: z23.string() }).loose(),
2495
+ fulfillment: z23.object({ kind: z23.string() }).loose()
2496
+ }).loose();
2497
+ var entitlementReadBase = {
2498
+ id: identifier,
2499
+ member: identifier,
2500
+ reward: tieredRewardReadSchema,
2501
+ earnedTier: identifier,
2502
+ tier: identifier,
2503
+ revision: z23.number().int()
2504
+ };
2505
+ var allocationReadSchema = z23.object({ item: identifier, label: z23.string() }).loose();
2506
+ var entitlementSchema = z23.union([
2507
+ z23.discriminatedUnion("status", [
2508
+ z23.object({ ...entitlementReadBase, status: z23.literal("available") }).loose(),
2509
+ z23.object({
2510
+ ...entitlementReadBase,
2511
+ status: z23.literal("handing-over"),
2512
+ handover: identifier,
2513
+ startedAt: z23.number(),
2514
+ allocation: allocationReadSchema.optional()
2515
+ }).loose(),
2516
+ z23.object({
2517
+ ...entitlementReadBase,
2518
+ status: z23.literal("collected"),
2519
+ handover: identifier,
2520
+ startedAt: z23.number(),
2521
+ allocation: allocationReadSchema.optional(),
2522
+ collectedAt: z23.number(),
2523
+ recovery: entitlementRecoverySchema.optional()
2524
+ }).loose(),
2525
+ z23.object({
2526
+ ...entitlementReadBase,
2527
+ status: z23.literal("void"),
2528
+ voidedAt: z23.number()
2529
+ }).loose()
2530
+ ]),
2531
+ z23.object({ ...entitlementReadBase, status: z23.string() }).loose().transform(({ status, ...entitlement }) => ({
2532
+ ...entitlement,
2533
+ status: "unsupported",
2534
+ reportedStatus: status
2535
+ }))
2536
+ ]);
2537
+ var beginHandoverSchema = z23.object({
2538
+ actionId: identifier,
2539
+ revision: z23.number().int().positive(),
2540
+ selection: pickupSelectionSchema.optional()
2541
+ }).strict();
2542
+ var confirmHandoverSchema = z23.object({ actionId: identifier, handover: identifier }).strict();
2543
+ var entitlementCorrectionSchema = z23.object({
2544
+ actionId: identifier,
2545
+ revision: z23.number().int().positive(),
2546
+ reason: z23.string().trim().min(1).max(500)
2547
+ }).strict();
2548
+ var completionRecordSchema = z23.object({
2549
+ key: z23.string().default("once"),
2550
+ id: identifier,
2551
+ quest: identifier,
2552
+ member: identifier
2553
+ });
2554
+ var questAvailabilitySchema = z23.discriminatedUnion("kind", [
2555
+ z23.object({
2556
+ kind: z23.literal("available"),
2557
+ input: z23.enum(["photo", "quiz", "none", "text", "url"])
2558
+ }).strict(),
2559
+ z23.object({ kind: z23.literal("completed") }).strict(),
2560
+ z23.object({
2561
+ kind: z23.literal("locked"),
2562
+ missing: z23.array(missingPrerequisiteSchema).min(1)
2563
+ }).strict(),
2564
+ z23.object({
2565
+ kind: z23.literal("blocked"),
2566
+ reason: z23.enum([
2567
+ "budget-exhausted",
2568
+ "connection-required",
2569
+ "wallet-required",
2570
+ "paused",
2571
+ "outside-window",
2572
+ "enrollment-required"
2573
+ ]),
2574
+ resetsAt: z23.number().int().safe().optional()
2575
+ }).strict(),
2576
+ z23.object({ kind: z23.literal("staff-required") }).strict(),
2577
+ z23.object({ kind: z23.literal("automatic") }).strict(),
2578
+ z23.object({ kind: z23.literal("checking"), attempt: identifier }).strict(),
2579
+ z23.object({ kind: z23.literal("needs-review"), attempt: identifier }).strict(),
2580
+ z23.object({ kind: z23.literal("retryable"), attempt: identifier }).strict()
2581
+ ]);
2582
+ var questAvailabilityResponseSchema = z23.union(
2583
+ questAvailabilitySchema.options.map((option) => option.strip())
2584
+ );
2585
+ var questBudgetViewSchema = z23.object({
2586
+ id: identifier,
2587
+ scope: z23.enum(["member", "project"]),
2588
+ period: z23.enum(["day", "week", "month", "lifetime"]),
2589
+ remaining: z23.number().int().safe().nonnegative(),
2590
+ resetsAt: z23.number().int().safe().nullable()
2591
+ });
2592
+ var memberProgressSchema = z23.object({
2593
+ member: identifier,
2594
+ quests: z23.array(
2595
+ z23.object({
2596
+ quest: identifier,
2597
+ key: identifier.optional(),
2598
+ release: identifier.optional(),
2599
+ title: z23.string(),
2600
+ presentation: questPresentationSchema.default({}),
2601
+ connections: z23.array(authProviderSchema).default([]),
2602
+ trigger: triggerResponseSchema,
2603
+ availability: questAvailabilityResponseSchema,
2604
+ completed: z23.boolean(),
2605
+ completion: completionPolicySchema.default({ kind: "once" }),
2606
+ streak: streakProgressSchema.nullable().optional(),
2607
+ counter: counterProgressSchema.nullable().optional(),
2608
+ /** Latest attempt's committed evaluator progress, while it remains deferred/evaluating. */
2609
+ progress: evaluatorProgressSchema.nullable().default(null),
2610
+ completionCount: z23.number().int().nonnegative().default(0),
2611
+ visibility: z23.enum(["visible", "hidden"]).default("visible"),
2612
+ missing: z23.array(missingPrerequisiteSchema),
2613
+ campaign: campaignViewSchema.nullable().default(null),
2614
+ window: availabilityWindowSchema.nullable().default(null),
2615
+ budgets: z23.array(questBudgetViewSchema).default([]),
2616
+ attempt: attemptSchema.nullable()
2617
+ })
2618
+ ),
2619
+ entitlements: z23.array(entitlementSchema)
2620
+ });
2621
+ var snapshotSchema = z23.object({
2622
+ releases: z23.array(publishedReleaseSchema),
2623
+ completions: z23.array(completionRecordSchema),
2624
+ entitlements: z23.array(entitlementSchema),
2625
+ attempts: z23.array(attemptSchema),
2626
+ balances: z23.array(
2627
+ z23.object({
2628
+ member: z23.string(),
2629
+ balance: z23.string(),
2630
+ earned: z23.number(),
2631
+ held: z23.number(),
2632
+ available: z23.number()
2633
+ })
2634
+ ),
2635
+ events: z23.array(eventSchema)
2636
+ });
2637
+ var evidenceSchema = z23.object({
2638
+ id: identifier,
2639
+ member: identifier,
2640
+ type: z23.enum(["image/jpeg", "image/png"]),
2641
+ size: z23.number()
2642
+ });
2643
+ var errorSchema = z23.object({
2644
+ error: z23.string(),
2645
+ code: z23.string().optional(),
2646
+ missing: z23.array(missingPrerequisiteSchema).optional()
2647
+ });
2648
+ var staffDecisionSchema = z23.object({
2649
+ actionId: identifier,
2650
+ generation: z23.number().int().nonnegative(),
2651
+ decision: z23.enum(["accept", "reject"]),
2652
+ reason: z23.string().trim().min(1).max(2e3)
2653
+ }).strict();
2654
+ var stockSchema = z23.object({ item: identifier, quantity: z23.number().int().min(0).max(1e4) }).strict();
2655
+ var reservationSchema = z23.object({
2656
+ actionId: identifier,
2657
+ member: identifier,
2658
+ item: identifier,
2659
+ balance: identifier,
2660
+ price: z23.number().int().positive().max(1e4)
2661
+ }).strict();
2662
+ var pageOptions = {
2663
+ limit: z23.number().int().min(1).max(100).default(25),
2664
+ cursor: z23.string().min(1).max(4096).optional()
2665
+ };
2666
+ var reviewListSchema = z23.object({
2667
+ ...pageOptions,
2668
+ member: identifier.optional(),
2669
+ quest: identifier.optional()
2670
+ }).strict();
2671
+ var memberListSchema = z23.object({
2672
+ ...pageOptions,
2673
+ prefix: identifier.optional()
2674
+ }).strict();
2675
+ var reviewItemSchema = z23.object({
2676
+ attempt: attemptSchema,
2677
+ title: z23.string(),
2678
+ checks: z23.array(
2679
+ z23.object({ criteria: z23.string(), result: photoResultSchema })
2680
+ )
2681
+ });
2682
+ var reviewPageSchema = z23.object({
2683
+ items: z23.array(reviewItemSchema).max(100),
2684
+ nextCursor: z23.string().nullable()
2685
+ });
2686
+ var memberPageSchema = z23.object({
2687
+ items: z23.array(z23.object({ member: identifier })).max(100),
2688
+ nextCursor: z23.string().nullable()
2689
+ });
2690
+ var createStockItemSchema = z23.object({ actionId: identifier, name: z23.string().trim().min(1).max(80) }).strict();
2691
+ var stockItemSchema = z23.object({ id: identifier, name: z23.string() });
2692
+ var contentPerformanceSnapshotSchema = z23.strictObject({
2693
+ contentAttempt: identifier,
2694
+ observation: identifier,
2695
+ observedAt: z23.number().int().safe().nonnegative(),
2696
+ metrics: contentMetricsSchema,
2697
+ rewards: rewardBundleSchema
2698
+ });
2699
+ var contentPerformanceQuerySchema = contentQualificationQuerySchema.extend({
2700
+ content: z23.string().min(1).max(256)
2701
+ });
2702
+ var contentPerformancePageSchema = z23.strictObject({
2703
+ current: z23.strictObject({
2704
+ state: z23.enum([
2705
+ "content-pending",
2706
+ "content-unqualified",
2707
+ "waiting",
2708
+ "pending",
2709
+ "qualified",
2710
+ "unqualified",
2711
+ "needs-review",
2712
+ "failed",
2713
+ "superseded"
2714
+ ]),
2715
+ reason: z23.string().nullable(),
2716
+ contentAttempt: identifier,
2717
+ attempt: identifier.nullable(),
2718
+ reward: contentQualificationSchema.shape.reward
2719
+ }),
2720
+ items: z23.array(
2721
+ z23.strictObject({
2722
+ attempt: identifier,
2723
+ contentAttempt: identifier,
2724
+ observation: identifier,
2725
+ observedAt: z23.number(),
2726
+ metrics: contentMetricsSchema,
2727
+ state: z23.enum([
2728
+ "pending",
2729
+ "qualified",
2730
+ "unqualified",
2731
+ "needs-review",
2732
+ "failed",
2733
+ "superseded"
2734
+ ]),
2735
+ reason: z23.string().nullable()
2736
+ })
2737
+ ),
2738
+ nextCursor: pageCursorSchema.nullable()
2739
+ });
2740
+
2741
+ export {
2742
+ pageCursorSchema,
2743
+ pageQuerySchema,
2744
+ authProviderSchema,
2745
+ accountConnectionSchema,
2746
+ discordMemberInputSchema,
2747
+ discordMessageInputSchema,
2748
+ discordMemberSchema,
2749
+ identifier,
2750
+ discordMessageSchema,
2751
+ discordMessagesSourceSchema,
2752
+ discordReactionsSourceSchema,
2753
+ discordMessageDataSchema,
2754
+ discordMessageTextDataSchema,
2755
+ discordReactionDataSchema,
2756
+ discordRewardSchema,
2757
+ discordResourceSourceSchema,
2758
+ trackerDataMaxBranches,
2759
+ trackerDataMaxEntries,
2760
+ trackerDataSchemaSchema,
2761
+ trackerDataSchema,
2762
+ trackerDataRecordSteps,
2763
+ trackerDataBatchSteps,
2764
+ trackerDataIssue,
2765
+ trackerDataIssues,
2766
+ trackerDataPathTypes,
2767
+ schemaCheckedReader,
2768
+ whereSchemaIssue,
2769
+ xTweetSchema,
2770
+ xContentBodySchema,
2771
+ trackerContentQuerySchema,
2772
+ trackerContentReadSchema,
2773
+ trackerEvidenceSchema,
2774
+ trackerContentSchema,
2775
+ knownIdentityKinds,
2776
+ appIdentityKindSchema,
2777
+ identityKindSchema,
2778
+ isAppIdentityKind,
2779
+ openIdentityKindSchema,
2780
+ memberIdentitySchema,
2781
+ accountRoleSchema,
2782
+ xAccountRoles,
2783
+ contentMetricNameSchema,
2784
+ xContentMetrics,
2785
+ customContentSchema,
2786
+ xSearchSourceSchema,
2787
+ customSourceSchema,
2788
+ trackerSourceSchema,
2789
+ trackerSourceKinds,
2790
+ sourceIdentities,
2791
+ sourceContent,
2792
+ trackerDefinitionSchema,
2793
+ trackerArtifactSchema,
2794
+ trackerSourceResponseSchema,
2795
+ isKnownTrackerSource,
2796
+ trackerDefinitionResponseSchema,
2797
+ publishedTrackerSchema,
2798
+ trackerStatusSchema,
2799
+ trackerControlSchema,
2800
+ trackerAccountSchema,
2801
+ trackerRecordInputSchema,
2802
+ trackerRecordAccountSchema,
2803
+ trackerRecordSchema,
2804
+ trackerIngestSchema,
2805
+ trackerIngestResultSchema,
2806
+ trackerSkipCodes,
2807
+ trackerOutcomeSchema,
2808
+ trackerOutcomeQuerySchema,
2809
+ trackerOutcomePageSchema,
2810
+ trackerOutcomeRetrySchema,
2811
+ trackerQuerySchema,
2812
+ trackerPageSchema,
2813
+ trackerSummarySchema,
2814
+ trackerPreviewLimits,
2815
+ trackerPreviewInputSchema,
2816
+ trackerPreviewSchema,
2817
+ contentQualificationDecisionSchema,
2818
+ contentQualificationQuerySchema,
2819
+ contentQualificationSchema,
2820
+ contentQualificationPageSchema,
2821
+ contentMetricSchema,
2822
+ contentMetricsSchema,
2823
+ contentPerformancePolicySchema,
2824
+ counterGoalSchema,
2825
+ counterWindowSchema,
2826
+ counterPolicySchema,
2827
+ counterAchievementSchema,
2828
+ counterProgressSchema,
2829
+ counterContributionSchema,
2830
+ counterHistorySchema,
2831
+ counterModerationSchema,
2832
+ counterHistoryQuerySchema,
2833
+ counterModerationResultSchema,
2834
+ canonicalTimeZone,
2835
+ timeZoneSchema,
2836
+ timeZoneNameSchema,
2837
+ refuseStreakTimeZone,
2838
+ refuseWindowTimeZone,
2839
+ calendarPeriodSchema,
2840
+ projectCalendarSchema,
2841
+ projectCalendarInputSchema,
2842
+ projectCalendarDeclarationSchema,
2843
+ streakPolicySchema,
2844
+ streakProgressSchema,
2845
+ trackerTriggerModeSchema,
2846
+ defaultTriggerMode,
2847
+ trackerBoundSchema,
2848
+ trackerConditionSchema,
2849
+ trackerWhereSchema,
2850
+ whereConditions,
2851
+ whereSettings,
2852
+ triggerEnrollmentSchema,
2853
+ triggerSinceSchema,
2854
+ triggerHistoricalSchema,
2855
+ trackerTriggerPolicySchema,
2856
+ triggerMode,
2857
+ triggerAdmission,
2858
+ beneficiaryRole,
2859
+ trackerAttributionSchema,
2860
+ trackerTriggerRecordSchema,
2861
+ trackerContentStageSchema,
2862
+ trackerTriggerContextSchema,
2863
+ completionPolicySchema,
2864
+ completionKeySchema,
2865
+ budgetSchema,
2866
+ evaluatorIntegrationProviderSchema,
2867
+ integrationProviderSchema,
2868
+ discordServerSchema,
2869
+ projectIntegrationSchema,
2870
+ textOptionsSchema,
2871
+ urlOptionsSchema,
2872
+ textEvidenceSchema,
2873
+ urlEvidenceSchema,
2874
+ valueEvidenceSchema,
2875
+ validateSubmissionValue,
2876
+ xPostId,
2877
+ quizChoiceSchema,
2878
+ quizQuestionSchema,
2879
+ quizQuestionsSchema,
2880
+ quizContentSchema,
2881
+ resourceSourceSchema,
2882
+ resourceRequestSchema,
2883
+ resourceOptionsSchema,
2884
+ settingInstant,
2885
+ settingResourceId,
2886
+ settingFieldSchema,
2887
+ settingsFieldsSchema,
2888
+ settingsValuesSchema,
2889
+ parseSettings,
2890
+ missingResourceSettings,
2891
+ compatibleSettingKinds,
2892
+ authoringIdentityShape,
2893
+ authoringKey,
2894
+ availabilityWindowSchema,
2895
+ campaignDefinitionSchema,
2896
+ defineCampaign,
2897
+ campaignViewSchema,
2898
+ campaignEnrollmentInputSchema,
2899
+ memberCampaignEnrollmentInputSchema,
2900
+ campaignWithdrawalInputSchema,
2901
+ memberCampaignWithdrawalInputSchema,
2902
+ campaignEnrollmentSchema,
2903
+ resourceHandle,
2904
+ ledgerSettingSchema,
2905
+ ledgerKey,
2906
+ projectGroupSchema,
2907
+ defineGroup,
2908
+ projectGroupKey,
2909
+ completionPrerequisiteSchema,
2910
+ balancePrerequisiteSchema,
2911
+ groupPrerequisiteSchema,
2912
+ prerequisiteSchema,
2913
+ missingPrerequisiteSchema,
2914
+ completed,
2915
+ balanceAtLeast,
2916
+ inGroup,
2917
+ pointsRewardSchema,
2918
+ tieredRewardDefinitionSchema,
2919
+ tieredRewardReferenceSchema,
2920
+ tierRewardSchema,
2921
+ integrationRewardSchema,
2922
+ rewardSchema,
2923
+ rewardKey,
2924
+ triggerSchema,
2925
+ photoResultSchema,
2926
+ textReviewInputSchema,
2927
+ textResultSchema,
2928
+ deferPolicy,
2929
+ evaluatorProgressSchema,
2930
+ decisionSchema,
2931
+ reviewModeSchema,
2932
+ storedReviewModeSchema,
2933
+ rewardBundleSchema,
2934
+ mediaUrlSchema,
2935
+ questPresentationSchema,
2936
+ questProfileSchema,
2937
+ evaluatorProtocol,
2938
+ evaluatorProtocolSchema,
2939
+ questDescriptionSchema,
2940
+ artifactSchema,
2941
+ releaseSchema,
2942
+ batchReleaseSchema,
2943
+ questSettingsInputSchema,
2944
+ storedQuestDescriptionSchema,
2945
+ publishedReleaseSchema,
2946
+ templateSchema,
2947
+ quizAnswersSchema,
2948
+ quizEvidenceSchema,
2949
+ submissionEvidenceSchema,
2950
+ submitSchema,
2951
+ AttemptStatus,
2952
+ attemptSchema,
2953
+ eventSchema,
2954
+ pickupSelectionSchema,
2955
+ pickupAllocationSchema,
2956
+ pickupPolicySchema,
2957
+ pickupCatalogSchema,
2958
+ pickupAvailabilitySchema,
2959
+ configurePickupSchema,
2960
+ entitlementRecoverySchema,
2961
+ entitlementStateSchema,
2962
+ entitlementSchema,
2963
+ beginHandoverSchema,
2964
+ confirmHandoverSchema,
2965
+ entitlementCorrectionSchema,
2966
+ completionRecordSchema,
2967
+ questAvailabilitySchema,
2968
+ questBudgetViewSchema,
2969
+ memberProgressSchema,
2970
+ snapshotSchema,
2971
+ evidenceSchema,
2972
+ errorSchema,
2973
+ staffDecisionSchema,
2974
+ stockSchema,
2975
+ reservationSchema,
2976
+ reviewListSchema,
2977
+ memberListSchema,
2978
+ reviewItemSchema,
2979
+ reviewPageSchema,
2980
+ memberPageSchema,
2981
+ createStockItemSchema,
2982
+ stockItemSchema,
2983
+ contentPerformanceSnapshotSchema,
2984
+ contentPerformanceQuerySchema,
2985
+ contentPerformancePageSchema
2986
+ };