@ttt-productions/ttt-core 0.78.22 → 0.78.24

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 (128) hide show
  1. package/dist/constants/business-user.d.ts +1 -1
  2. package/dist/constants/business-user.js +1 -1
  3. package/dist/constants/business-user.js.map +1 -1
  4. package/dist/constants/release-flags.d.ts +2 -2
  5. package/dist/constants/release-flags.d.ts.map +1 -1
  6. package/dist/constants/release-flags.js +2 -2
  7. package/dist/constants/release-flags.js.map +1 -1
  8. package/dist/doc-schemas/chat-sync.d.ts.map +1 -1
  9. package/dist/doc-schemas/chat-sync.js +3 -2
  10. package/dist/doc-schemas/chat-sync.js.map +1 -1
  11. package/dist/doc-schemas/commissions.d.ts +14 -11
  12. package/dist/doc-schemas/commissions.d.ts.map +1 -1
  13. package/dist/doc-schemas/commissions.js +14 -4
  14. package/dist/doc-schemas/commissions.js.map +1 -1
  15. package/dist/doc-schemas/media-activation-jobs.d.ts.map +1 -1
  16. package/dist/doc-schemas/media-activation-jobs.js +4 -3
  17. package/dist/doc-schemas/media-activation-jobs.js.map +1 -1
  18. package/dist/doc-schemas/media-assets.d.ts +2 -2
  19. package/dist/doc-schemas/media-assets.d.ts.map +1 -1
  20. package/dist/doc-schemas/media-assets.js +5 -4
  21. package/dist/doc-schemas/media-assets.js.map +1 -1
  22. package/dist/doc-schemas/messaging.d.ts.map +1 -1
  23. package/dist/doc-schemas/messaging.js +3 -2
  24. package/dist/doc-schemas/messaging.js.map +1 -1
  25. package/dist/doc-schemas/ncii/allegations.js +3 -3
  26. package/dist/doc-schemas/ncii/allegations.js.map +1 -1
  27. package/dist/doc-schemas/ncii/cases.d.ts.map +1 -1
  28. package/dist/doc-schemas/ncii/cases.js +4 -3
  29. package/dist/doc-schemas/ncii/cases.js.map +1 -1
  30. package/dist/doc-schemas/ncii/config.d.ts.map +1 -1
  31. package/dist/doc-schemas/ncii/config.js +4 -3
  32. package/dist/doc-schemas/ncii/config.js.map +1 -1
  33. package/dist/doc-schemas/ncii/holds.js +3 -3
  34. package/dist/doc-schemas/ncii/holds.js.map +1 -1
  35. package/dist/doc-schemas/ncii/removal.js +3 -3
  36. package/dist/doc-schemas/ncii/removal.js.map +1 -1
  37. package/dist/doc-schemas/ncii/requests.d.ts.map +1 -1
  38. package/dist/doc-schemas/ncii/requests.js +4 -3
  39. package/dist/doc-schemas/ncii/requests.js.map +1 -1
  40. package/dist/doc-schemas/notification-ledger.d.ts.map +1 -1
  41. package/dist/doc-schemas/notification-ledger.js +3 -1
  42. package/dist/doc-schemas/notification-ledger.js.map +1 -1
  43. package/dist/doc-schemas/payments.d.ts.map +1 -1
  44. package/dist/doc-schemas/payments.js +2 -1
  45. package/dist/doc-schemas/payments.js.map +1 -1
  46. package/dist/doc-schemas/registry.d.ts +108 -35
  47. package/dist/doc-schemas/registry.d.ts.map +1 -1
  48. package/dist/doc-schemas/registry.js +4 -0
  49. package/dist/doc-schemas/registry.js.map +1 -1
  50. package/dist/doc-schemas/safety/age.d.ts.map +1 -1
  51. package/dist/doc-schemas/safety/age.js +4 -3
  52. package/dist/doc-schemas/safety/age.js.map +1 -1
  53. package/dist/doc-schemas/safety/case-aliases.d.ts.map +1 -1
  54. package/dist/doc-schemas/safety/case-aliases.js +5 -4
  55. package/dist/doc-schemas/safety/case-aliases.js.map +1 -1
  56. package/dist/doc-schemas/safety/case.d.ts.map +1 -1
  57. package/dist/doc-schemas/safety/case.js +4 -3
  58. package/dist/doc-schemas/safety/case.js.map +1 -1
  59. package/dist/doc-schemas/safety/evidence.js +3 -3
  60. package/dist/doc-schemas/safety/evidence.js.map +1 -1
  61. package/dist/doc-schemas/safety/foundation.d.ts.map +1 -1
  62. package/dist/doc-schemas/safety/foundation.js +5 -3
  63. package/dist/doc-schemas/safety/foundation.js.map +1 -1
  64. package/dist/doc-schemas/safety/holds.d.ts.map +1 -1
  65. package/dist/doc-schemas/safety/holds.js +4 -3
  66. package/dist/doc-schemas/safety/holds.js.map +1 -1
  67. package/dist/doc-schemas/safety/monitors.d.ts.map +1 -1
  68. package/dist/doc-schemas/safety/monitors.js +5 -3
  69. package/dist/doc-schemas/safety/monitors.js.map +1 -1
  70. package/dist/doc-schemas/safety/provenance.js +3 -3
  71. package/dist/doc-schemas/safety/provenance.js.map +1 -1
  72. package/dist/doc-schemas/safety/report.d.ts.map +1 -1
  73. package/dist/doc-schemas/safety/report.js +4 -3
  74. package/dist/doc-schemas/safety/report.js.map +1 -1
  75. package/dist/doc-schemas/safety/sagas.js +3 -3
  76. package/dist/doc-schemas/safety/sagas.js.map +1 -1
  77. package/dist/doc-schemas/social.d.ts +130 -0
  78. package/dist/doc-schemas/social.d.ts.map +1 -1
  79. package/dist/doc-schemas/social.js +91 -2
  80. package/dist/doc-schemas/social.js.map +1 -1
  81. package/dist/doc-schemas/square-announcement-jobs.d.ts +306 -14
  82. package/dist/doc-schemas/square-announcement-jobs.d.ts.map +1 -1
  83. package/dist/doc-schemas/square-announcement-jobs.js +15 -2
  84. package/dist/doc-schemas/square-announcement-jobs.js.map +1 -1
  85. package/dist/doc-schemas/user.js +3 -3
  86. package/dist/doc-schemas/user.js.map +1 -1
  87. package/dist/doc-schemas/work-project.js +2 -2
  88. package/dist/doc-schemas/work-project.js.map +1 -1
  89. package/dist/ids/chat-ids.d.ts +3 -2
  90. package/dist/ids/chat-ids.d.ts.map +1 -1
  91. package/dist/ids/chat-ids.js +3 -2
  92. package/dist/ids/chat-ids.js.map +1 -1
  93. package/dist/media/domain-events-admin.d.ts +0 -7
  94. package/dist/media/domain-events-admin.d.ts.map +1 -1
  95. package/dist/media/domain-events-admin.js +0 -11
  96. package/dist/media/domain-events-admin.js.map +1 -1
  97. package/dist/media/domain-events.d.ts +0 -6
  98. package/dist/media/domain-events.d.ts.map +1 -1
  99. package/dist/media/domain-events.js +1 -2
  100. package/dist/media/domain-events.js.map +1 -1
  101. package/dist/media/hall-library-target-fields.js +1 -1
  102. package/dist/media/hall-library-target-fields.js.map +1 -1
  103. package/dist/media/pending-media.d.ts +0 -54
  104. package/dist/media/pending-media.d.ts.map +1 -1
  105. package/dist/media/photodna-coverage.d.ts.map +1 -1
  106. package/dist/media/photodna-coverage.js +5 -3
  107. package/dist/media/photodna-coverage.js.map +1 -1
  108. package/dist/paths/related-ids.js +1 -1
  109. package/dist/paths/related-ids.js.map +1 -1
  110. package/dist/safety/ncii-intake-derivations.d.ts.map +1 -1
  111. package/dist/safety/ncii-intake-derivations.js +4 -2
  112. package/dist/safety/ncii-intake-derivations.js.map +1 -1
  113. package/dist/safety/resource-keys.d.ts +8 -0
  114. package/dist/safety/resource-keys.d.ts.map +1 -1
  115. package/dist/safety/resource-keys.js +12 -1
  116. package/dist/safety/resource-keys.js.map +1 -1
  117. package/dist/schemas/chat.js +3 -3
  118. package/dist/schemas/chat.js.map +1 -1
  119. package/dist/schemas/ncii.js +1 -1
  120. package/dist/schemas/ncii.js.map +1 -1
  121. package/dist/schemas/notification.d.ts +8 -8
  122. package/dist/schemas/notification.d.ts.map +1 -1
  123. package/dist/schemas/notification.js +17 -11
  124. package/dist/schemas/notification.js.map +1 -1
  125. package/dist/types/social.d.ts +1 -45
  126. package/dist/types/social.d.ts.map +1 -1
  127. package/dist/types/social.js.map +1 -1
  128. package/package.json +3 -3
@@ -1,6 +1,5 @@
1
1
  import { z } from 'zod';
2
2
  import type { SquareStreetzPostType } from './social.js';
3
- import type { SquareStreetzPostPayload } from '../types/social.js';
4
3
  /**
5
4
  * The ONE canonical derivation of a Square announcement outbox job id (ARCH-102 —
6
5
  * every enqueue site, the outbox worker, and tests derive from HERE, never a
@@ -12,18 +11,115 @@ import type { SquareStreetzPostPayload } from '../types/social.js';
12
11
  */
13
12
  export declare function buildSquareAnnouncementJobId(announcementType: SquareStreetzPostType, primaryDocId: string): string;
