@domino-sdk/relay 0.29.0 → 0.31.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.
@@ -0,0 +1,42 @@
1
+ import {
2
+ identifier
3
+ } from "./chunk-UPWID5KS.js";
4
+
5
+ // src/auth.ts
6
+ import { z } from "zod";
7
+ var authScopeSchema = z.object({
8
+ organization: identifier,
9
+ project: identifier,
10
+ environment: z.enum(["test", "live"])
11
+ }).strict();
12
+ var principalSchema = z.discriminatedUnion("kind", [
13
+ z.object({ kind: z.literal("member"), member: identifier }).strict(),
14
+ z.object({ kind: z.literal("staff"), subject: identifier }).strict(),
15
+ z.object({ kind: z.literal("operator"), subject: identifier }).strict()
16
+ ]);
17
+ var sessionSchema = authScopeSchema.extend({
18
+ id: identifier,
19
+ principal: principalSchema,
20
+ expiresAt: z.number()
21
+ });
22
+ var memberSummarySchema = z.object({
23
+ member: identifier,
24
+ avatarSeed: z.string().min(1).max(100)
25
+ });
26
+ var exchangeSchema = authScopeSchema.extend({
27
+ identity: z.object({ issuer: identifier, subject: z.string().min(1).max(200) }).strict(),
28
+ role: z.enum(["member", "staff", "operator"])
29
+ }).strict();
30
+ var exchangeResultSchema = z.object({
31
+ token: z.string(),
32
+ session: sessionSchema
33
+ });
34
+
35
+ export {
36
+ authScopeSchema,
37
+ principalSchema,
38
+ sessionSchema,
39
+ memberSummarySchema,
40
+ exchangeSchema,
41
+ exchangeResultSchema
42
+ };
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  profileSummarySchema
3
- } from "./chunk-MRKFRCCI.js";
3
+ } from "./chunk-UI4N4XRZ.js";
4
4
  import {
5
5
  contentMetricSchema,
6
6
  contentMetricsSchema,
7
7
  identifier,
8
8
  pointsRewardSchema,
9
9
  tierRewardSchema
10
- } from "./chunk-BE5V6RFD.js";
10
+ } from "./chunk-UPWID5KS.js";
11
11
 
12
12
  // src/engagement.ts
13
13
  import { z } from "zod";
@@ -1,36 +1,147 @@
1
1
  import {
2
2
  identifier
3
- } from "./chunk-BE5V6RFD.js";
3
+ } from "./chunk-UPWID5KS.js";
4
4
 
5
- // src/auth.ts
5
+ // src/profiles.ts
6
6
  import { z } from "zod";