14
13
  /**
15
- * Payload half of the announcement input — exactly what the
16
- * runManageSquareStreetzPost dispatcher accepts: the canonical
17
- * SquareStreetzPostPayload plus the two dispatcher-level extras (`projectId`,
18
- * and the pattern-C pre-minted `postId` for USER_POST). Validated structurally
19
- * (a plain object) and TYPED precisely; the dispatcher re-validates domain
20
- * fields when the worker delivers (same posture as chatMessageOutbox.payload).
14
+ * Payload half of the announcement input — exactly what the runManageSquareStreetzPost
15
+ * dispatcher accepts: the canonical `SquareStreetzPostPayloadSchema` plus the two
16
+ * dispatcher-level extras (`projectId`, and the pattern-C pre-minted `postId` for
17
+ * USER_POST). Derived from the ONE payload schema (ARCH-102) so the durable outbox row is
18
+ * field-validated, not merely checked for object-ness. NON-strict / no pairing refinement:
19
+ * it is parsed at ENQUEUE inside the announcing transaction, so a throw would fail the
20
+ * primary action over an announcement defect (ENG-009); the post core enforces the
21
+ * `mediaAssetId`↔`mediaType` pairing at DELIVERY, where a failure dead-letters the job.
21
22
  */
22
- export type SquareAnnouncementPayload = SquareStreetzPostPayload & {
23
- projectId?: string;
24
- postId?: string;
25
- };
26
- export declare const SquareAnnouncementPayloadSchema: z.ZodCustom<SquareAnnouncementPayload, SquareAnnouncementPayload>;
23
+ export declare const SquareAnnouncementPayloadSchema: z.ZodObject<{
24
+ userId: z.ZodString;
25
+ mentions: z.ZodOptional<z.ZodArray<z.ZodObject<{
26
+ placeholder: z.ZodString;
27
+ type: z.ZodEnum<{
28
+ workRealm: "workRealm";
29
+ workProject: "workProject";
30
+ audition: "audition";
31
+ user: "user";
32
+ commission: "commission";
33
+ }>;
34
+ id: z.ZodString;
35
+ }, z.core.$strict>>>;
36
+ newMediaAssetId: z.ZodOptional<z.ZodString>;
37
+ craftSkill: z.ZodOptional<z.ZodObject<{
38
+ id: z.ZodString;
39
+ name: z.ZodString;
40
+ mediaAssetId: z.ZodString;
41
+ type: z.ZodEnum<{
42
+ video: "video";
43
+ image: "image";
44
+ audio: "audio";
45
+ }>;
46
+ tags: z.ZodOptional<z.ZodArray<z.ZodEnum<{
47
+ acting: "acting";
48
+ "voice-over": "voice-over";
49
+ singing: "singing";
50
+ rapping: "rapping";
51
+ "instrumental-performance": "instrumental-performance";
52
+ "dance-choreography": "dance-choreography";
53
+ "stand-up-sketch-comedy": "stand-up-sketch-comedy";
54
+ "writing-storytelling": "writing-storytelling";
55
+ songwriting: "songwriting";
56
+ "poetry-spoken-word": "poetry-spoken-word";
57
+ "drawing-illustration": "drawing-illustration";
58
+ painting: "painting";
59
+ animation: "animation";
60
+ "graphic-design": "graphic-design";
61
+ photography: "photography";
62
+ "cinematography-camera": "cinematography-camera";
63
+ "video-editing": "video-editing";
64
+ "visual-effects": "visual-effects";
65
+ directing: "directing";
66
+ "costume-makeup": "costume-makeup";
67
+ "set-prop-design": "set-prop-design";
68
+ "music-production": "music-production";
69
+ "composing-scoring": "composing-scoring";
70
+ "sound-design": "sound-design";
71
+ }>>>;
72
+ kind: z.ZodOptional<z.ZodEnum<{
73
+ original: "original";
74
+ mimicOnTtt: "mimicOnTtt";
75
+ mimicOffTtt: "mimicOffTtt";
76
+ }>>;
77
+ source: z.ZodOptional<z.ZodObject<{
78
+ type: z.ZodEnum<{
79
+ workProject: "workProject";
80
+ user: "user";
81
+ }>;
82
+ id: z.ZodString;
83
+ }, z.core.$strict>>;
84
+ }, z.core.$strip>>;
85
+ craftSkillId: z.ZodOptional<z.ZodString>;
86
+ workProjectTitle: z.ZodOptional<z.ZodString>;
87
+ workProjectId: z.ZodOptional<z.ZodString>;
88
+ workProjectType: z.ZodOptional<z.ZodEnum<{
89
+ Tales: "Tales";
90
+ Tunes: "Tunes";
91
+ Television: "Television";
92
+ }>>;
93
+ workProjectDescription: z.ZodOptional<z.ZodString>;
94
+ workRealmId: z.ZodOptional<z.ZodString>;
95
+ workRealmTitle: z.ZodOptional<z.ZodString>;
96
+ hallItemId: z.ZodOptional<z.ZodString>;
97
+ hallItemTitle: z.ZodOptional<z.ZodString>;
98
+ hallSubItemType: z.ZodOptional<z.ZodEnum<{
99
+ chapter: "chapter";
100
+ track: "track";
101
+ episode: "episode";
102
+ }>>;
103
+ content: z.ZodOptional<z.ZodString>;
104
+ mediaAssetId: z.ZodOptional<z.ZodString>;
105
+ mediaType: z.ZodOptional<z.ZodEnum<{
106
+ video: "video";
107
+ image: "image";
108
+ audio: "audio";
109
+ other: "other";
110
+ }>>;
111
+ createdAt: z.ZodOptional<z.ZodNumber>;
112
+ auditionId: z.ZodOptional<z.ZodString>;
113
+ commissionListingId: z.ZodOptional<z.ZodString>;
114
+ auditionAnnounceKind: z.ZodOptional<z.ZodEnum<{
115
+ work: "work";
116
+ platform: "platform";
117
+ sponsored: "sponsored";
118
+ }>>;
119
+ projectId: z.ZodOptional<z.ZodString>;
120
+ postId: z.ZodOptional<z.ZodString>;
121
+ }, z.core.$strip>;
122
+ export type SquareAnnouncementPayload = z.infer<typeof SquareAnnouncementPayloadSchema>;
27
123
  /** The discriminated announcement input (`{ type, payload }`) the job carries. */
28
124
  export declare const SquareAnnouncementInputSchema: z.ZodObject<{
29
125
  type: z.ZodEnum<{
@@ -38,7 +134,105 @@ export declare const SquareAnnouncementInputSchema: z.ZodObject<{
38
134
  NEW_AUDITION: "NEW_AUDITION";
39
135
  NEW_COMMISSION: "NEW_COMMISSION";
40
136
  }>;
41
- payload: z.ZodCustom<SquareAnnouncementPayload, SquareAnnouncementPayload>;
137
+ payload: z.ZodObject<{
138
+ userId: z.ZodString;
139
+ mentions: z.ZodOptional<z.ZodArray<z.ZodObject<{
140
+ placeholder: z.ZodString;
141
+ type: z.ZodEnum<{
142
+ workRealm: "workRealm";
143
+ workProject: "workProject";
144
+ audition: "audition";
145
+ user: "user";
146
+ commission: "commission";
147
+ }>;
148
+ id: z.ZodString;
149
+ }, z.core.$strict>>>;
150
+ newMediaAssetId: z.ZodOptional<z.ZodString>;
151
+ craftSkill: z.ZodOptional<z.ZodObject<{
152
+ id: z.ZodString;
153
+ name: z.ZodString;
154
+ mediaAssetId: z.ZodString;
155
+ type: z.ZodEnum<{
156
+ video: "video";
157
+ image: "image";
158
+ audio: "audio";
159
+ }>;
160
+ tags: z.ZodOptional<z.ZodArray<z.ZodEnum<{
161
+ acting: "acting";
162
+ "voice-over": "voice-over";
163
+ singing: "singing";
164
+ rapping: "rapping";
165
+ "instrumental-performance": "instrumental-performance";
166
+ "dance-choreography": "dance-choreography";
167
+ "stand-up-sketch-comedy": "stand-up-sketch-comedy";
168
+ "writing-storytelling": "writing-storytelling";
169
+ songwriting: "songwriting";
170
+ "poetry-spoken-word": "poetry-spoken-word";
171
+ "drawing-illustration": "drawing-illustration";
172
+ painting: "painting";
173
+ animation: "animation";
174
+ "graphic-design": "graphic-design";
175
+ photography: "photography";
176
+ "cinematography-camera": "cinematography-camera";
177
+ "video-editing": "video-editing";
178
+ "visual-effects": "visual-effects";
179
+ directing: "directing";
180
+ "costume-makeup": "costume-makeup";
181
+ "set-prop-design": "set-prop-design";
182
+ "music-production": "music-production";
183
+ "composing-scoring": "composing-scoring";
184
+ "sound-design": "sound-design";
185
+ }>>>;
186
+ kind: z.ZodOptional<z.ZodEnum<{
187
+ original: "original";
188
+ mimicOnTtt: "mimicOnTtt";
189
+ mimicOffTtt: "mimicOffTtt";
190
+ }>>;
191
+ source: z.ZodOptional<z.ZodObject<{
192
+ type: z.ZodEnum<{
193
+ workProject: "workProject";
194
+ user: "user";
195
+ }>;
196
+ id: z.ZodString;
197
+ }, z.core.$strict>>;
198
+ }, z.core.$strip>>;
199
+ craftSkillId: z.ZodOptional<z.ZodString>;
200
+ workProjectTitle: z.ZodOptional<z.ZodString>;
201
+ workProjectId: z.ZodOptional<z.ZodString>;
202
+ workProjectType: z.ZodOptional<z.ZodEnum<{
203
+ Tales: "Tales";
204
+ Tunes: "Tunes";
205
+ Television: "Television";
206
+ }>>;
207
+ workProjectDescription: z.ZodOptional<z.ZodString>;
208
+ workRealmId: z.ZodOptional<z.ZodString>;
209
+ workRealmTitle: z.ZodOptional<z.ZodString>;
210
+ hallItemId: z.ZodOptional<z.ZodString>;
211
+ hallItemTitle: z.ZodOptional<z.ZodString>;
212
+ hallSubItemType: z.ZodOptional<z.ZodEnum<{
213
+ chapter: "chapter";
214
+ track: "track";
215
+ episode: "episode";
216
+ }>>;
217
+ content: z.ZodOptional<z.ZodString>;
218
+ mediaAssetId: z.ZodOptional<z.ZodString>;
219
+ mediaType: z.ZodOptional<z.ZodEnum<{
220
+ video: "video";
221
+ image: "image";
222
+ audio: "audio";
223
+ other: "other";
224
+ }>>;
225
+ createdAt: z.ZodOptional<z.ZodNumber>;
226
+ auditionId: z.ZodOptional<z.ZodString>;
227
+ commissionListingId: z.ZodOptional<z.ZodString>;
228
+ auditionAnnounceKind: z.ZodOptional<z.ZodEnum<{
229
+ work: "work";
230
+ platform: "platform";
231
+ sponsored: "sponsored";
232
+ }>>;
233
+ projectId: z.ZodOptional<z.ZodString>;
234
+ postId: z.ZodOptional<z.ZodString>;
235
+ }, z.core.$strip>;
42
236
  }, z.core.$strip>;
43
237
  export type SquareAnnouncementInput = z.infer<typeof SquareAnnouncementInputSchema>;
44
238
  export declare const SquareAnnouncementJobStatusSchema: z.ZodEnum<{
@@ -63,7 +257,105 @@ export declare const SquareAnnouncementJobSchema: z.ZodObject<{
63
257
  NEW_AUDITION: "NEW_AUDITION";
64
258
  NEW_COMMISSION: "NEW_COMMISSION";
65
259
  }>;
66
- payload: z.ZodCustom<SquareAnnouncementPayload, SquareAnnouncementPayload>;
260
+ payload: z.ZodObject<{
261
+ userId: z.ZodString;
262
+ mentions: z.ZodOptional<z.ZodArray<z.ZodObject<{
263
+ placeholder: z.ZodString;
264
+ type: z.ZodEnum<{
265
+ workRealm: "workRealm";
266
+ workProject: "workProject";
267
+ audition: "audition";
268
+ user: "user";
269
+ commission: "commission";
270
+ }>;
271
+ id: z.ZodString;
272
+ }, z.core.$strict>>>;
273
+ newMediaAssetId: z.ZodOptional<z.ZodString>;
274
+ craftSkill: z.ZodOptional<z.ZodObject<{
275
+ id: z.ZodString;
276
+ name: z.ZodString;
277
+ mediaAssetId: z.ZodString;
278
+ type: z.ZodEnum<{
279
+ video: "video";
280
+ image: "image";
281
+ audio: "audio";
282
+ }>;
283
+ tags: z.ZodOptional<z.ZodArray<z.ZodEnum<{
284
+ acting: "acting";
285
+ "voice-over": "voice-over";
286
+ singing: "singing";
287
+ rapping: "rapping";
288
+ "instrumental-performance": "instrumental-performance";
289
+ "dance-choreography": "dance-choreography";
290
+ "stand-up-sketch-comedy": "stand-up-sketch-comedy";
291
+ "writing-storytelling": "writing-storytelling";
292
+ songwriting: "songwriting";
293
+ "poetry-spoken-word": "poetry-spoken-word";
294
+ "drawing-illustration": "drawing-illustration";
295
+ painting: "painting";
296
+ animation: "animation";
297
+ "graphic-design": "graphic-design";
298
+ photography: "photography";
299
+ "cinematography-camera": "cinematography-camera";
300
+ "video-editing": "video-editing";
301
+ "visual-effects": "visual-effects";
302
+ directing: "directing";
303
+ "costume-makeup": "costume-makeup";
304
+ "set-prop-design": "set-prop-design";
305
+ "music-production": "music-production";
306
+ "composing-scoring": "composing-scoring";
307
+ "sound-design": "sound-design";
308
+ }>>>;
309
+ kind: z.ZodOptional<z.ZodEnum<{
310
+ original: "original";
311
+ mimicOnTtt: "mimicOnTtt";
312
+ mimicOffTtt: "mimicOffTtt";
313
+ }>>;
314
+ source: z.ZodOptional<z.ZodObject<{
315
+ type: z.ZodEnum<{
316
+ workProject: "workProject";
317
+ user: "user";
318
+ }>;
319
+ id: z.ZodString;
320
+ }, z.core.$strict>>;
321
+ }, z.core.$strip>>;
322
+ craftSkillId: z.ZodOptional<z.ZodString>;
323
+ workProjectTitle: z.ZodOptional<z.ZodString>;
324
+ workProjectId: z.ZodOptional<z.ZodString>;
325
+ workProjectType: z.ZodOptional<z.ZodEnum<{
326
+ Tales: "Tales";
327
+ Tunes: "Tunes";
328
+ Television: "Television";
329
+ }>>;
330
+ workProjectDescription: z.ZodOptional<z.ZodString>;
331
+ workRealmId: z.ZodOptional<z.ZodString>;
332
+ workRealmTitle: z.ZodOptional<z.ZodString>;
333
+ hallItemId: z.ZodOptional<z.ZodString>;
334
+ hallItemTitle: z.ZodOptional<z.ZodString>;
335
+ hallSubItemType: z.ZodOptional<z.ZodEnum<{
336
+ chapter: "chapter";
337
+ track: "track";
338
+ episode: "episode";
339
+ }>>;
340
+ content: z.ZodOptional<z.ZodString>;
341
+ mediaAssetId: z.ZodOptional<z.ZodString>;
342
+ mediaType: z.ZodOptional<z.ZodEnum<{
343
+ video: "video";
344
+ image: "image";
345
+ audio: "audio";
346
+ other: "other";
347
+ }>>;
348
+ createdAt: z.ZodOptional<z.ZodNumber>;
349
+ auditionId: z.ZodOptional<z.ZodString>;
350
+ commissionListingId: z.ZodOptional<z.ZodString>;
351
+ auditionAnnounceKind: z.ZodOptional<z.ZodEnum<{
352
+ work: "work";
353
+ platform: "platform";
354
+ sponsored: "sponsored";
355
+ }>>;
356
+ projectId: z.ZodOptional<z.ZodString>;
357
+ postId: z.ZodOptional<z.ZodString>;
358
+ }, z.core.$strip>;
67
359
  }, z.core.$strip>;
68
360
  source: z.ZodRecord<z.ZodString, z.ZodString>;
69
361
  status: z.ZodEnum<{
@@ -1 +1 @@
1
- {"version":3,"file":"square-announcement-jobs.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/square-announcement-jobs.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAEnE;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAC1C,gBAAgB,EAAE,qBAAqB,EACvC,YAAY,EAAE,MAAM,GACnB,MAAM,CAER;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,yBAAyB,GAAG,wBAAwB,GAAG;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,+BAA+B,mEAG3C,CAAC;AAEF,kFAAkF;AAClF,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;iBAGxC,CAAC;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAEpF,eAAO,MAAM,iCAAiC;;;;;EAK5C,CAAC;AACH,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAC;AAE5F,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAe7B,CAAC;AACZ,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC"}
1
+ {"version":3,"file":"square-announcement-jobs.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/square-announcement-jobs.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEzD;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAC1C,gBAAgB,EAAE,qBAAqB,EACvC,YAAY,EAAE,MAAM,GACnB,MAAM,CAER;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAG1C,CAAC;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AAExF,kFAAkF;AAClF,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGxC,CAAC;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAEpF,eAAO,MAAM,iCAAiC;;;;;EAK5C,CAAC;AACH,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAC;AAE5F,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAe7B,CAAC;AACZ,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC"}
@@ -16,7 +16,7 @@
16
16
  // Timestamps follow the app-wide epoch-ms number convention (Date.now()). No
17
17
  // native-TTL field on this doc — `dead` jobs are retained for operator replay.
18
18
  import { z } from 'zod';
19
- import { SquareStreetzPostTypeSchema } from './social.js';
19
+ import { SquareStreetzPostTypeSchema, SquareStreetzPostPayloadSchema } from './social.js';
20
20
  /**
21
21
  * The ONE canonical derivation of a Square announcement outbox job id (ARCH-102 —
22
22
  * every enqueue site, the outbox worker, and tests derive from HERE, never a
@@ -29,7 +29,20 @@ import { SquareStreetzPostTypeSchema } from './social.js';
29
29
  export function buildSquareAnnouncementJobId(announcementType, primaryDocId) {
30
30
  return `${announcementType}_${primaryDocId}`;
31
31
  }
32
- export const SquareAnnouncementPayloadSchema = z.custom((v) => typeof v === 'object' && v !== null, { message: 'Expected a Square announcement payload object' });
32
+ /**
33
+ * Payload half of the announcement input — exactly what the runManageSquareStreetzPost
34
+ * dispatcher accepts: the canonical `SquareStreetzPostPayloadSchema` plus the two
35
+ * dispatcher-level extras (`projectId`, and the pattern-C pre-minted `postId` for
36
+ * USER_POST). Derived from the ONE payload schema (ARCH-102) so the durable outbox row is
37
+ * field-validated, not merely checked for object-ness. NON-strict / no pairing refinement:
38
+ * it is parsed at ENQUEUE inside the announcing transaction, so a throw would fail the
39
+ * primary action over an announcement defect (ENG-009); the post core enforces the
40
+ * `mediaAssetId`↔`mediaType` pairing at DELIVERY, where a failure dead-letters the job.
41
+ */
42
+ export const SquareAnnouncementPayloadSchema = SquareStreetzPostPayloadSchema.extend({
43
+ projectId: z.string().optional(),
44
+ postId: z.string().optional(),
45
+ });
33
46
  /** The discriminated announcement input (`{ type, payload }`) the job carries. */
34
47
  export const SquareAnnouncementInputSchema = z.object({
35
48
  type: SquareStreetzPostTypeSchema,
@@ -1 +1 @@
1
- {"version":3,"file":"square-announcement-jobs.js","sourceRoot":"","sources":["../../src/doc-schemas/square-announcement-jobs.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,iFAAiF;AACjF,+EAA+E;AAC/E,4EAA4E;AAC5E,4EAA4E;AAC5E,8DAA8D;AAC9D,qDAAqD;AACrD,EAAE;AACF,kFAAkF;AAClF,oFAAoF;AACpF,kFAAkF;AAClF,iFAAiF;AACjF,8EAA8E;AAC9E,gEAAgE;AAChE,EAAE;AACF,6EAA6E;AAC7E,+EAA+E;AAE/E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAC;AAI1D;;;;;;;;GAQG;AACH,MAAM,UAAU,4BAA4B,CAC1C,gBAAuC,EACvC,YAAoB;IAEpB,OAAO,GAAG,gBAAgB,IAAI,YAAY,EAAE,CAAC;AAC/C,CAAC;AAeD,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,CAAC,MAAM,CACrD,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,EAC1C,EAAE,OAAO,EAAE,+CAA+C,EAAE,CAC7D,CAAC;AAEF,kFAAkF;AAClF,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC,MAAM,CAAC;IACpD,IAAI,EAAE,2BAA2B;IACjC,OAAO,EAAE,+BAA+B;CACzC,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAAC,CAAC,IAAI,CAAC;IACtD,SAAS,EAAE,uCAAuC;IAClD,YAAY,EAAE,0BAA0B;IACxC,WAAW,EAAE,6DAA6D;IAC1E,MAAM,EAAE,mDAAmD;CAC5D,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC;KACzC,MAAM,CAAC;IACN,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,wEAAwE;IACxE,YAAY,EAAE,6BAA6B;IAC3C;;kEAE8D;IAC9D,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;IACxC,MAAM,EAAE,iCAAiC;IACzC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IAC5C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;CACtB,CAAC;KACD,MAAM,EAAE,CAAC","sourcesContent":["// squareAnnouncementJobs/{jobId} — durable outbox for AUTOMATIC Square Streetz\n// announcements. The announcing domain enqueues a job in the SAME transaction as\n// its state commit (commission accepted, new audition/commission/work-project,\n// craft-skill create/delete, profile-picture update, …) instead of awaiting\n// runManageSquareStreetzPost inside the callable; the outbox trigger worker\n// drains the job and applies the announcement. Admin-SDK-only\n// (`allow read, write: if false`); NO client access.\n//\n// jobId — DETERMINISTIC (collision over duplication): derived from the announcing\n// action's natural key via `buildSquareAnnouncementJobId` below — the ONE canonical\n// derivation (ARCH-102); enqueue sites, the worker, and tests MUST call it, never\n// hand-roll the template. The enqueue MUST use `.create()` at this id inside the\n// announcing transaction, so a replayed/retried transaction COLLIDES with the\n// already-enqueued job instead of duplicating the announcement.\n//\n// Timestamps follow the app-wide epoch-ms number convention (Date.now()). No\n// native-TTL field on this doc — `dead` jobs are retained for operator replay.\n\nimport { z } from 'zod';\nimport { SquareStreetzPostTypeSchema } from './social.js';\nimport type { SquareStreetzPostType } from './social.js';\nimport type { SquareStreetzPostPayload } from '../types/social.js';\n\n/**\n * The ONE canonical derivation of a Square announcement outbox job id (ARCH-102 —\n * every enqueue site, the outbox worker, and tests derive from HERE, never a\n * hand-rolled template): `${announcementType}_${primaryDocId}`, where\n * `primaryDocId` is the announcing action's natural-key doc id (e.g.\n * `NEW_CRAFT_SKILL_${craftSkillId}`, `NEW_WORK_PROJECT_${workProjectId}`,\n * `COMMISSION_ACCEPTED_${commissionProposalId}`). Deterministic so a replayed\n * transaction's `.create()` collides instead of duplicating the announcement.\n */\nexport function buildSquareAnnouncementJobId(\n announcementType: SquareStreetzPostType,\n primaryDocId: string,\n): string {\n return `${announcementType}_${primaryDocId}`;\n}\n\n/**\n * Payload half of the announcement input — exactly what the\n * runManageSquareStreetzPost dispatcher accepts: the canonical\n * SquareStreetzPostPayload plus the two dispatcher-level extras (`projectId`,\n * and the pattern-C pre-minted `postId` for USER_POST). Validated structurally\n * (a plain object) and TYPED precisely; the dispatcher re-validates domain\n * fields when the worker delivers (same posture as chatMessageOutbox.payload).\n */\nexport type SquareAnnouncementPayload = SquareStreetzPostPayload & {\n projectId?: string;\n postId?: string;\n};\n\nexport const SquareAnnouncementPayloadSchema = z.custom<SquareAnnouncementPayload>(\n (v) => typeof v === 'object' && v !== null,\n { message: 'Expected a Square announcement payload object' },\n);\n\n/** The discriminated announcement input (`{ type, payload }`) the job carries. */\nexport const SquareAnnouncementInputSchema = z.object({\n type: SquareStreetzPostTypeSchema,\n payload: SquareAnnouncementPayloadSchema,\n});\nexport type SquareAnnouncementInput = z.infer<typeof SquareAnnouncementInputSchema>;\n\nexport const SquareAnnouncementJobStatusSchema = z.enum([\n 'pending', // enqueued; awaiting the outbox worker\n 'processing', // claimed by a worker run\n 'delivered', // announcement applied to the Streetz feed; terminal success\n 'dead', // retries exhausted — retained for operator replay\n]);\nexport type SquareAnnouncementJobStatus = z.infer<typeof SquareAnnouncementJobStatusSchema>;\n\nexport const SquareAnnouncementJobSchema = z\n .object({\n jobId: z.string().min(1),\n /** The exact runManageSquareStreetzPost input the worker dispatches. */\n announcement: SquareAnnouncementInputSchema,\n /** The announcing action's natural-key ids, keyed by field name (e.g.\n * `{ craftSkillId: '…' }`, `{ commissionListingId: '…', commissionProposalId: '…' }`) —\n * the same key(s) the deterministic jobId is derived from. */\n source: z.record(z.string(), z.string()),\n status: SquareAnnouncementJobStatusSchema,\n attemptCount: z.number().int().nonnegative(),\n lastError: z.string().optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n })\n .strict();\nexport type SquareAnnouncementJob = z.infer<typeof SquareAnnouncementJobSchema>;\n"]}
1
+ {"version":3,"file":"square-announcement-jobs.js","sourceRoot":"","sources":["../../src/doc-schemas/square-announcement-jobs.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,iFAAiF;AACjF,+EAA+E;AAC/E,4EAA4E;AAC5E,4EAA4E;AAC5E,8DAA8D;AAC9D,qDAAqD;AACrD,EAAE;AACF,kFAAkF;AAClF,oFAAoF;AACpF,kFAAkF;AAClF,iFAAiF;AACjF,8EAA8E;AAC9E,gEAAgE;AAChE,EAAE;AACF,6EAA6E;AAC7E,+EAA+E;AAE/E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,2BAA2B,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAG1F;;;;;;;;GAQG;AACH,MAAM,UAAU,4BAA4B,CAC1C,gBAAuC,EACvC,YAAoB;IAEpB,OAAO,GAAG,gBAAgB,IAAI,YAAY,EAAE,CAAC;AAC/C,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAG,8BAA8B,CAAC,MAAM,CAAC;IACnF,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC9B,CAAC,CAAC;AAGH,kFAAkF;AAClF,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC,MAAM,CAAC;IACpD,IAAI,EAAE,2BAA2B;IACjC,OAAO,EAAE,+BAA+B;CACzC,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAAC,CAAC,IAAI,CAAC;IACtD,SAAS,EAAE,uCAAuC;IAClD,YAAY,EAAE,0BAA0B;IACxC,WAAW,EAAE,6DAA6D;IAC1E,MAAM,EAAE,mDAAmD;CAC5D,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC;KACzC,MAAM,CAAC;IACN,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,wEAAwE;IACxE,YAAY,EAAE,6BAA6B;IAC3C;;kEAE8D;IAC9D,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;IACxC,MAAM,EAAE,iCAAiC;IACzC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IAC5C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;CACtB,CAAC;KACD,MAAM,EAAE,CAAC","sourcesContent":["// squareAnnouncementJobs/{jobId} — durable outbox for AUTOMATIC Square Streetz\n// announcements. The announcing domain enqueues a job in the SAME transaction as\n// its state commit (commission accepted, new audition/commission/work-project,\n// craft-skill create/delete, profile-picture update, …) instead of awaiting\n// runManageSquareStreetzPost inside the callable; the outbox trigger worker\n// drains the job and applies the announcement. Admin-SDK-only\n// (`allow read, write: if false`); NO client access.\n//\n// jobId — DETERMINISTIC (collision over duplication): derived from the announcing\n// action's natural key via `buildSquareAnnouncementJobId` below — the ONE canonical\n// derivation (ARCH-102); enqueue sites, the worker, and tests MUST call it, never\n// hand-roll the template. The enqueue MUST use `.create()` at this id inside the\n// announcing transaction, so a replayed/retried transaction COLLIDES with the\n// already-enqueued job instead of duplicating the announcement.\n//\n// Timestamps follow the app-wide epoch-ms number convention (Date.now()). No\n// native-TTL field on this doc — `dead` jobs are retained for operator replay.\n\nimport { z } from 'zod';\nimport { SquareStreetzPostTypeSchema, SquareStreetzPostPayloadSchema } from './social.js';\nimport type { SquareStreetzPostType } from './social.js';\n\n/**\n * The ONE canonical derivation of a Square announcement outbox job id (ARCH-102 —\n * every enqueue site, the outbox worker, and tests derive from HERE, never a\n * hand-rolled template): `${announcementType}_${primaryDocId}`, where\n * `primaryDocId` is the announcing action's natural-key doc id (e.g.\n * `NEW_CRAFT_SKILL_${craftSkillId}`, `NEW_WORK_PROJECT_${workProjectId}`,\n * `COMMISSION_ACCEPTED_${commissionProposalId}`). Deterministic so a replayed\n * transaction's `.create()` collides instead of duplicating the announcement.\n */\nexport function buildSquareAnnouncementJobId(\n announcementType: SquareStreetzPostType,\n primaryDocId: string,\n): string {\n return `${announcementType}_${primaryDocId}`;\n}\n\n/**\n * Payload half of the announcement input — exactly what the runManageSquareStreetzPost\n * dispatcher accepts: the canonical `SquareStreetzPostPayloadSchema` plus the two\n * dispatcher-level extras (`projectId`, and the pattern-C pre-minted `postId` for\n * USER_POST). Derived from the ONE payload schema (ARCH-102) so the durable outbox row is\n * field-validated, not merely checked for object-ness. NON-strict / no pairing refinement:\n * it is parsed at ENQUEUE inside the announcing transaction, so a throw would fail the\n * primary action over an announcement defect (ENG-009); the post core enforces the\n * `mediaAssetId`↔`mediaType` pairing at DELIVERY, where a failure dead-letters the job.\n */\nexport const SquareAnnouncementPayloadSchema = SquareStreetzPostPayloadSchema.extend({\n projectId: z.string().optional(),\n postId: z.string().optional(),\n});\nexport type SquareAnnouncementPayload = z.infer<typeof SquareAnnouncementPayloadSchema>;\n\n/** The discriminated announcement input (`{ type, payload }`) the job carries. */\nexport const SquareAnnouncementInputSchema = z.object({\n type: SquareStreetzPostTypeSchema,\n payload: SquareAnnouncementPayloadSchema,\n});\nexport type SquareAnnouncementInput = z.infer<typeof SquareAnnouncementInputSchema>;\n\nexport const SquareAnnouncementJobStatusSchema = z.enum([\n 'pending', // enqueued; awaiting the outbox worker\n 'processing', // claimed by a worker run\n 'delivered', // announcement applied to the Streetz feed; terminal success\n 'dead', // retries exhausted — retained for operator replay\n]);\nexport type SquareAnnouncementJobStatus = z.infer<typeof SquareAnnouncementJobStatusSchema>;\n\nexport const SquareAnnouncementJobSchema = z\n .object({\n jobId: z.string().min(1),\n /** The exact runManageSquareStreetzPost input the worker dispatches. */\n announcement: SquareAnnouncementInputSchema,\n /** The announcing action's natural-key ids, keyed by field name (e.g.\n * `{ craftSkillId: '…' }`, `{ commissionListingId: '…', commissionProposalId: '…' }`) —\n * the same key(s) the deterministic jobId is derived from. */\n source: z.record(z.string(), z.string()),\n status: SquareAnnouncementJobStatusSchema,\n attemptCount: z.number().int().nonnegative(),\n lastError: z.string().optional(),\n createdAt: z.number(),\n updatedAt: z.number(),\n })\n .strict();\nexport type SquareAnnouncementJob = z.infer<typeof SquareAnnouncementJobSchema>;\n"]}
@@ -15,8 +15,8 @@ const mediaKindSchema = ContentMediaKindSchema;
15
15
  * authoritative value; the chat access projection and the status-reconcile queue
16
16
  * derive from the same set). Never re-declare inline. */
17
17
  export const UserAccountStatusSchema = z.enum(['active', 'suspended', 'banned']);
18
- // Craft-skill kind — mandatory choice at upload, no default (see
19
- // CODE_CHANGE_craft_skill_kinds.md). 'original' = the artisan's own original creation;
18
+ // Craft-skill kind — mandatory choice at upload, no default (see ttt-prod
19
+ // docs/design/profile-and-craft-skills.md). 'original' = the artisan's own original creation;
20
20
  // 'mimicOnTtt' = a performance/recreation of work that originated in the TTT community
21
21
  // (requires a source reference); 'mimicOffTtt' = a performance/recreation of work from
22
22
  // outside TTT (covers covers + public-domain works, no source reference).
@@ -131,7 +131,7 @@ export const FullUserSchema = z.object({
131
131
  // Charter honor stamp: written once at registration by /api/register/complete as
132
132
  // byMode(true, false) — true only for accounts created during Charter Season. The
133
133
  // flip publish makes new signups false automatically; no backfill, no date math.
134
- // Backend-only-writable, cosmetic, not PII (docs/charter-season/honor-roll-and-badges.md).
134
+ // Backend-only-writable, cosmetic, not PII (ttt-prod docs/charter-season/honor-roll-and-badges.md).
135
135
  charterSignupMember: z.boolean().optional(),
136
136
  status: UserAccountStatusSchema.optional(),
137
137
  // Chat-edge-rebuild account-access domain (Contract B / round-10 blocker 1): the
@@ -1 +1 @@
1
- {"version":3,"file":"user.js","sourceRoot":"","sources":["../../src/doc-schemas/user.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,oFAAoF;AACpF,+EAA+E;AAC/E,gFAAgF;AAChF,+EAA+E;AAE/E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,6BAA6B,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,kFAAkF;AAClF,MAAM,eAAe,GAAG,sBAAsB,CAAC;AAE/C;;yDAEyD;AACzD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;AAGjF,iEAAiE;AACjE,uFAAuF;AACvF,uFAAuF;AACvF,uFAAuF;AACvF,0EAA0E;AAC1E,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,YAAY,EAAE,aAAa,CAAC,CAAC,CAAC;AAGtF,yFAAyF;AACzF,uFAAuF;AACvF,wFAAwF;AACxF,iCAAiC;AACjC,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC;KAC7C,MAAM,CAAC;IACN,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACrC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACtB,CAAC;KACD,MAAM,EAAE,CAAC;AAGZ,kFAAkF;AAClF,iFAAiF;AACjF,wBAAwB;AACxB,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC;KACzC,MAAM,CAAC;IACN,aAAa,EAAE,oBAAoB;IACnC,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;CACrB,CAAC;KACD,MAAM,EAAE,CAAC;AAGZ,yFAAyF;AACzF,yFAAyF;AACzF,8EAA8E;AAC9E,MAAM,mBAAmB,GAAG;IAC1B,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,kFAAkF;IAClF,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IAC7C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,IAAI,EAAE,eAAe;IACrB,2EAA2E;IAC3E,6EAA6E;IAC7E,yEAAyE;IACzE,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE;IACnB,WAAW,EAAE,2BAA2B;CACzC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IAC3D,CAAC,CAAC,MAAM,CAAC;QACP,GAAG,mBAAmB;QACtB,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;KAC5B,CAAC;IACF,CAAC,CAAC,MAAM,CAAC;QACP,GAAG,mBAAmB;QACtB,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC;QAC7B,2EAA2E;QAC3E,MAAM,EAAE,+BAA+B;KACxC,CAAC;IACF,CAAC,CAAC,MAAM,CAAC;QACP,GAAG,mBAAmB;QACtB,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;KAC/B,CAAC;CACH,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE;IAC1B,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE;IAC7B,cAAc,EAAE,eAAe;IAC/B,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IAC7C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,6EAA6E;IAC7E,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE;IACnB,uFAAuF;IACvF,eAAe;IACf,IAAI,EAAE,oBAAoB;IAC1B,wFAAwF;IACxF,qFAAqF;IACrF,4EAA4E;IAC5E,MAAM,EAAE,+BAA+B,CAAC,QAAQ,EAAE;CACnD,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,IAAI,EAAE,eAAe;CACtB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;IACzB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE;IAC9B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC;CAC1C,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,MAAM,CAAC;IAClD,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE;IACzB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE;IAC9B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;CACrB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,qBAAqB,EAAE,CAAC,CAAC,MAAM,EAAE;IACjC,0EAA0E;IAC1E,oEAAoE;IACpE,qBAAqB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IACvD,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACrC,mFAAmF;IACnF,sFAAsF;IACtF,uFAAuF;IACvF,kFAAkF;IAClF,iDAAiD;IACjD,UAAU,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAClC,iFAAiF;IACjF,kFAAkF;IAClF,iFAAiF;IACjF,2FAA2F;IAC3F,mBAAmB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC3C,MAAM,EAAE,uBAAuB,CAAC,QAAQ,EAAE;IAC1C,iFAAiF;IACjF,qFAAqF;IACrF,sFAAsF;IACtF,uFAAuF;IACvF,kFAAkF;IAClF,oBAAoB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3C,kBAAkB,EAAE,uBAAuB,CAAC,QAAQ,EAAE;IACtD,qFAAqF;IACrF,0FAA0F;IAC1F,oGAAoG;IACpG,wBAAwB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAChD,iBAAiB,EAAE,CAAC,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,QAAQ,EAAE;IAC7D,sBAAsB,EAAE,CAAC,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,QAAQ,EAAE;IACvE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,4EAA4E;IAC5E,4EAA4E;IAC5E,2EAA2E;IAC3E,iDAAiD;IACjD,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACpC,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,GAAG,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC3B,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC9B,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC5B,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC/B,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC7B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAChC,CAAC,CAAC;AAGH;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,uFAAuF;IACvF,kFAAkF;IAClF,yCAAyC;IACzC,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAC7C,wCAAwC;IACxC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,uFAAuF;IACvF,sFAAsF;IACtF,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,QAAQ,EAAE,EAAE,eAAe;IACjF,qFAAqF;IACrF,wEAAwE;IACxE,0BAA0B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAClD,CAAC,CAAC;AAGH;;;GAGG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,mFAAmF;IACnF,0EAA0E;IAC1E,kFAAkF;IAClF,gEAAgE;IAChE,wBAAwB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/C,yFAAyF;IACzF,6FAA6F;IAC7F,uCAAuC;IACvC,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACzC,+FAA+F;IAC/F,8FAA8F;IAC9F,kGAAkG;IAClG,2FAA2F;IAC3F,oBAAoB,EAAE,CAAC;SACpB,MAAM,CAAC;QACN,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,2BAA2B,CAAC;QAC3D,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC,QAAQ,EAAE;QAC9D,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;KACxB,CAAC;SACD,QAAQ,EAAE;IACb,2BAA2B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClD,6EAA6E;IAC7E,6EAA6E;IAC7E,8EAA8E;IAC9E,0BAA0B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjD,UAAU,EAAE,oBAAoB,CAAC,QAAQ,EAAE;IAC3C,4EAA4E;IAC5E,qFAAqF;IACrF,+EAA+E;IAC/E,QAAQ,EAAE,uBAAuB,CAAC,QAAQ,EAAE;IAC5C,gFAAgF;IAChF,+EAA+E;IAC/E,0EAA0E;IAC1E,sDAAsD;IACtD,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACnC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACrC,gFAAgF;IAChF,+EAA+E;IAC/E,mEAAmE;IACnE,YAAY,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACpC,mFAAmF;IACnF,iFAAiF;IACjF,4BAA4B;IAC5B,GAAG,6BAA6B;CACjC,CAAC,CAAC","sourcesContent":["// User-related Firestore document SCHEMAS — the single source of truth for the\n// `userProfiles/{uid}` doc, its `privateData/{uid}` subdoc, and craft-skill shapes.\n// (The `publicUsers/{uid}` mirror lives in ./publicUser.) TypeScript types are\n// inferred from these schemas via `z.infer`, so a document's shape and its type\n// cannot drift apart. See docs/design/firestore-schema-registry.md (ttt-prod).\n\nimport { z } from 'zod';\nimport { HALL_WING_TYPE_KEYS } from '../types/content.js';\nimport { MAX_ARTISAN_LOCATION_LENGTH } from '../constants/business.js';\nimport { CRAFT_SKILL_TAG_VALUES } from '../constants/options.js';\nimport { userPrivateDataAgeFieldsShape } from './safety/age.js';\nimport { ContentMediaKindSchema } from './media-assets.js';\n\n// The canonical stored media kind — declared once in doc-schemas/media-assets.ts.\nconst mediaKindSchema = ContentMediaKindSchema;\n\n/** The ONE canonical application account status (userProfiles.status is the\n * authoritative value; the chat access projection and the status-reconcile queue\n * derive from the same set). Never re-declare inline. */\nexport const UserAccountStatusSchema = z.enum(['active', 'suspended', 'banned']);\nexport type UserAccountStatus = z.infer<typeof UserAccountStatusSchema>;\n\n// Craft-skill kind — mandatory choice at upload, no default (see\n// CODE_CHANGE_craft_skill_kinds.md). 'original' = the artisan's own original creation;\n// 'mimicOnTtt' = a performance/recreation of work that originated in the TTT community\n// (requires a source reference); 'mimicOffTtt' = a performance/recreation of work from\n// outside TTT (covers covers + public-domain works, no source reference).\nexport const CraftSkillKindSchema = z.enum(['original', 'mimicOnTtt', 'mimicOffTtt']);\nexport type CraftSkillKind = z.infer<typeof CraftSkillKindSchema>;\n\n// Source reference for a 'mimicOnTtt' skill — the original artisan OR the original work,\n// linked mention-style (id only, no name snapshots, resolved at render per the Display\n// Identity Invariant). 'workProject' is the safe framing today; linking a specific hall\n// item is optional future scope.\nexport const CraftSkillSourceReferenceSchema = z\n .object({\n type: z.enum(['user', 'workProject']),\n id: z.string().min(1),\n })\n .strict();\nexport type CraftSkillSourceReference = z.infer<typeof CraftSkillSourceReferenceSchema>;\n\n// The agreed attestation recorded on the doc: which statement (keyed by kind) the\n// uploader agreed to, its version, and when (epoch ms, always a number — never a\n// Firestore Timestamp).\nexport const CraftSkillAttestationSchema = z\n .object({\n statementKind: CraftSkillKindSchema,\n statementVersion: z.number().int().min(1),\n agreedAt: z.number(),\n })\n .strict();\nexport type CraftSkillAttestation = z.infer<typeof CraftSkillAttestationSchema>;\n\n// Base craft-skill fields shared across all kinds. The `kind` + `source` relationship is\n// layered on top as a discriminated union so an invalid combination (e.g. a source on an\n// 'original', or a missing source on a 'mimicOnTtt') fails schema validation.\nconst craftSkillBaseShape = {\n id: z.string(),\n name: z.string(),\n mediaAssetId: z.string(),\n // Canonical discipline-tag allowlist — never open strings (DJ ruling 2026-07-13).\n tags: z.array(z.enum(CRAFT_SKILL_TAG_VALUES)),\n createdAt: z.number(),\n type: mediaKindSchema,\n // Moderation visibility flag. Absent/false = visible; true = hidden by the\n // craft-skill hide cascade (report auto-hide or admin action). Mirrored onto\n // every taggedCraftSkills index doc so discovery surfaces can filter it.\n hidden: z.boolean(),\n attestation: CraftSkillAttestationSchema,\n};\n\nexport const CraftSkillSchema = z.discriminatedUnion('kind', [\n z.object({\n ...craftSkillBaseShape,\n kind: z.literal('original'),\n }),\n z.object({\n ...craftSkillBaseShape,\n kind: z.literal('mimicOnTtt'),\n // REQUIRED for the on-TTT mimic kind: the linked original artisan or work.\n source: CraftSkillSourceReferenceSchema,\n }),\n z.object({\n ...craftSkillBaseShape,\n kind: z.literal('mimicOffTtt'),\n }),\n]);\nexport type CraftSkill = z.infer<typeof CraftSkillSchema>;\n\nexport const CraftSkillReferenceSchema = z.object({\n craftSkillId: z.string(),\n compositeId: z.string(),\n userId: z.string(),\n craftSkillName: z.string(),\n craftSkillAssetId: z.string(),\n craftSkillType: mediaKindSchema,\n tags: z.array(z.enum(CRAFT_SKILL_TAG_VALUES)),\n createdAt: z.number(),\n // Mirror of CraftSkill.hidden; lets the tag-browse filter hidden skills out.\n hidden: z.boolean(),\n // Mirror of CraftSkill.kind so the tag-browse card can render the kind badge without a\n // second read.\n kind: CraftSkillKindSchema,\n // Mirror of CraftSkill.source — present ONLY when kind === 'mimicOnTtt' (the source-doc\n // discriminated union guarantees that invariant on the authoritative side). Lets the\n // browse card render the clickable \"someone performed my work\" source link.\n source: CraftSkillSourceReferenceSchema.optional(),\n});\nexport type CraftSkillReference = z.infer<typeof CraftSkillReferenceSchema>;\n\nexport const MinimalCraftSkillSchema = z.object({\n id: z.string(),\n name: z.string(),\n mediaAssetId: z.string(),\n type: mediaKindSchema,\n});\nexport type MinimalCraftSkill = z.infer<typeof MinimalCraftSkillSchema>;\n\nexport const OwnedWorkProjectSchema = z.object({\n workProjectId: z.string(),\n workingTitle: z.string(),\n workingDescription: z.string(),\n type: z.string(),\n createdOn: z.number(),\n hallWingType: z.enum(HALL_WING_TYPE_KEYS),\n});\nexport type OwnedWorkProject = z.infer<typeof OwnedWorkProjectSchema>;\n\nexport const AssociatedWorkProjectSchema = z.object({\n workProjectId: z.string(),\n workingTitle: z.string(),\n workingDescription: z.string(),\n type: z.string(),\n joinedOn: z.number(),\n});\nexport type AssociatedWorkProject = z.infer<typeof AssociatedWorkProjectSchema>;\n\nexport const FullUserSchema = z.object({\n uid: z.string(),\n displayName: z.string(),\n displayName_lowercase: z.string(),\n // One asset, variants full/medium/small in the mediaAssets registry; URLs\n // are built at render time (media-assets-and-protected-serving.md).\n profilePictureAssetId: z.string().nullable().optional(),\n artisanCreator: z.number().optional(),\n // Cosmetic supporter badge. Set true via the Admin SDK inside the Stripe webhook's\n // pledge-record transaction once the user completes a pledge; rendered on the profile\n // page. Lives here (not publicUsers) because userProfiles/{uid} is already readable by\n // any authenticated user, so other viewers see the badge with no mirror. Not PII.\n // Revoked (→ false) on refund once refunds ship.\n hasPledged: z.boolean().optional(),\n // Charter honor stamp: written once at registration by /api/register/complete as\n // byMode(true, false) — true only for accounts created during Charter Season. The\n // flip publish makes new signups false automatically; no backfill, no date math.\n // Backend-only-writable, cosmetic, not PII (docs/charter-season/honor-roll-and-badges.md).\n charterSignupMember: z.boolean().optional(),\n status: UserAccountStatusSchema.optional(),\n // Chat-edge-rebuild account-access domain (Contract B / round-10 blocker 1): the\n // single ban/unban ordering version + state the chat `accountAccess` sync events key\n // on. Backend-only-writable. Deliberate defaults when ABSENT: a never-touched account\n // is `{ accountAccessVersion: 0, accountAccessState: 'active' }` (NOT banned) — bumped\n // atomically on suspend/ban/unban, which enqueue the accountAccessChanged fanout.\n accountAccessVersion: z.number().optional(),\n accountAccessState: UserAccountStatusSchema.optional(),\n // Moderation: set true by the forceDisplayNameReset callable when an admin resets an\n // abusive display name. The app gates the user into a forced \"pick a new name\" flow until\n // they complete it via setMyDisplayName (which clears this). Backend-only-writable (like `status`).\n displayNameResetRequired: z.boolean().optional(),\n ownedWorkProjects: z.array(OwnedWorkProjectSchema).optional(),\n associatedWorkProjects: z.array(AssociatedWorkProjectSchema).optional(),\n createdAt: z.number(),\n // N3 data-deletion / GDPR erasure: epoch ms when the account-deletion scrub\n // anonymized this profile in place. When set, the identity fields have been\n // scrubbed (displayName → the FORMER_MEMBER_DISPLAY_NAME sentinel) and the\n // account is a tombstone. Backend-only-writable.\n anonymizedAt: z.number().optional(),\n});\nexport type FullUser = z.infer<typeof FullUserSchema>;\n\nexport const UserAgreementsSchema = z.object({\n age: z.boolean().optional(),\n nudity: z.boolean().optional(),\n meet: z.boolean().optional(),\n cookies: z.boolean().optional(),\n terms: z.boolean().optional(),\n agreedOn: z.number().optional(),\n});\nexport type UserAgreements = z.infer<typeof UserAgreementsSchema>;\n\n/**\n * First-visit site-tour state (account-durable, server-written) stored on\n * `privateData/{uid}.siteTour`. A missing `siteTour` field means the member has never\n * handled the tour. Automatic-invitation eligibility is evaluated in this order:\n * 1. `automaticInvitesDisabledAt` present → never invite automatically (\"Don't show\n * this again\");\n * 2. `notTodayDate` equals the member's current LOCAL calendar date → do not invite\n * that day (\"Not today\");\n * 3. `completedVersion` equals `SITE_TOUR_CURRENT_VERSION` → already handled;\n * 4. otherwise → offer the tour.\n * Written ONLY by the `updateSiteTourPreference` callable via the Admin SDK; never\n * client-written. `notTodayDate` is a strict `YYYY-MM-DD` local-date string (same\n * date-string convention as the age cluster's `attestedDateOfBirth`). See\n * docs/design/landing-backstage-guide-and-first-visit-plan.md §10.\n */\nexport const UserSiteTourStateSchema = z.object({\n // The tour version the member completed. The callable stamps SITE_TOUR_CURRENT_VERSION\n // server-side at completion (the version is server-owned, never client-supplied);\n // absent until a completion is recorded.\n completedVersion: z.number().int().optional(),\n // Epoch ms when the tour was completed.\n completedAt: z.number().optional(),\n // The member's LOCAL calendar date (YYYY-MM-DD) recorded by \"Not today\"; the automatic\n // invitation is suppressed for exactly that date, then offered again on a later date.\n notTodayDate: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}$/).optional(), // 'YYYY-MM-DD'\n // Epoch ms when the member chose \"Don't show this again\" (permanent automatic-invite\n // dismissal). Manual replay from Help ignores this without clearing it.\n automaticInvitesDisabledAt: z.number().optional(),\n});\nexport type UserSiteTourState = z.infer<typeof UserSiteTourStateSchema>;\n\n/**\n * Owner-only account state at `userProfiles/{uid}/privateData/{uid}` (readable\n * only by the owner; never mirrored to publicUsers).\n */\nexport const UserPrivateDataSchema = z.object({\n email: z.string(),\n // Epoch ms when the user applied for news/political posting (not a boolean) so the\n // applicant queue can be ordered/triaged by application date. Mirrors the\n // `artisanCreator?: number` grant-timestamp pattern. Truthy when set, so existing\n // truthiness reads keep working; absent until the user applies.\n isWaitingForNewsApproval: z.number().optional(),\n // Epoch ms when the user attested they are a U.S.-based person while becoming an artisan\n // (required at artisan signup for now). Mirrors the ageAttested attestation pattern; written\n // server-side by becomeArtisanCreator.\n usPersonAttestedAt: z.number().optional(),\n // Non-U.S. artisan-interest \"waitlist\" recorded ONLY for adult accounts when a non-U.S. person\n // asks to be notified once creator signups open in their region. Owner-only, backend-written.\n // `requestedAt` is the immutable first-come-first-serve timestamp; `country`/`region` let signups\n // be opened by jurisdiction as each region's laws clear. Mirrors isWaitingForNewsApproval.\n nonUsArtisanInterest: z\n .object({\n country: z.string().min(1).max(MAX_ARTISAN_LOCATION_LENGTH),\n region: z.string().max(MAX_ARTISAN_LOCATION_LENGTH).optional(),\n requestedAt: z.number(),\n })\n .optional(),\n squareStreetzAgreementsDate: z.number().optional(),\n // Epoch ms when the user accepted the one-time Hall download acknowledgement\n // (personal offline use only, no redistribution). Written server-side by the\n // acceptHallDownloadAcknowledgement callable; gates the Hall download button.\n hallDownloadAcknowledgedAt: z.number().optional(),\n agreements: UserAgreementsSchema.optional(),\n // First-visit site-tour state (account-durable; the SOLE authority for tour\n // eligibility — no local-storage cache/mirror). Absent = never handled. Written only\n // by the updateSiteTourPreference callable. See UserSiteTourStateSchema above.\n siteTour: UserSiteTourStateSchema.optional(),\n // Moderation: human-readable reason for the current account status (set when an\n // admin suspends/bans the user). Written by the setUserStatus callable via the\n // Admin SDK; readable only by the owner (shown in their restricted view).\n // Cleared when the account is reinstated to 'active'.\n statusReason: z.string().optional(),\n statusReasonAt: z.number().optional(),\n // Trust & Safety (§A8): silent interim safety-lock flag. Backend-only-writable,\n // restricted to the owner's view. Set true while a child-safety/NCII action is\n // pending against the account; the app gates the user accordingly.\n safetyLocked: z.boolean().optional(),\n // Trust & Safety (§A7): server-write-only age/registration fields, merged from the\n // standalone age cluster shape (./safety/age.js) so the canonical schema and the\n // age cluster cannot drift.\n ...userPrivateDataAgeFieldsShape,\n});\nexport type UserPrivateData = z.infer<typeof UserPrivateDataSchema>;\n"]}
1
+ {"version":3,"file":"user.js","sourceRoot":"","sources":["../../src/doc-schemas/user.ts"],"names":[],"mappings":"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","sourcesContent":["// User-related Firestore document SCHEMAS — the single source of truth for the\n// `userProfiles/{uid}` doc, its `privateData/{uid}` subdoc, and craft-skill shapes.\n// (The `publicUsers/{uid}` mirror lives in ./publicUser.) TypeScript types are\n// inferred from these schemas via `z.infer`, so a document's shape and its type\n// cannot drift apart. See docs/design/firestore-schema-registry.md (ttt-prod).\n\nimport { z } from 'zod';\nimport { HALL_WING_TYPE_KEYS } from '../types/content.js';\nimport { MAX_ARTISAN_LOCATION_LENGTH } from '../constants/business.js';\nimport { CRAFT_SKILL_TAG_VALUES } from '../constants/options.js';\nimport { userPrivateDataAgeFieldsShape } from './safety/age.js';\nimport { ContentMediaKindSchema } from './media-assets.js';\n\n// The canonical stored media kind — declared once in doc-schemas/media-assets.ts.\nconst mediaKindSchema = ContentMediaKindSchema;\n\n/** The ONE canonical application account status (userProfiles.status is the\n * authoritative value; the chat access projection and the status-reconcile queue\n * derive from the same set). Never re-declare inline. */\nexport const UserAccountStatusSchema = z.enum(['active', 'suspended', 'banned']);\nexport type UserAccountStatus = z.infer<typeof UserAccountStatusSchema>;\n\n// Craft-skill kind — mandatory choice at upload, no default (see ttt-prod\n// docs/design/profile-and-craft-skills.md). 'original' = the artisan's own original creation;\n// 'mimicOnTtt' = a performance/recreation of work that originated in the TTT community\n// (requires a source reference); 'mimicOffTtt' = a performance/recreation of work from\n// outside TTT (covers covers + public-domain works, no source reference).\nexport const CraftSkillKindSchema = z.enum(['original', 'mimicOnTtt', 'mimicOffTtt']);\nexport type CraftSkillKind = z.infer<typeof CraftSkillKindSchema>;\n\n// Source reference for a 'mimicOnTtt' skill — the original artisan OR the original work,\n// linked mention-style (id only, no name snapshots, resolved at render per the Display\n// Identity Invariant). 'workProject' is the safe framing today; linking a specific hall\n// item is optional future scope.\nexport const CraftSkillSourceReferenceSchema = z\n .object({\n type: z.enum(['user', 'workProject']),\n id: z.string().min(1),\n })\n .strict();\nexport type CraftSkillSourceReference = z.infer<typeof CraftSkillSourceReferenceSchema>;\n\n// The agreed attestation recorded on the doc: which statement (keyed by kind) the\n// uploader agreed to, its version, and when (epoch ms, always a number — never a\n// Firestore Timestamp).\nexport const CraftSkillAttestationSchema = z\n .object({\n statementKind: CraftSkillKindSchema,\n statementVersion: z.number().int().min(1),\n agreedAt: z.number(),\n })\n .strict();\nexport type CraftSkillAttestation = z.infer<typeof CraftSkillAttestationSchema>;\n\n// Base craft-skill fields shared across all kinds. The `kind` + `source` relationship is\n// layered on top as a discriminated union so an invalid combination (e.g. a source on an\n// 'original', or a missing source on a 'mimicOnTtt') fails schema validation.\nconst craftSkillBaseShape = {\n id: z.string(),\n name: z.string(),\n mediaAssetId: z.string(),\n // Canonical discipline-tag allowlist — never open strings (DJ ruling 2026-07-13).\n tags: z.array(z.enum(CRAFT_SKILL_TAG_VALUES)),\n createdAt: z.number(),\n type: mediaKindSchema,\n // Moderation visibility flag. Absent/false = visible; true = hidden by the\n // craft-skill hide cascade (report auto-hide or admin action). Mirrored onto\n // every taggedCraftSkills index doc so discovery surfaces can filter it.\n hidden: z.boolean(),\n attestation: CraftSkillAttestationSchema,\n};\n\nexport const CraftSkillSchema = z.discriminatedUnion('kind', [\n z.object({\n ...craftSkillBaseShape,\n kind: z.literal('original'),\n }),\n z.object({\n ...craftSkillBaseShape,\n kind: z.literal('mimicOnTtt'),\n // REQUIRED for the on-TTT mimic kind: the linked original artisan or work.\n source: CraftSkillSourceReferenceSchema,\n }),\n z.object({\n ...craftSkillBaseShape,\n kind: z.literal('mimicOffTtt'),\n }),\n]);\nexport type CraftSkill = z.infer<typeof CraftSkillSchema>;\n\nexport const CraftSkillReferenceSchema = z.object({\n craftSkillId: z.string(),\n compositeId: z.string(),\n userId: z.string(),\n craftSkillName: z.string(),\n craftSkillAssetId: z.string(),\n craftSkillType: mediaKindSchema,\n tags: z.array(z.enum(CRAFT_SKILL_TAG_VALUES)),\n createdAt: z.number(),\n // Mirror of CraftSkill.hidden; lets the tag-browse filter hidden skills out.\n hidden: z.boolean(),\n // Mirror of CraftSkill.kind so the tag-browse card can render the kind badge without a\n // second read.\n kind: CraftSkillKindSchema,\n // Mirror of CraftSkill.source — present ONLY when kind === 'mimicOnTtt' (the source-doc\n // discriminated union guarantees that invariant on the authoritative side). Lets the\n // browse card render the clickable \"someone performed my work\" source link.\n source: CraftSkillSourceReferenceSchema.optional(),\n});\nexport type CraftSkillReference = z.infer<typeof CraftSkillReferenceSchema>;\n\nexport const MinimalCraftSkillSchema = z.object({\n id: z.string(),\n name: z.string(),\n mediaAssetId: z.string(),\n type: mediaKindSchema,\n});\nexport type MinimalCraftSkill = z.infer<typeof MinimalCraftSkillSchema>;\n\nexport const OwnedWorkProjectSchema = z.object({\n workProjectId: z.string(),\n workingTitle: z.string(),\n workingDescription: z.string(),\n type: z.string(),\n createdOn: z.number(),\n hallWingType: z.enum(HALL_WING_TYPE_KEYS),\n});\nexport type OwnedWorkProject = z.infer<typeof OwnedWorkProjectSchema>;\n\nexport const AssociatedWorkProjectSchema = z.object({\n workProjectId: z.string(),\n workingTitle: z.string(),\n workingDescription: z.string(),\n type: z.string(),\n joinedOn: z.number(),\n});\nexport type AssociatedWorkProject = z.infer<typeof AssociatedWorkProjectSchema>;\n\nexport const FullUserSchema = z.object({\n uid: z.string(),\n displayName: z.string(),\n displayName_lowercase: z.string(),\n // One asset, variants full/medium/small in the mediaAssets registry; URLs\n // are built at render time (media-assets-and-protected-serving.md).\n profilePictureAssetId: z.string().nullable().optional(),\n artisanCreator: z.number().optional(),\n // Cosmetic supporter badge. Set true via the Admin SDK inside the Stripe webhook's\n // pledge-record transaction once the user completes a pledge; rendered on the profile\n // page. Lives here (not publicUsers) because userProfiles/{uid} is already readable by\n // any authenticated user, so other viewers see the badge with no mirror. Not PII.\n // Revoked (→ false) on refund once refunds ship.\n hasPledged: z.boolean().optional(),\n // Charter honor stamp: written once at registration by /api/register/complete as\n // byMode(true, false) — true only for accounts created during Charter Season. The\n // flip publish makes new signups false automatically; no backfill, no date math.\n // Backend-only-writable, cosmetic, not PII (ttt-prod docs/charter-season/honor-roll-and-badges.md).\n charterSignupMember: z.boolean().optional(),\n status: UserAccountStatusSchema.optional(),\n // Chat-edge-rebuild account-access domain (Contract B / round-10 blocker 1): the\n // single ban/unban ordering version + state the chat `accountAccess` sync events key\n // on. Backend-only-writable. Deliberate defaults when ABSENT: a never-touched account\n // is `{ accountAccessVersion: 0, accountAccessState: 'active' }` (NOT banned) — bumped\n // atomically on suspend/ban/unban, which enqueue the accountAccessChanged fanout.\n accountAccessVersion: z.number().optional(),\n accountAccessState: UserAccountStatusSchema.optional(),\n // Moderation: set true by the forceDisplayNameReset callable when an admin resets an\n // abusive display name. The app gates the user into a forced \"pick a new name\" flow until\n // they complete it via setMyDisplayName (which clears this). Backend-only-writable (like `status`).\n displayNameResetRequired: z.boolean().optional(),\n ownedWorkProjects: z.array(OwnedWorkProjectSchema).optional(),\n associatedWorkProjects: z.array(AssociatedWorkProjectSchema).optional(),\n createdAt: z.number(),\n // N3 data-deletion / GDPR erasure: epoch ms when the account-deletion scrub\n // anonymized this profile in place. When set, the identity fields have been\n // scrubbed (displayName → the FORMER_MEMBER_DISPLAY_NAME sentinel) and the\n // account is a tombstone. Backend-only-writable.\n anonymizedAt: z.number().optional(),\n});\nexport type FullUser = z.infer<typeof FullUserSchema>;\n\nexport const UserAgreementsSchema = z.object({\n age: z.boolean().optional(),\n nudity: z.boolean().optional(),\n meet: z.boolean().optional(),\n cookies: z.boolean().optional(),\n terms: z.boolean().optional(),\n agreedOn: z.number().optional(),\n});\nexport type UserAgreements = z.infer<typeof UserAgreementsSchema>;\n\n/**\n * First-visit site-tour state (account-durable, server-written) stored on\n * `privateData/{uid}.siteTour`. A missing `siteTour` field means the member has never\n * handled the tour. Automatic-invitation eligibility is evaluated in this order:\n * 1. `automaticInvitesDisabledAt` present → never invite automatically (\"Don't show\n * this again\");\n * 2. `notTodayDate` equals the member's current LOCAL calendar date → do not invite\n * that day (\"Not today\");\n * 3. `completedVersion` equals `SITE_TOUR_CURRENT_VERSION` → already handled;\n * 4. otherwise → offer the tour.\n * Written ONLY by the `updateSiteTourPreference` callable via the Admin SDK; never\n * client-written. `notTodayDate` is a strict `YYYY-MM-DD` local-date string (same\n * date-string convention as the age cluster's `attestedDateOfBirth`). See\n * docs/design/landing-backstage-guide-and-first-visit-plan.md §10.\n */\nexport const UserSiteTourStateSchema = z.object({\n // The tour version the member completed. The callable stamps SITE_TOUR_CURRENT_VERSION\n // server-side at completion (the version is server-owned, never client-supplied);\n // absent until a completion is recorded.\n completedVersion: z.number().int().optional(),\n // Epoch ms when the tour was completed.\n completedAt: z.number().optional(),\n // The member's LOCAL calendar date (YYYY-MM-DD) recorded by \"Not today\"; the automatic\n // invitation is suppressed for exactly that date, then offered again on a later date.\n notTodayDate: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}$/).optional(), // 'YYYY-MM-DD'\n // Epoch ms when the member chose \"Don't show this again\" (permanent automatic-invite\n // dismissal). Manual replay from Help ignores this without clearing it.\n automaticInvitesDisabledAt: z.number().optional(),\n});\nexport type UserSiteTourState = z.infer<typeof UserSiteTourStateSchema>;\n\n/**\n * Owner-only account state at `userProfiles/{uid}/privateData/{uid}` (readable\n * only by the owner; never mirrored to publicUsers).\n */\nexport const UserPrivateDataSchema = z.object({\n email: z.string(),\n // Epoch ms when the user applied for news/political posting (not a boolean) so the\n // applicant queue can be ordered/triaged by application date. Mirrors the\n // `artisanCreator?: number` grant-timestamp pattern. Truthy when set, so existing\n // truthiness reads keep working; absent until the user applies.\n isWaitingForNewsApproval: z.number().optional(),\n // Epoch ms when the user attested they are a U.S.-based person while becoming an artisan\n // (required at artisan signup for now). Mirrors the ageAttested attestation pattern; written\n // server-side by becomeArtisanCreator.\n usPersonAttestedAt: z.number().optional(),\n // Non-U.S. artisan-interest \"waitlist\" recorded ONLY for adult accounts when a non-U.S. person\n // asks to be notified once creator signups open in their region. Owner-only, backend-written.\n // `requestedAt` is the immutable first-come-first-serve timestamp; `country`/`region` let signups\n // be opened by jurisdiction as each region's laws clear. Mirrors isWaitingForNewsApproval.\n nonUsArtisanInterest: z\n .object({\n country: z.string().min(1).max(MAX_ARTISAN_LOCATION_LENGTH),\n region: z.string().max(MAX_ARTISAN_LOCATION_LENGTH).optional(),\n requestedAt: z.number(),\n })\n .optional(),\n squareStreetzAgreementsDate: z.number().optional(),\n // Epoch ms when the user accepted the one-time Hall download acknowledgement\n // (personal offline use only, no redistribution). Written server-side by the\n // acceptHallDownloadAcknowledgement callable; gates the Hall download button.\n hallDownloadAcknowledgedAt: z.number().optional(),\n agreements: UserAgreementsSchema.optional(),\n // First-visit site-tour state (account-durable; the SOLE authority for tour\n // eligibility — no local-storage cache/mirror). Absent = never handled. Written only\n // by the updateSiteTourPreference callable. See UserSiteTourStateSchema above.\n siteTour: UserSiteTourStateSchema.optional(),\n // Moderation: human-readable reason for the current account status (set when an\n // admin suspends/bans the user). Written by the setUserStatus callable via the\n // Admin SDK; readable only by the owner (shown in their restricted view).\n // Cleared when the account is reinstated to 'active'.\n statusReason: z.string().optional(),\n statusReasonAt: z.number().optional(),\n // Trust & Safety (§A8): silent interim safety-lock flag. Backend-only-writable,\n // restricted to the owner's view. Set true while a child-safety/NCII action is\n // pending against the account; the app gates the user accordingly.\n safetyLocked: z.boolean().optional(),\n // Trust & Safety (§A7): server-write-only age/registration fields, merged from the\n // standalone age cluster shape (./safety/age.js) so the canonical schema and the\n // age cluster cannot drift.\n ...userPrivateDataAgeFieldsShape,\n});\nexport type UserPrivateData = z.infer<typeof UserPrivateDataSchema>;\n"]}
@@ -5,7 +5,7 @@
5
5
  // document's shape and its TypeScript type cannot drift apart.
6
6
  //
7
7
  // Terminology: the current-owner field is `workStewardUid` (locked rename from the old
8
- // `ownerUid`; see docs/design/terminology-naming-convention.md — Steward row). The original
8
+ // `ownerUid`; see ttt-prod docs/design/terminology-naming-convention.md — Steward row). The original
9
9
  // creator is `foundingArtisanUid` (locked rename from the old `createdByUid`; Founding Artisan).
10
10
  import { z } from 'zod';
11
11
  import { HALL_WING_TYPE_KEYS, WORK_PROJECT_TYPE_KEYS } from '../types/content.js';
@@ -116,7 +116,7 @@ export const PublicWorkProjectSchema = z.object({
116
116
  // A default folder (every active guildmate views/uploads) + custom folders whose
117
117
  // audience is controlled by TRADE PROFESSIONS, while file-system ADMINISTRATION is
118
118
  // controlled by guild standings (StewardOwner / WorkProjectManager / WorkAssetAdmin).
119
- // See docs/design/work-project-file-folders.md. Realm sharing of a file is the
119
+ // See ttt-prod docs/design/work-project-file-folders.md. Realm sharing of a file is the
120
120
  // `realmFileCanonStatus` seam on the file's mediaAssets doc (media-assets.ts).
121
121
  // ===========================================================================
122
122
  /** `allWorkProjects/{workProjectId}/workFileFolders/{workFileFolderId}`. */