7
- var authScopeSchema = z.object({
8
- organization: identifier,
9
- project: identifier,
10
- environment: z.enum(["test", "live"])
11
- }).strict();
12
- var principalSchema = z.discriminatedUnion("kind", [
13
- z.object({ kind: z.literal("member"), member: identifier }).strict(),
14
- z.object({ kind: z.literal("staff"), subject: identifier }).strict(),
15
- z.object({ kind: z.literal("operator"), subject: identifier }).strict()
7
+ var count = z.number().int().nonnegative().safe();
8
+ var profileVisibilitySchema = z.enum([
9
+ "private",
10
+ "participants",
11
+ "public"
12
+ ]);
13
+ var avatarProviderSchema = z.enum(["x", "discord", "google"]);
14
+ var profileDefaultProviderSchema = z.enum(["x", "discord"]);
15
+ var profileDefaultsSchema = z.array(profileDefaultProviderSchema).max(profileDefaultProviderSchema.options.length).refine(
16
+ (providers) => new Set(providers).size === providers.length,
17
+ "List each provider once"
18
+ );
19
+ var avatarSeedSchema = z.string().min(1).max(100);
20
+ var profileAvatarSchema = z.discriminatedUnion("source", [
21
+ z.object({
22
+ source: z.literal("upload"),
23
+ url: z.string().url(),
24
+ seed: avatarSeedSchema
25
+ }),
26
+ z.object({
27
+ source: z.literal("account"),
28
+ provider: avatarProviderSchema,
29
+ url: z.string().url(),
30
+ seed: avatarSeedSchema
31
+ }),
32
+ z.object({ source: z.literal("generated"), seed: avatarSeedSchema })
16
33
  ]);
17
- var sessionSchema = authScopeSchema.extend({
34
+ var profileSummarySchema = z.object({
18
35
  id: identifier,
19
- principal: principalSchema,
20
- expiresAt: z.number()
36
+ name: z.string(),
37
+ avatar: profileAvatarSchema
21
38
  });
22
- var memberSummarySchema = z.object({
23
- member: identifier,
24
- avatarSeed: z.string().min(1).max(100)
39
+ var invisible = /[\p{Cc}؜᠎​-‏‪-‮⁠-⁤⁦-⁩]/u;
40
+ var displayNameSchema = z.string().max(200).transform((value) => value.normalize("NFC").replace(/\s+/g, " ").trim()).pipe(
41
+ z.string().min(1, "Enter a name").max(40, "Use at most 40 characters").refine((value) => !invisible.test(value), "Use visible characters only")
42
+ );
43
+ var profileUpdateSchema = z.object({
44
+ displayName: displayNameSchema.nullable().optional(),
45
+ avatar: z.discriminatedUnion("source", [
46
+ z.object({
47
+ source: z.literal("account"),
48
+ provider: avatarProviderSchema
49
+ }).strict(),
50
+ z.object({ source: z.literal("generated") }).strict()
51
+ ]).nullable().optional(),
52
+ hidden: z.boolean().optional()
53
+ }).strict().refine(
54
+ (value) => Object.values(value).some((field) => field !== void 0),
55
+ "Change at least one field"
56
+ );
57
+ var ownProfileSchema = profileSummarySchema.extend({
58
+ /** The name the member chose, or null for the default. */
59
+ displayName: z.string().nullable(),
60
+ /** The avatar the member chose: `default` follows the project's defaults. */
61
+ avatarChoice: z.enum(["default", "upload", "account", "generated"]),
62
+ /** The account of an `account` choice. */
63
+ avatarProvider: avatarProviderSchema.nullable(),
64
+ hidden: z.boolean(),
65
+ /** An operator locked the name and avatar; the member can still hide the profile. */
66
+ locked: z.boolean(),
67
+ /** Who can see profiles in this project, so the app can explain it. */
68
+ visibility: profileVisibilitySchema,
69
+ /** The member's connected accounts a picture or name can come from. */
70
+ options: z.array(
71
+ z.object({
72
+ provider: avatarProviderSchema,
73
+ name: z.string().nullable(),
74
+ imageUrl: z.string().url().nullable()
75
+ })
76
+ )
25
77
  });
26
- var exchangeSchema = authScopeSchema.extend({
27
- identity: z.object({ issuer: identifier, subject: z.string().min(1).max(200) }).strict(),
28
- role: z.enum(["member", "staff", "operator"])
78
+ var cursor = z.string().min(1).max(512);
79
+ var profileCompletionQuerySchema = z.object({
80
+ limit: z.coerce.number().int().min(1).max(100).default(20),
81
+ cursor: cursor.optional()
29
82
  }).strict();
30
- var exchangeResultSchema = z.object({
31
- token: z.string(),
32
- session: sessionSchema
83
+ var profileCompletionSchema = z.object({
84
+ quest: identifier,
85
+ key: identifier.optional(),
86
+ title: z.string(),
87
+ completions: count.positive(),
88
+ /** Null for completions recorded before completion times were. */
89
+ lastCompletedAt: count.nullable()
90
+ });
91
+ var profileCompletionPageSchema = z.object({
92
+ items: z.array(profileCompletionSchema),
93
+ nextCursor: cursor.nullable()
94
+ });
95
+ var profileReferralSchema = z.object({
96
+ program: identifier,
97
+ key: identifier.optional(),
98
+ title: z.string(),
99
+ /** Members this member invited. Invitations are shared by every program. */
100
+ invited: count,
101
+ /** Invited members who qualified in this program. */
102
+ qualified: count,
103
+ milestones: z.array(
104
+ z.object({ id: identifier, count, reached: z.boolean() })
105
+ )
106
+ });
107
+ var profileSettingsSchema = z.object({
108
+ visibility: profileVisibilitySchema,
109
+ defaults: profileDefaultsSchema,
110
+ revision: count,
111
+ actor: z.string().nullable(),
112
+ updatedAt: count.nullable()
33
113
  });
114
+ var profileSettingsInputSchema = profileSettingsSchema.omit({ revision: true, actor: true, updatedAt: true }).extend({
115
+ actionId: identifier,
116
+ /** The revision the change was made against; a newer one is a 409. */
117
+ expectedRevision: count,
118
+ reason: z.string().trim().min(1).max(500)
119
+ }).strict();
120
+ var profileModerationSchema = z.object({
121
+ actionId: identifier,
122
+ resetName: z.boolean().default(false),
123
+ removeAvatar: z.boolean().default(false),
124
+ /** True locks the name and avatar, false unlocks them. */
125
+ lock: z.boolean().optional(),
126
+ reason: z.string().trim().min(1).max(1e3)
127
+ }).strict().refine(
128
+ (value) => value.resetName || value.removeAvatar || value.lock !== void 0,
129
+ "Choose an action"
130
+ );
131
+ var managedProfileSchema = ownProfileSchema.omit({ options: true }).extend({
132
+ member: identifier,
133
+ lockedAt: count.nullable(),
134
+ lockedBy: z.string().nullable(),
135
+ lockedReason: z.string().nullable(),
136
+ updatedAt: count
137
+ });
138
+ var AVATAR_UPLOAD_LIMIT = 5 * 1024 * 1024;
139
+ var avatarUploadTypes = ["image/jpeg", "image/png", "image/webp"];
140
+ function isProfileParticipantRoute(path, method) {
141
+ return method === "GET" && (path === "/v1/me/profile" || /^\/v1\/profiles\/[\w-]+(?:\/completions|\/referrals\/[\w-]+)?$/.test(
142
+ path
143
+ ) || /^\/v1\/leaderboards\/[\w-]+\/profiles\/[\w-]+$/.test(path)) || method === "POST" && (path === "/v1/me/profile" || path === "/v1/me/profile/avatar");
144
+ }
34
145
 
35
146
  // src/wallet.ts
36
147
  import { z as z2 } from "zod";
@@ -171,8 +282,8 @@ function caip10(wallet, network) {
171
282
  return `${wallet.network}:${wallet.address}`;
172
283
  }
173
284
  const selected = network ?? (wallet.chain === "solana" ? solanaMainnet : "eip155:1");
174
- const syntax = wallet.chain === "solana" ? /^solana:[1-9A-HJ-NP-Za-km-z]{32}$/ : /^eip155:[1-9][0-9]{0,15}$/;
175
- if (!syntax.test(selected)) {
285
+ const valid = wallet.chain === "solana" ? /^solana:[1-9A-HJ-NP-Za-km-z]{32}$/.test(selected) : isEvmChainId(selected);
286
+ if (!valid) {
176
287
  throw new Error(`Use a ${wallet.chain} network for this wallet`);
177
288
  }
178
289
  return `${selected}:${wallet.address}`;
@@ -182,6 +293,13 @@ function isWalletParticipantRoute(path) {
182
293
  path
183
294
  );
184
295
  }
296
+ function isEvmChainId(value) {
297
+ return /^eip155:[1-9][0-9]{0,15}$/.test(value);
298
+ }
299
+ var evmChainIdSchema = z2.custom(
300
+ (value) => typeof value === "string" && isEvmChainId(value),
301
+ 'Use an EVM chain ID such as "eip155:8453"'
302
+ );
185
303
  var units = z2.string().regex(/^(0|[1-9][0-9]*)$/);
186
304
  var walletBalanceSchema = z2.object({
187
305
  /** Canonical CAIP-2 ID: `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` or `eip155:<chain ID>`. */
@@ -202,12 +320,27 @@ function isWalletSignInRoute(path) {
202
320
  }
203
321
 
204
322
  export {
205
- authScopeSchema,
206
- principalSchema,
207
- sessionSchema,
208
- memberSummarySchema,
209
- exchangeSchema,
210
- exchangeResultSchema,
323
+ profileVisibilitySchema,
324
+ avatarProviderSchema,
325
+ profileDefaultProviderSchema,
326
+ profileDefaultsSchema,
327
+ avatarSeedSchema,
328
+ profileAvatarSchema,
329
+ profileSummarySchema,
330
+ displayNameSchema,
331
+ profileUpdateSchema,
332
+ ownProfileSchema,
333
+ profileCompletionQuerySchema,
334
+ profileCompletionSchema,
335
+ profileCompletionPageSchema,
336
+ profileReferralSchema,
337
+ profileSettingsSchema,
338
+ profileSettingsInputSchema,
339
+ profileModerationSchema,
340
+ managedProfileSchema,
341
+ AVATAR_UPLOAD_LIMIT,
342
+ avatarUploadTypes,
343
+ isProfileParticipantRoute,
211
344
  solanaAddressSchema,
212
345
  walletConnectionSchema,
213
346
  walletChallengeInputSchema,
@@ -233,6 +366,8 @@ export {
233
366
  walletSignInNetwork,
234
367
  caip10,
235
368
  isWalletParticipantRoute,
369
+ isEvmChainId,
370
+ evmChainIdSchema,
236
371
  walletBalanceSchema,
237
372
  isWalletSignInRoute
238
373
  };
@@ -91,25 +91,58 @@ var trackerContentSchema = z2.strictObject({
91
91
  })
92
92
  ])
93
93
  });
94
+ var identityKindSchema = z2.enum(["wallet", "x", "discord", "member"]);
95
+ var accountRoleSchema = z2.string().regex(
96
+ /^[a-zA-Z][a-zA-Z0-9_]{0,39}$/,
97
+ "Name roles like author or recipient: a letter, then letters, digits or underscores"
98
+ );
99
+ var xAccountRoles = ["author", "inReplyTo"];
100
+ var distinct = (values) => new Set(values).size === values.length;
101
+ var xSearchSourceSchema = z2.object({
102
+ kind: z2.literal("x-search"),
103
+ query: z2.string().trim().min(1).max(2e3)
104
+ }).strict();
105
+ var customSourceSchema = z2.object({
106
+ kind: z2.literal("custom"),
107
+ namespace: identifier,
108
+ /**
109
+ * The identity kinds a record's author and named accounts can be, attributed to members
110
+ * through verified links. Omitted when authors are opaque IDs, which no quest can pay.
111
+ */
112
+ identities: z2.array(identityKindSchema).min(1).max(4).refine(distinct, "List each identity kind once").optional(),
113
+ /** Roles of the named accounts records can carry besides their author, such as `recipient`. */
114
+ accounts: z2.array(accountRoleSchema).min(1).max(10).refine(distinct, "List each account role once").refine(
115
+ (roles) => !roles.includes("author"),
116
+ "author is every record's own role; name other accounts"
117
+ ).optional(),
118
+ /**
119
+ * How trackers published before identity kinds stored `identities: ["wallet"]`. Reads return
120
+ * those definitions as stored; write `identities` instead.
121
+ *
122
+ * @deprecated Use `identities: ["wallet"]`.
123
+ */
124
+ authors: z2.literal("wallet").optional()
125
+ }).strict().refine(
126
+ (source) => !(source.authors && source.identities),
127
+ "Use identities, not authors"
128
+ ).refine(
129
+ (source) => !source.accounts || source.identities,
130
+ "Named accounts need identities"
131
+ );
94
132
  var trackerSourceSchema = z2.discriminatedUnion("kind", [
95
- z2.object({
96
- kind: z2.literal("x-search"),
97
- query: z2.string().trim().min(1).max(2e3)
98
- }).strict(),
99
- z2.object({
100
- kind: z2.literal("custom"),
101
- namespace: identifier,
102
- /**
103
- * Record authors are canonical CAIP-10 wallet account IDs, attributed to members through
104
- * their verified wallet links. Omitted when authors are opaque IDs.
105
- */
106
- authors: z2.literal("wallet").optional()
107
- }).strict()
133
+ xSearchSourceSchema,
134
+ customSourceSchema
108
135
  ]);
136
+ function sourceIdentities(source) {
137
+ if (source.kind === "x-search") {
138
+ return ["x"];
139
+ }
140
+ return source.identities ?? (source.authors === "wallet" ? ["wallet"] : void 0);
141
+ }
109
142
  var x = {
110
- search: (input) => trackerSourceSchema.options[0].parse({ kind: "x-search", ...input })
143
+ search: (input) => xSearchSourceSchema.parse({ kind: "x-search", ...input })
111
144
  };
112
- var customSource = (namespace, options = {}) => trackerSourceSchema.options[1].parse({
145
+ var customSource = (namespace, options = {}) => customSourceSchema.parse({
113
146
  kind: "custom",
114
147
  namespace,
115
148
  ...options
@@ -155,14 +188,25 @@ var trackerControlSchema = z2.object({
155
188
  actionId: identifier,
156
189
  action: z2.enum(["pause", "resume", "refresh"])
157
190
  }).strict();
191
+ var trackerAccountSchema = z2.strictObject({
192
+ kind: identityKindSchema.optional(),
193
+ id: externalId
194
+ });
158
195
  var trackerRecordInputSchema = z2.object({
159
196
  id: externalId,
160
197
  occurredAt: timestamp,
161
198
  observedAt: timestamp,
162
199
  author: z2.object({
163
200
  id: externalId,
164
- verified: z2.boolean().nullable().default(null)
201
+ verified: z2.boolean().nullable().default(null),
202
+ /** The author's identity kind; needed when the source names more than one. */
203
+ kind: identityKindSchema.optional()
165
204
  }).strict().nullable().default(null),
205
+ /** Named accounts besides the author, by the roles the custom source declares. */
206
+ accounts: z2.record(accountRoleSchema, trackerAccountSchema).refine(
207
+ (accounts) => Object.keys(accounts).length <= 10,
208
+ "At most 10 accounts"
209
+ ).optional(),
166
210
  data: z2.record(z2.string(), z2.json()),
167
211
  removed: z2.boolean().default(false)
168
212
  }).strict().refine(
@@ -182,7 +226,16 @@ var trackerIngestSchema = z2.object({
182
226
  var trackerIngestResultSchema = z2.object({
183
227
  stored: count,
184
228
  /** Tracker-trigger decisions this ingest caused. Absent from servers without tracker triggers. */
185
- admissions: z2.object({ admitted: count, skipped: count }).optional()
229
+ admissions: z2.object({
230
+ admitted: count,
231
+ skipped: count,
232
+ /**
233
+ * Observations a quest's firing mode selected but its `where` filter did not match, counted
234
+ * per quest like `admitted` and `skipped`. They record no outcome. Present only when
235
+ * nonzero.
236
+ */
237
+ filtered: count.optional()
238
+ }).optional()
186
239
  });
187
240
  var trackerOutcomeFields = {
188
241
  /** Stable quest ID. */
@@ -200,10 +253,37 @@ var trackerOutcomeFields = {
200
253
  /** Null for automatic decisions; the staff actor after a retry. */
201
254
  actor: z2.string().nullable()
202
255
  };
256
+ var trackerSkipCodes = [
257
+ /** The quest is paused or no longer active. */
258
+ "quest-paused",
259
+ /** The record occurred before the quest was published. */
260
+ "before-activation",
261
+ /** The record is marked removed. */
262
+ "record-removed",
263
+ /** The captured X post of this observation cannot be read. */
264
+ "content-unavailable",
265
+ /** The record has no account in the beneficiary role, such as a post that is not a reply. */
266
+ "no-account",
267
+ /**
268
+ * The beneficiary account is the record's author account, such as a reply to oneself, or both
269
+ * belong to the same member. A different account is judged once it resolves to a member, after
270
+ * `unlinked-account` and `ambiguous-account`.
271
+ */
272
+ "beneficiary-is-author",
273
+ /** No member has verified the beneficiary account. */
274
+ "unlinked-account",
275
+ /** More than one member has the beneficiary account. */
276
+ "ambiguous-account",
277
+ /** The attributed member has not joined the project. */
278
+ "not-joined",
279
+ /** The attributed member has not completed the quest's prerequisites. */
280
+ "prerequisites-incomplete"
281
+ ];
203
282
  var trackerOutcomeSchema = z2.discriminatedUnion("state", [
204
283
  z2.strictObject({
205
284
  ...trackerOutcomeFields,
206
285
  state: z2.literal("admitted"),
286
+ code: z2.null(),
207
287
  reason: z2.null(),
208
288
  /** The attributed member. */
209
289
  member: identifier,
@@ -213,7 +293,9 @@ var trackerOutcomeSchema = z2.discriminatedUnion("state", [
213
293
  z2.strictObject({
214
294
  ...trackerOutcomeFields,
215
295
  state: z2.literal("skipped"),
216
- /** Why the observation was skipped. */
296
+ /** Why the observation was skipped, as one of `trackerSkipCodes`. */
297
+ code: z2.string().min(1),
298
+ /** Why the observation was skipped, for people. */
217
299
  reason: z2.string(),
218
300
  /** The attributed member, when attribution got that far. */
219
301
  member: identifier.nullable(),
@@ -226,6 +308,8 @@ var trackerOutcomeQuerySchema = z2.strictObject({
226
308
  record: externalId.optional(),
227
309
  member: identifier.optional(),
228
310
  state: z2.enum(["admitted", "skipped"]).optional(),
311
+ /** Only skips with this code, such as `unlinked-account`. */
312
+ code: z2.string().min(1).max(100).optional(),
229
313
  limit: z2.coerce.number().int().min(1).max(100).default(25),
230
314
  /** Opaque cursor from `next`: older outcomes. */
231
315
  before: z2.string().max(512).optional()
@@ -289,7 +373,7 @@ var trackerPreviewLimits = {
289
373
  days: 30
290
374
  };
291
375
  var trackerPreviewInputSchema = z2.object({
292
- query: trackerSourceSchema.options[0].shape.query,
376
+ query: xSearchSourceSchema.shape.query,
293
377
  /** Start of the searched window. The window ends when the sample is fetched. */
294
378
  since: timestamp
295
379
  }).strict();
@@ -499,36 +583,88 @@ var streakProgressSchema = z4.object({
499
583
  import { z as z5 } from "zod";
500
584
  var timestamp3 = z5.number().int().safe().nonnegative().max(864e13);
501
585
  var count2 = z5.number().int().safe().nonnegative();
502
- var trackerBeneficiarySchema = z5.enum(["author", "replied-to"]);
586
+ var trackerTriggerModeSchema = z5.enum([
587
+ "new-record",
588
+ "new-observation",
589
+ "data-changed"
590
+ ]);
591
+ function defaultTriggerMode(source) {
592
+ return source === "x-search" ? "new-record" : "new-observation";
593
+ }
594
+ var trackerBoundSchema = z5.union([
595
+ z5.number().finite(),
596
+ z5.strictObject({ setting: z5.string().regex(/^[a-zA-Z][a-zA-Z0-9_]*$/) })
597
+ ]);
598
+ var dataPath = z5.string().max(200).regex(
599
+ /^[^.\s]+(\.[^.\s]+)*$/,
600
+ "Use dot-separated keys, such as metrics.likes"
601
+ );
602
+ var trackerWhereSchema = z5.union([
603
+ z5.strictObject({
604
+ path: dataPath,
605
+ equals: z5.union([z5.string().max(1e3), z5.number().finite(), z5.boolean()])
606
+ }),
607
+ z5.strictObject({
608
+ path: dataPath,
609
+ gt: trackerBoundSchema.optional(),
610
+ gte: trackerBoundSchema.optional(),
611
+ lt: trackerBoundSchema.optional(),
612
+ lte: trackerBoundSchema.optional()
613
+ }).refine(
614
+ (where) => [where.gt, where.gte, where.lt, where.lte].some(
615
+ (bound) => bound !== void 0
616
+ ),
617
+ "Compare with equals, gt, gte, lt or lte"
618
+ )
619
+ ]);
503
620
  var trackerTriggerPolicySchema = z5.strictObject({
504
621
  /** The tracker's authoring key; publication binds it to the tracker's stable ID. */
505
622
  tracker: identifier,
506
623
  source: z5.enum(["x-search", "custom"]),
507
- beneficiary: trackerBeneficiarySchema
624
+ /** Which observations fire; absent means the source's default (`defaultTriggerMode`). */
625
+ on: trackerTriggerModeSchema.optional(),
626
+ where: trackerWhereSchema.optional(),
627
+ /**
628
+ * The record account the quest pays: `author`, `inReplyTo` for an X post, or a named account of
629
+ * a custom record. Relay attributes it through verified links; evaluators cannot redirect it.
630
+ * Releases published before account roles store `"replied-to"` for `inReplyTo`.
631
+ */
632
+ beneficiary: z5.union([accountRoleSchema, z5.literal("replied-to")])
508
633
  });
509
- var accountId = z5.string().min(5).max(256);
634
+ function triggerMode(policy) {
635
+ return policy.on ?? defaultTriggerMode(policy.source);
636
+ }
637
+ function beneficiaryRole(policy) {
638
+ return policy.beneficiary === "replied-to" ? "inReplyTo" : policy.beneficiary;
639
+ }
640
+ var xLink = {
641
+ issuer: z5.string().min(1),
642
+ /** The account's stable user ID. */
643
+ subject: z5.string().min(1).max(256),
644
+ /** The member's account selection revision. */
645
+ revision: count2,
646
+ /** When the member linked the account; null when unknown. */
647
+ linkedAt: timestamp3.nullable()
648
+ };
510
649
  var trackerAttributionSchema = z5.strictObject({
511
650
  member: identifier,
512
651
  capturedAt: timestamp3,
513
652
  account: z5.discriminatedUnion("provider", [
514
653
  z5.strictObject({
515
654
  provider: z5.literal("wallet"),
516
- /** Canonical CAIP-10 account ID, as the record's author. */
517
- id: accountId,
655
+ /** Canonical CAIP-10 account ID, as the record names it. */
656
+ id: z5.string().min(5).max(256),
518
657
  /** The wallet link's revision. */
519
658
  revision: count2,
520
659
  /** When the member verified the wallet. */
521
660
  linkedAt: timestamp3.nullable()
522
661
  }),
662
+ z5.strictObject({ provider: z5.literal("x"), ...xLink }),
663
+ z5.strictObject({ provider: z5.literal("discord"), ...xLink }),
523
664
  z5.strictObject({
524
- provider: z5.literal("x"),
525
- issuer: z5.string().min(1),
526
- /** The X account's stable user ID. */
527
- subject: z5.string().min(1).max(256),
528
- /** The member's X account selection revision. */
529
- revision: count2,
530
- /** When the member linked the X account; null when unknown. */
531
- linkedAt: timestamp3.nullable()
665
+ provider: z5.literal("member"),
666
+ /** The member ID the record names. */
667
+ id: identifier
532
668
  })
533
669
  ])
534
670
  });
@@ -540,8 +676,10 @@ var trackerTriggerRecordSchema = z5.strictObject({
540
676
  firstSeenAt: timestamp3,
541
677
  author: z5.strictObject({
542
678
  id: z5.string().min(1).max(256),
543
- verified: z5.boolean().nullable()
679
+ verified: z5.boolean().nullable(),
680
+ kind: identityKindSchema.optional()
544
681
  }).nullable(),
682
+ accounts: z5.record(accountRoleSchema, trackerAccountSchema).optional(),
545
683
  data: z5.record(z5.string(), z5.json()),
546
684
  removed: z5.boolean()
547
685
  });
@@ -550,7 +688,11 @@ var trackerTriggerContextSchema = z5.strictObject({
550
688
  tracker: identifier,
551
689
  /** The tracker's authoring key. */
552
690
  key: identifier,
553
- beneficiary: trackerBeneficiarySchema,
691
+ /**
692
+ * The record account the attempt pays, as the quest's release names it. Releases published
693
+ * before account roles name `inReplyTo` `"replied-to"`, which their bundled evaluators expect.
694
+ */
695
+ beneficiary: z5.union([accountRoleSchema, z5.literal("replied-to")]),
554
696
  record: trackerTriggerRecordSchema,
555
697
  /** The captured X post of this observation; null for custom trackers. */
556
698
  x: z5.strictObject({
@@ -1525,7 +1667,13 @@ export {
1525
1667
  trackerContentReadSchema,
1526
1668
  trackerEvidenceSchema,
1527
1669
  trackerContentSchema,
1670
+ identityKindSchema,
1671
+ accountRoleSchema,
1672
+ xAccountRoles,
1673
+ xSearchSourceSchema,
1674
+ customSourceSchema,
1528
1675
  trackerSourceSchema,
1676
+ sourceIdentities,
1529
1677
  x,
1530
1678
  customSource,
1531
1679
  trackerDefinitionSchema,
@@ -1534,10 +1682,12 @@ export {
1534
1682
  publishedTrackerSchema,
1535
1683
  trackerStatusSchema,
1536
1684
  trackerControlSchema,
1685
+ trackerAccountSchema,
1537
1686
  trackerRecordInputSchema,
1538
1687
  trackerRecordSchema,
1539
1688
  trackerIngestSchema,
1540
1689
  trackerIngestResultSchema,
1690
+ trackerSkipCodes,
1541
1691
  trackerOutcomeSchema,
1542
1692
  trackerOutcomeQuerySchema,
1543
1693
  trackerOutcomePageSchema,
@@ -1570,8 +1720,13 @@ export {
1570
1720
  streakPolicySchema,
1571
1721
  streak,
1572
1722
  streakProgressSchema,
1573
- trackerBeneficiarySchema,
1723
+ trackerTriggerModeSchema,
1724
+ defaultTriggerMode,
1725
+ trackerBoundSchema,
1726
+ trackerWhereSchema,
1574
1727
  trackerTriggerPolicySchema,
1728
+ triggerMode,
1729
+ beneficiaryRole,
1575
1730
  trackerAttributionSchema,
1576
1731
  trackerTriggerRecordSchema,
1577
1732
  trackerTriggerContextSchema,