@ttt-productions/ttt-core 0.79.80 → 0.79.83

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.
@@ -57,8 +57,8 @@ export type ContentMediaKind = z.infer<typeof ContentMediaKindSchema>;
57
57
  export declare const MEDIA_VARIANT_KEYS: readonly ["full", "medium", "small", "main", "poster"];
58
58
  export declare const MediaVariantKeySchema: z.ZodEnum<{
59
59
  full: "full";
60
- poster: "poster";
61
60
  small: "small";
61
+ poster: "poster";
62
62
  medium: "medium";
63
63
  main: "main";
64
64
  }>;
@@ -101,8 +101,8 @@ export declare const MediaOriginLineageV1Schema: z.ZodObject<{
101
101
  originalSha256: z.ZodOptional<z.ZodString>;
102
102
  variantSha256s: z.ZodRecord<z.ZodEnum<{
103
103
  full: "full";
104
- poster: "poster";
105
104
  small: "small";
105
+ poster: "poster";
106
106
  medium: "medium";
107
107
  main: "main";
108
108
  }> & z.core.$partial, z.ZodString>;
@@ -481,8 +481,8 @@ export declare const MediaAssetSchema: z.ZodObject<{
481
481
  originalSha256: z.ZodOptional<z.ZodString>;
482
482
  variantSha256s: z.ZodRecord<z.ZodEnum<{
483
483
  full: "full";
484
- poster: "poster";
485
484
  small: "small";
485
+ poster: "poster";
486
486
  medium: "medium";
487
487
  main: "main";
488
488
  }> & z.core.$partial, z.ZodString>;
@@ -33,8 +33,8 @@ export declare const MediaAssetCopyIntentSchema: z.ZodObject<{
33
33
  ownerId: z.ZodString;
34
34
  variantKeys: z.ZodArray<z.ZodEnum<{
35
35
  full: "full";
36
- poster: "poster";
37
36
  small: "small";
37
+ poster: "poster";
38
38
  medium: "medium";
39
39
  main: "main";
40
40
  }>>;
@@ -93,8 +93,8 @@ export declare const MediaCopyIntentSchema: z.ZodDiscriminatedUnion<[z.ZodObject
93
93
  ownerId: z.ZodString;
94
94
  variantKeys: z.ZodArray<z.ZodEnum<{
95
95
  full: "full";
96
- poster: "poster";
97
96
  small: "small";
97
+ poster: "poster";
98
98
  medium: "medium";
99
99
  main: "main";
100
100
  }>>;
@@ -33,8 +33,8 @@ export declare const ContentViolationSchema: z.ZodObject<{
33
33
  userId: z.ZodString;
34
34
  fileType: z.ZodString;
35
35
  violationType: z.ZodOptional<z.ZodEnum<{
36
- media: "media";
37
36
  text: "text";
37
+ media: "media";
38
38
  }>>;
39
39
  reason: z.ZodString;
40
40
  timestamp: z.ZodNumber;
@@ -13,6 +13,7 @@ export declare const TakeItDownRequestRootV1Schema: z.ZodObject<{
13
13
  workProject: "workProject";
14
14
  workRealm: "workRealm";
15
15
  audition: "audition";
16
+ url: "url";
16
17
  username: "username";
17
18
  mediaAsset: "mediaAsset";
18
19
  hallItem: "hallItem";
@@ -26,7 +27,6 @@ export declare const TakeItDownRequestRootV1Schema: z.ZodObject<{
26
27
  guildInviteMessage: "guildInviteMessage";
27
28
  conversationFile: "conversationFile";
28
29
  guildChatMessage: "guildChatMessage";
29
- url: "url";
30
30
  additionalText: "additionalText";
31
31
  }>;
32
32
  surfaceLabel: z.ZodString;
@@ -10,8 +10,8 @@ export type PledgeRefundState = z.infer<typeof PledgeRefundStateSchema>;
10
10
  /** Where a chargeback dispute stands: `underReview` while open, then `won` or `lost` once closed. */
11
11
  export declare const PLEDGE_DISPUTE_STATES: readonly ["none", "underReview", "won", "lost"];
12
12
  export declare const PledgeDisputeStateSchema: z.ZodEnum<{
13
- underReview: "underReview";
14
13
  none: "none";
14
+ underReview: "underReview";
15
15
  won: "won";
16
16
  lost: "lost";
17
17
  }>;
@@ -78,8 +78,8 @@ export declare const PledgePaymentSchema: z.ZodObject<{
78
78
  partial: "partial";
79
79
  }>;
80
80
  disputeState: z.ZodEnum<{
81
- underReview: "underReview";
82
81
  none: "none";
82
+ underReview: "underReview";
83
83
  won: "won";
84
84
  lost: "lost";
85
85
  }>;
@@ -911,8 +911,8 @@ export declare const COLLECTION_SCHEMAS: {
911
911
  partial: "partial";
912
912
  }>;
913
913
  disputeState: z.ZodEnum<{
914
- underReview: "underReview";
915
914
  none: "none";
915
+ underReview: "underReview";
916
916
  won: "won";
917
917
  lost: "lost";
918
918
  }>;
@@ -1755,8 +1755,8 @@ export declare const COLLECTION_SCHEMAS: {
1755
1755
  userId: z.ZodString;
1756
1756
  fileType: z.ZodString;
1757
1757
  violationType: z.ZodOptional<z.ZodEnum<{
1758
- media: "media";
1759
1758
  text: "text";
1759
+ media: "media";
1760
1760
  }>>;
1761
1761
  reason: z.ZodString;
1762
1762
  timestamp: z.ZodNumber;
@@ -4092,8 +4092,8 @@ export declare const COLLECTION_SCHEMAS: {
4092
4092
  originalSha256: z.ZodOptional<z.ZodString>;
4093
4093
  variantSha256s: z.ZodRecord<z.ZodEnum<{
4094
4094
  full: "full";
4095
- poster: "poster";
4096
4095
  small: "small";
4096
+ poster: "poster";
4097
4097
  medium: "medium";
4098
4098
  main: "main";
4099
4099
  }> & z.core.$partial, z.ZodString>;
@@ -4357,8 +4357,8 @@ export declare const COLLECTION_SCHEMAS: {
4357
4357
  ownerId: z.ZodString;
4358
4358
  variantKeys: z.ZodArray<z.ZodEnum<{
4359
4359
  full: "full";
4360
- poster: "poster";
4361
4360
  small: "small";
4361
+ poster: "poster";
4362
4362
  medium: "medium";
4363
4363
  main: "main";
4364
4364
  }>>;
@@ -5572,8 +5572,8 @@ export declare const COLLECTION_SCHEMAS: {
5572
5572
  }, z.core.$strict>;
5573
5573
  readonly 'childSafetyCases/{caseId}/childSafetyCaseAccounts/{uid}': z.ZodObject<{
5574
5574
  role: z.ZodEnum<{
5575
- uploader: "uploader";
5576
5575
  requester: "requester";
5576
+ uploader: "uploader";
5577
5577
  distributor: "distributor";
5578
5578
  questionable: "questionable";
5579
5579
  }>;
@@ -5595,8 +5595,8 @@ export declare const COLLECTION_SCHEMAS: {
5595
5595
  }, z.core.$strict>;
5596
5596
  readonly 'childSafetyCases/{caseId}/childSafetyCaseAccounts/{uid}/childSafetyCaseAccountHistory/{historyId}': z.ZodObject<{
5597
5597
  role: z.ZodEnum<{
5598
- uploader: "uploader";
5599
5598
  requester: "requester";
5599
+ uploader: "uploader";
5600
5600
  distributor: "distributor";
5601
5601
  questionable: "questionable";
5602
5602
  }>;
@@ -5796,6 +5796,7 @@ export declare const COLLECTION_SCHEMAS: {
5796
5796
  workProject: "workProject";
5797
5797
  workRealm: "workRealm";
5798
5798
  audition: "audition";
5799
+ url: "url";
5799
5800
  username: "username";
5800
5801
  mediaAsset: "mediaAsset";
5801
5802
  hallItem: "hallItem";
@@ -5809,7 +5810,6 @@ export declare const COLLECTION_SCHEMAS: {
5809
5810
  guildInviteMessage: "guildInviteMessage";
5810
5811
  conversationFile: "conversationFile";
5811
5812
  guildChatMessage: "guildChatMessage";
5812
- url: "url";
5813
5813
  additionalText: "additionalText";
5814
5814
  }>;
5815
5815
  authorizedFor: z.ZodObject<{
@@ -5888,8 +5888,8 @@ export declare const COLLECTION_SCHEMAS: {
5888
5888
  originalSha256: z.ZodOptional<z.ZodString>;
5889
5889
  variantSha256s: z.ZodRecord<z.ZodEnum<{
5890
5890
  full: "full";
5891
- poster: "poster";
5892
5891
  small: "small";
5892
+ poster: "poster";
5893
5893
  medium: "medium";
5894
5894
  main: "main";
5895
5895
  }> & z.core.$partial, z.ZodString>;
@@ -6043,8 +6043,8 @@ export declare const COLLECTION_SCHEMAS: {
6043
6043
  originalSha256: z.ZodOptional<z.ZodString>;
6044
6044
  variantSha256s: z.ZodRecord<z.ZodEnum<{
6045
6045
  full: "full";
6046
- poster: "poster";
6047
6046
  small: "small";
6047
+ poster: "poster";
6048
6048
  medium: "medium";
6049
6049
  main: "main";
6050
6050
  }> & z.core.$partial, z.ZodString>;
@@ -6559,6 +6559,7 @@ export declare const COLLECTION_SCHEMAS: {
6559
6559
  workProject: "workProject";
6560
6560
  workRealm: "workRealm";
6561
6561
  audition: "audition";
6562
+ url: "url";
6562
6563
  username: "username";
6563
6564
  mediaAsset: "mediaAsset";
6564
6565
  hallItem: "hallItem";
@@ -6572,7 +6573,6 @@ export declare const COLLECTION_SCHEMAS: {
6572
6573
  guildInviteMessage: "guildInviteMessage";
6573
6574
  conversationFile: "conversationFile";
6574
6575
  guildChatMessage: "guildChatMessage";
6575
- url: "url";
6576
6576
  additionalText: "additionalText";
6577
6577
  }>;
6578
6578
  surfaceLabel: z.ZodString;
@@ -92,8 +92,8 @@ export declare const ChildSafetyDecisionKindSchema: z.ZodEnum<{
92
92
  export type ChildSafetyDecisionKind = z.infer<typeof ChildSafetyDecisionKindSchema>;
93
93
  /** §A1b accounts[].role on a case. */
94
94
  export declare const ChildSafetyAccountRoleSchema: z.ZodEnum<{
95
- uploader: "uploader";
96
95
  requester: "requester";
96
+ uploader: "uploader";
97
97
  distributor: "distributor";
98
98
  questionable: "questionable";
99
99
  }>;
@@ -442,8 +442,8 @@ export type ChildSafetyDecisionViewV1 = z.infer<typeof ChildSafetyDecisionViewV1
442
442
  * `subjectDisposition` is distinct from the case-level `reportDisposition`. */
443
443
  export declare const ChildSafetyCaseAccountV1Schema: z.ZodObject<{
444
444
  role: z.ZodEnum<{
445
- uploader: "uploader";
446
445
  requester: "requester";
446
+ uploader: "uploader";
447
447
  distributor: "distributor";
448
448
  questionable: "questionable";
449
449
  }>;
@@ -467,8 +467,8 @@ export type ChildSafetyCaseAccountV1 = z.infer<typeof ChildSafetyCaseAccountV1Sc
467
467
  /** …/accounts/{uid}/history/{historyId} — append-only per-account history. */
468
468
  export declare const ChildSafetyCaseAccountHistoryV1Schema: z.ZodObject<{
469
469
  role: z.ZodEnum<{
470
- uploader: "uploader";
471
470
  requester: "requester";
471
+ uploader: "uploader";
472
472
  distributor: "distributor";
473
473
  questionable: "questionable";
474
474
  }>;
@@ -151,8 +151,8 @@ export declare const SafetyEvidenceManifestV1Schema: z.ZodObject<{
151
151
  originalSha256: z.ZodOptional<z.ZodString>;
152
152
  variantSha256s: z.ZodRecord<z.ZodEnum<{
153
153
  full: "full";
154
- poster: "poster";
155
154
  small: "small";
155
+ poster: "poster";
156
156
  medium: "medium";
157
157
  main: "main";
158
158
  }> & z.core.$partial, z.ZodString>;
@@ -343,8 +343,8 @@ export declare const SafetyEvidenceCaptureRequestV1Schema: z.ZodDiscriminatedUni
343
343
  originalSha256: z.ZodOptional<z.ZodString>;
344
344
  variantSha256s: z.ZodRecord<z.ZodEnum<{
345
345
  full: "full";
346
- poster: "poster";
347
346
  small: "small";
347
+ poster: "poster";
348
348
  medium: "medium";
349
349
  main: "main";
350
350
  }> & z.core.$partial, z.ZodString>;
@@ -463,8 +463,8 @@ export declare const SafetyEvidenceJobCaptureControlV1Schema: z.ZodObject<{
463
463
  originalSha256: z.ZodOptional<z.ZodString>;
464
464
  variantSha256s: z.ZodRecord<z.ZodEnum<{
465
465
  full: "full";
466
- poster: "poster";
467
466
  small: "small";
467
+ poster: "poster";
468
468
  medium: "medium";
469
469
  main: "main";
470
470
  }> & z.core.$partial, z.ZodString>;
@@ -607,8 +607,8 @@ export declare const SafetyEvidenceJobItemDocV1Schema: z.ZodUnion<readonly [z.Zo
607
607
  originalSha256: z.ZodOptional<z.ZodString>;
608
608
  variantSha256s: z.ZodRecord<z.ZodEnum<{
609
609
  full: "full";
610
- poster: "poster";
611
610
  small: "small";
611
+ poster: "poster";
612
612
  medium: "medium";
613
613
  main: "main";
614
614
  }> & z.core.$partial, z.ZodString>;
@@ -133,6 +133,7 @@ export declare const TargetLocatorKindSchema: z.ZodEnum<{
133
133
  workProject: "workProject";
134
134
  workRealm: "workRealm";
135
135
  audition: "audition";
136
+ url: "url";
136
137
  username: "username";
137
138
  mediaAsset: "mediaAsset";
138
139
  hallItem: "hallItem";
@@ -146,7 +147,6 @@ export declare const TargetLocatorKindSchema: z.ZodEnum<{
146
147
  guildInviteMessage: "guildInviteMessage";
147
148
  conversationFile: "conversationFile";
148
149
  guildChatMessage: "guildChatMessage";
149
- url: "url";
150
150
  additionalText: "additionalText";
151
151
  }>;
152
152
  export type TargetLocatorKind = z.infer<typeof TargetLocatorKindSchema>;
@@ -156,6 +156,7 @@ export declare const TargetLocatorSummaryV1Schema: z.ZodObject<{
156
156
  workProject: "workProject";
157
157
  workRealm: "workRealm";
158
158
  audition: "audition";
159
+ url: "url";
159
160
  username: "username";
160
161
  mediaAsset: "mediaAsset";
161
162
  hallItem: "hallItem";
@@ -169,7 +170,6 @@ export declare const TargetLocatorSummaryV1Schema: z.ZodObject<{
169
170
  guildInviteMessage: "guildInviteMessage";
170
171
  conversationFile: "conversationFile";
171
172
  guildChatMessage: "guildChatMessage";
172
- url: "url";
173
173
  additionalText: "additionalText";
174
174
  }>;
175
175
  surfaceLabel: z.ZodString;
@@ -98,6 +98,7 @@ export declare const SafetyResourceCommandV1Schema: z.ZodObject<{
98
98
  workProject: "workProject";
99
99
  workRealm: "workRealm";
100
100
  audition: "audition";
101
+ url: "url";
101
102
  username: "username";
102
103
  mediaAsset: "mediaAsset";
103
104
  hallItem: "hallItem";
@@ -111,7 +112,6 @@ export declare const SafetyResourceCommandV1Schema: z.ZodObject<{
111
112
  guildInviteMessage: "guildInviteMessage";
112
113
  conversationFile: "conversationFile";
113
114
  guildChatMessage: "guildChatMessage";
114
- url: "url";
115
115
  additionalText: "additionalText";
116
116
  }>;
117
117
  authorizedFor: z.ZodObject<{
@@ -8,6 +8,13 @@ export declare const UserAccountStatusSchema: z.ZodEnum<{
8
8
  banned: "banned";
9
9
  }>;
10
10
  export type UserAccountStatus = z.infer<typeof UserAccountStatusSchema>;
11
+ /** The status an account holds while no status decision has ever been written: a profile, or a
12
+ * token, with no `status` is an active account. */
13
+ export declare const ABSENT_USER_ACCOUNT_STATUS: "active";
14
+ /** A stored `userProfiles.status` read as the account's status: absent is
15
+ * `ABSENT_USER_ACCOUNT_STATUS`; any value outside `UserAccountStatusSchema` throws, so a
16
+ * malformed status is never enforced, compared, or shown as if it were real. */
17
+ export declare function parseUserAccountStatus(value: unknown): UserAccountStatus;
11
18
  export declare const CraftSkillKindSchema: z.ZodEnum<{
12
19
  original: "original";
13
20
  mimicOnTtt: "mimicOnTtt";
@@ -1 +1 @@
1
- {"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/user.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAgBxB;;yDAEyD;AACzD,eAAO,MAAM,uBAAuB;;;;EAA4C,CAAC;AACjF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAOxE,eAAO,MAAM,oBAAoB;;;;EAAoD,CAAC;AACtF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;0EAE0E;AAC1E,eAAO,MAAM,iCAAiC,EAAE,cAA6B,CAAC;AAM9E,eAAO,MAAM,+BAA+B;;;;;;kBAKjC,CAAC;AACZ,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AAKxF,eAAO,MAAM,2BAA2B;;;;;;;;kBAM7B,CAAC;AACZ,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAqBhF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAe3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmBpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E,eAAO,MAAM,uBAAuB;;;;;;;;;iBAKlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,eAAO,MAAM,sBAAsB;;;;;;;;;;;iBAOjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,eAAO,MAAM,2BAA2B;;;;;;iBAMtC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwCzB,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD,eAAO,MAAM,oBAAoB;;;;;;;;;iBAqB/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,uBAAuB;;;;;iBAalC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE;;;GAGG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8DhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
1
+ {"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/user.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAgBxB;;yDAEyD;AACzD,eAAO,MAAM,uBAAuB;;;;EAA4C,CAAC;AACjF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE;oDACoD;AACpD,eAAO,MAAM,0BAA0B,UAAgD,CAAC;AAExF;;iFAEiF;AACjF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,iBAAiB,CAExE;AAOD,eAAO,MAAM,oBAAoB;;;;EAAoD,CAAC;AACtF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;0EAE0E;AAC1E,eAAO,MAAM,iCAAiC,EAAE,cAA6B,CAAC;AAM9E,eAAO,MAAM,+BAA+B;;;;;;kBAKjC,CAAC;AACZ,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AAKxF,eAAO,MAAM,2BAA2B;;;;;;;;kBAM7B,CAAC;AACZ,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAqBhF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAe3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmBpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E,eAAO,MAAM,uBAAuB;;;;;;;;;iBAKlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,eAAO,MAAM,sBAAsB;;;;;;;;;;;iBAOjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,eAAO,MAAM,2BAA2B;;;;;;iBAMtC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwCzB,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD,eAAO,MAAM,oBAAoB;;;;;;;;;iBAqB/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,uBAAuB;;;;;iBAalC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE;;;GAGG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8DhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
@@ -18,6 +18,15 @@ const mediaKindSchema = ContentMediaKindSchema;
18
18
  * authoritative value; the chat access projection and the status-reconcile queue
19
19
  * derive from the same set). Never re-declare inline. */
20
20
  export const UserAccountStatusSchema = z.enum(['active', 'suspended', 'banned']);
21
+ /** The status an account holds while no status decision has ever been written: a profile, or a
22
+ * token, with no `status` is an active account. */
23
+ export const ABSENT_USER_ACCOUNT_STATUS = 'active';
24
+ /** A stored `userProfiles.status` read as the account's status: absent is
25
+ * `ABSENT_USER_ACCOUNT_STATUS`; any value outside `UserAccountStatusSchema` throws, so a
26
+ * malformed status is never enforced, compared, or shown as if it were real. */
27
+ export function parseUserAccountStatus(value) {
28
+ return value === undefined ? ABSENT_USER_ACCOUNT_STATUS : UserAccountStatusSchema.parse(value);
29
+ }
21
30
  // Craft-skill kind — mandatory choice at upload, no default (see ttt-prod
22
31
  // docs/design/profile-and-craft-skills.md). 'original' = the artisan's own original creation;
23
32
  // 'mimicOnTtt' = a performance/recreation of work that originated in the TTT community
@@ -1 +1 @@
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';\nimport { ModerationHiddenBySchema } from './moderation.js';\nimport {\n calendarDateSchema,\n documentIdSegmentSchema,\n} from '../schemas/atoms.js';\nimport { PublicDocumentAcceptanceSchema, PublicDocumentVersionOrNoneSchema } from './public-documents.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/** The ONE craft-skill kind that carries a `source` reference. The discriminated\n * CraftSkillSchema arm below and every upload-time validator derive from this named\n * declaration rather than re-quoting the member (ENG-005 / ARCH-102). */\nexport const CRAFT_SKILL_KIND_REQUIRING_SOURCE: CraftSkillKind = 'mimicOnTtt';\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: documentIdSegmentSchema,\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 hiddenBy: ModerationHiddenBySchema.optional(),\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 hiddenBy: ModerationHiddenBySchema.optional(),\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 status: UserAccountStatusSchema.optional(),\n // Stamped by the one status writer on every status change: when, and the acting admin/operator\n // uid (a system actor writes its own id). Absent on an account whose status never changed.\n statusUpdatedAt: z.number().optional(),\n // Either the authenticated actor's uid or a stable namespaced system actor\n // identifier (for example `system:autoHashLock`); never null.\n statusUpdatedBy: z.string().min(1).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 /**\n * The Terms / Privacy versions accepted at registration, read server-side from the live\n * docs at acceptance time — never client-supplied, never a hardcoded constant. Kept for the\n * accounts that recorded them; the current per-document record is\n * `privateData.publicDocumentAcceptance`.\n *\n * `0` is the sentinel for \"registered while no legal document was published\" (a fresh\n * environment's first account). Published versions start at 1, so 0 can never equal a live\n * version — which is deliberate: it keeps the record from claiming consent that never\n * happened, and leaves the version-bump re-acceptance path free to catch the account once\n * real legal content ships.\n */\n termsVersion: z.number().int().nonnegative().optional(),\n privacyVersion: z.number().int().nonnegative().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: calendarDateSchema.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 // The rules-and-agreements `version` in force when the user accepted; 0 when no versioned\n // rules doc existed yet, so a later real version 1 still re-prompts.\n squareStreetzAgreementsVersion: PublicDocumentVersionOrNoneSchema.optional(),\n // The rules-and-agreements version in force when the user accepted the Artisan upgrade's\n // agreement, read server-side in the grant transaction (the grant time is the profile's\n // `artisanCreator` stamp). Same 0 sentinel as `squareStreetzAgreementsVersion`.\n artisanCreatorAgreementsVersion: PublicDocumentVersionOrNoneSchema.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 // The latest accepted version of each public document and the accepted level (see\n // PublicDocumentAcceptanceSchema). Written by registration and the acceptance callable only;\n // the `docsAccepted` claim mirrors `acceptedLevel`. Absent = nothing accepted (level 0).\n publicDocumentAcceptance: PublicDocumentAcceptanceSchema.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 // Counts the owner's Craft publishes and deletes. Each one reads this doc and writes the next\n // value inside its own transaction, so two publishes that both counted a free Craft slot write\n // the same document and conflict instead of both landing past the cap (BACKEND-116). Absent\n // until the first Craft change (read as 0); a moderation hide never writes it.\n craftSkillChangeMarker: z.number().int().nonnegative().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';\nimport { ModerationHiddenBySchema } from './moderation.js';\nimport {\n calendarDateSchema,\n documentIdSegmentSchema,\n} from '../schemas/atoms.js';\nimport { PublicDocumentAcceptanceSchema, PublicDocumentVersionOrNoneSchema } from './public-documents.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/** The status an account holds while no status decision has ever been written: a profile, or a\n * token, with no `status` is an active account. */\nexport const ABSENT_USER_ACCOUNT_STATUS = 'active' as const satisfies UserAccountStatus;\n\n/** A stored `userProfiles.status` read as the account's status: absent is\n * `ABSENT_USER_ACCOUNT_STATUS`; any value outside `UserAccountStatusSchema` throws, so a\n * malformed status is never enforced, compared, or shown as if it were real. */\nexport function parseUserAccountStatus(value: unknown): UserAccountStatus {\n return value === undefined ? ABSENT_USER_ACCOUNT_STATUS : UserAccountStatusSchema.parse(value);\n}\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/** The ONE craft-skill kind that carries a `source` reference. The discriminated\n * CraftSkillSchema arm below and every upload-time validator derive from this named\n * declaration rather than re-quoting the member (ENG-005 / ARCH-102). */\nexport const CRAFT_SKILL_KIND_REQUIRING_SOURCE: CraftSkillKind = 'mimicOnTtt';\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: documentIdSegmentSchema,\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 hiddenBy: ModerationHiddenBySchema.optional(),\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 hiddenBy: ModerationHiddenBySchema.optional(),\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 status: UserAccountStatusSchema.optional(),\n // Stamped by the one status writer on every status change: when, and the acting admin/operator\n // uid (a system actor writes its own id). Absent on an account whose status never changed.\n statusUpdatedAt: z.number().optional(),\n // Either the authenticated actor's uid or a stable namespaced system actor\n // identifier (for example `system:autoHashLock`); never null.\n statusUpdatedBy: z.string().min(1).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 /**\n * The Terms / Privacy versions accepted at registration, read server-side from the live\n * docs at acceptance time — never client-supplied, never a hardcoded constant. Kept for the\n * accounts that recorded them; the current per-document record is\n * `privateData.publicDocumentAcceptance`.\n *\n * `0` is the sentinel for \"registered while no legal document was published\" (a fresh\n * environment's first account). Published versions start at 1, so 0 can never equal a live\n * version — which is deliberate: it keeps the record from claiming consent that never\n * happened, and leaves the version-bump re-acceptance path free to catch the account once\n * real legal content ships.\n */\n termsVersion: z.number().int().nonnegative().optional(),\n privacyVersion: z.number().int().nonnegative().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: calendarDateSchema.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 // The rules-and-agreements `version` in force when the user accepted; 0 when no versioned\n // rules doc existed yet, so a later real version 1 still re-prompts.\n squareStreetzAgreementsVersion: PublicDocumentVersionOrNoneSchema.optional(),\n // The rules-and-agreements version in force when the user accepted the Artisan upgrade's\n // agreement, read server-side in the grant transaction (the grant time is the profile's\n // `artisanCreator` stamp). Same 0 sentinel as `squareStreetzAgreementsVersion`.\n artisanCreatorAgreementsVersion: PublicDocumentVersionOrNoneSchema.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 // The latest accepted version of each public document and the accepted level (see\n // PublicDocumentAcceptanceSchema). Written by registration and the acceptance callable only;\n // the `docsAccepted` claim mirrors `acceptedLevel`. Absent = nothing accepted (level 0).\n publicDocumentAcceptance: PublicDocumentAcceptanceSchema.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 // Counts the owner's Craft publishes and deletes. Each one reads this doc and writes the next\n // value inside its own transaction, so two publishes that both counted a free Craft slot write\n // the same document and conflict instead of both landing past the cap (BACKEND-116). Absent\n // until the first Craft change (read as 0); a moderation hide never writes it.\n craftSkillChangeMarker: z.number().int().nonnegative().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,4 +1,5 @@
1
1
  import { type HallContentSubItemSurface } from '../constants/hall-content-routing.js';
2
+ import { type WorkSectionPaths } from '../paths/work-section-paths.js';
2
3
  export declare const HALL_LIBRARY_TARGET_FIELDS: {
3
4
  readonly 'hallLibrary-cover-square': "coverSquareAssetId";
4
5
  readonly 'hallLibrary-cover-poster': "coverPosterAssetId";
@@ -41,8 +42,19 @@ export declare const HALL_LIBRARY_SUB_ITEM_SURFACE_BY_ORIGIN: {
41
42
  readonly 'television-episode-photo': "televisionEpisode";
42
43
  readonly 'television-episode-video': "televisionEpisode";
43
44
  };
44
- /** True when this origin is valid for the addressed working sub-item surface. */
45
- export declare function isHallLibrarySubItemOriginForSurface(origin: HallLibrarySubItemFileOrigin, surface: HallLibrarySubItemSurface): boolean;
45
+ /** Where one sub-item upload lands: the working surface it addresses, the canonical builder of
46
+ * that surface's sub-item document, and the field it fills. */
47
+ export interface HallLibrarySubItemMediaSlot {
48
+ readonly surface: HallLibrarySubItemSurface;
49
+ readonly ownerDoc: WorkSectionPaths['subItem'];
50
+ readonly field: HallLibrarySubItemTargetField;
51
+ }
52
+ /**
53
+ * One entry per sub-item upload origin, derived from the routing and field maps above: a writer
54
+ * takes the document it writes AND the field it fills from the same lookup, so the two cannot name
55
+ * different origins, and a job whose addressed surface is not its entry's surface is refused.
56
+ */
57
+ export declare const HALL_LIBRARY_SUB_ITEM_MEDIA_SLOTS: Readonly<Record<HallLibrarySubItemFileOrigin, HallLibrarySubItemMediaSlot>>;
46
58
  /** True when the origin writes a cover field on the hall parent / Work section doc. */
47
59
  export declare function isHallLibraryCoverFileOrigin(origin: string): origin is HallLibraryCoverFileOrigin;
48
60
  /** True when the origin writes a media field on a chapter / track / episode doc. */
@@ -1 +1 @@
1
- {"version":3,"file":"hall-library-target-fields.d.ts","sourceRoot":"","sources":["../../src/media/hall-library-target-fields.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,sCAAsC,CAAC;AAa9C,eAAO,MAAM,0BAA0B;;;;;;;;;CASiB,CAAC;AAEzD,MAAM,MAAM,qBAAqB,GAAG,MAAM,OAAO,0BAA0B,CAAC;AAC5E,MAAM,MAAM,sBAAsB,GAAG,OAAO,0BAA0B,CAAC,qBAAqB,CAAC,CAAC;AAU9F,MAAM,MAAM,0BAA0B,GACpC,OAAO,CAAC,qBAAqB,EAAE,qBAAqB,MAAM,EAAE,CAAC,CAAC;AAChE,MAAM,MAAM,4BAA4B,GACtC,OAAO,CAAC,qBAAqB,EAAE,0BAA0B,CAAC,CAAC;AAE7D,eAAO,MAAM,gCAAgC;;;;CAI2C,CAAC;AAEzF,eAAO,MAAM,mCAAmC;;;;;;CAM0C,CAAC;AAE3F,MAAM,MAAM,2BAA2B,GACrC,OAAO,gCAAgC,CAAC,0BAA0B,CAAC,CAAC;AACtE,MAAM,MAAM,6BAA6B,GACvC,OAAO,mCAAmC,CAAC,4BAA4B,CAAC,CAAC;AAE3E,gFAAgF;AAChF,MAAM,MAAM,yBAAyB,GAAG,yBAAyB,CAAC;AAElE;;;;GAIG;AACH,eAAO,MAAM,uCAAuC;;;;;;CAMgC,CAAC;AAErF,iFAAiF;AACjF,wBAAgB,oCAAoC,CAClD,MAAM,EAAE,4BAA4B,EACpC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAET;AAED,uFAAuF;AACvF,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,MAAM,GACb,MAAM,IAAI,0BAA0B,CAEtC;AAED,oFAAoF;AACpF,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,MAAM,GACb,MAAM,IAAI,4BAA4B,CAExC;AAOD;mFACmF;AACnF,eAAO,MAAM,+BAA+B,EAAE,SAAS,2BAA2B,EAChC,CAAC;AAEnD;mFACmF;AACnF,eAAO,MAAM,kCAAkC,EAAE,SAAS,6BAA6B,EAClC,CAAC"}
1
+ {"version":3,"file":"hall-library-target-fields.d.ts","sourceRoot":"","sources":["../../src/media/hall-library-target-fields.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAA8B,KAAK,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAcnG,eAAO,MAAM,0BAA0B;;;;;;;;;CASiB,CAAC;AAEzD,MAAM,MAAM,qBAAqB,GAAG,MAAM,OAAO,0BAA0B,CAAC;AAC5E,MAAM,MAAM,sBAAsB,GAAG,OAAO,0BAA0B,CAAC,qBAAqB,CAAC,CAAC;AAU9F,MAAM,MAAM,0BAA0B,GACpC,OAAO,CAAC,qBAAqB,EAAE,qBAAqB,MAAM,EAAE,CAAC,CAAC;AAChE,MAAM,MAAM,4BAA4B,GACtC,OAAO,CAAC,qBAAqB,EAAE,0BAA0B,CAAC,CAAC;AAE7D,eAAO,MAAM,gCAAgC;;;;CAI2C,CAAC;AAEzF,eAAO,MAAM,mCAAmC;;;;;;CAM0C,CAAC;AAE3F,MAAM,MAAM,2BAA2B,GACrC,OAAO,gCAAgC,CAAC,0BAA0B,CAAC,CAAC;AACtE,MAAM,MAAM,6BAA6B,GACvC,OAAO,mCAAmC,CAAC,4BAA4B,CAAC,CAAC;AAE3E,gFAAgF;AAChF,MAAM,MAAM,yBAAyB,GAAG,yBAAyB,CAAC;AAElE;;;;GAIG;AACH,eAAO,MAAM,uCAAuC;;;;;;CAMgC,CAAC;AAErF;gEACgE;AAChE,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,OAAO,EAAE,yBAAyB,CAAC;IAC5C,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAC/C,QAAQ,CAAC,KAAK,EAAE,6BAA6B,CAAC;CAC/C;AAUD;;;;GAIG;AACH,eAAO,MAAM,iCAAiC,EAAE,QAAQ,CAAC,MAAM,CAAC,4BAA4B,EAAE,2BAA2B,CAAC,CAYvH,CAAC;AAEJ,uFAAuF;AACvF,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,MAAM,GACb,MAAM,IAAI,0BAA0B,CAEtC;AAED,oFAAoF;AACpF,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,MAAM,GACb,MAAM,IAAI,4BAA4B,CAExC;AAOD;mFACmF;AACnF,eAAO,MAAM,+BAA+B,EAAE,SAAS,2BAA2B,EAChC,CAAC;AAEnD;mFACmF;AACnF,eAAO,MAAM,kCAAkC,EAAE,SAAS,6BAA6B,EAClC,CAAC"}
@@ -1,4 +1,6 @@
1
1
  import { HALL_CONTENT_SURFACE_NAMES_BY_WORK_TYPE, } from '../constants/hall-content-routing.js';
2
+ import { WORK_SECTION_PATHS_BY_TYPE } from '../paths/work-section-paths.js';
3
+ import { WORK_PROJECT_TYPE_KEYS } from '../types/content.js';
2
4
  // Server-side mapping from hallLibrary/sub-item fileOrigin to the doc field
3
5
  // that receives the processed media-asset reference (never a URL — see
4
6
  // ttt-prod docs/design/media-assets-and-protected-serving.md).
@@ -44,10 +46,25 @@ export const HALL_LIBRARY_SUB_ITEM_SURFACE_BY_ORIGIN = {
44
46
  'television-episode-photo': HALL_CONTENT_SURFACE_NAMES_BY_WORK_TYPE.Television.subItemSurface,
45
47
  'television-episode-video': HALL_CONTENT_SURFACE_NAMES_BY_WORK_TYPE.Television.subItemSurface,
46
48
  };
47
- /** True when this origin is valid for the addressed working sub-item surface. */
48
- export function isHallLibrarySubItemOriginForSurface(origin, surface) {
49
- return HALL_LIBRARY_SUB_ITEM_SURFACE_BY_ORIGIN[origin] === surface;
49
+ function subItemBuilderForSurface(surface) {
50
+ const workType = WORK_PROJECT_TYPE_KEYS.find((type) => HALL_CONTENT_SURFACE_NAMES_BY_WORK_TYPE[type].subItemSurface === surface);
51
+ if (!workType)
52
+ throw new Error(`no Work type owns the sub-item surface ${surface}`);
53
+ return WORK_SECTION_PATHS_BY_TYPE[workType].subItem;
50
54
  }
55
+ /**
56
+ * One entry per sub-item upload origin, derived from the routing and field maps above: a writer
57
+ * takes the document it writes AND the field it fills from the same lookup, so the two cannot name
58
+ * different origins, and a job whose addressed surface is not its entry's surface is refused.
59
+ */
60
+ export const HALL_LIBRARY_SUB_ITEM_MEDIA_SLOTS = Object.freeze(Object.fromEntries(Object.keys(HALL_LIBRARY_SUB_ITEM_SURFACE_BY_ORIGIN).map((origin) => [
61
+ origin,
62
+ Object.freeze({
63
+ surface: HALL_LIBRARY_SUB_ITEM_SURFACE_BY_ORIGIN[origin],
64
+ ownerDoc: subItemBuilderForSurface(HALL_LIBRARY_SUB_ITEM_SURFACE_BY_ORIGIN[origin]),
65
+ field: HALL_LIBRARY_SUB_ITEM_TARGET_FIELDS[origin],
66
+ }),
67
+ ])));
51
68
  /** True when the origin writes a cover field on the hall parent / Work section doc. */
52
69
  export function isHallLibraryCoverFileOrigin(origin) {
53
70
  return Object.prototype.hasOwnProperty.call(HALL_LIBRARY_COVER_TARGET_FIELDS, origin);
@@ -1 +1 @@
1
- {"version":3,"file":"hall-library-target-fields.js","sourceRoot":"","sources":["../../src/media/hall-library-target-fields.ts"],"names":[],"mappings":"AACA,OAAO,EACL,uCAAuC,GAExC,MAAM,sCAAsC,CAAC;AAE9C,4EAA4E;AAC5E,uEAAuE;AACvE,+DAA+D;AAC/D,EAAE;AACF,kEAAkE;AAClE,sEAAsE;AACtE,oEAAoE;AACpE,oDAAoD;AACpD,EAAE;AACF,qEAAqE;AACrE,qCAAqC;AACrC,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,0BAA0B,EAAK,oBAAoB;IACnD,0BAA0B,EAAK,oBAAoB;IACnD,6BAA6B,EAAE,uBAAuB;IACtD,eAAe,EAAY,cAAc;IACzC,kBAAkB,EAAe,cAAc;IAC/C,kBAAkB,EAAe,cAAc;IAC/C,0BAA0B,EAAe,cAAc;IACvD,0BAA0B,EAAe,cAAc;CACD,CAAC;AAkBzD,MAAM,CAAC,MAAM,gCAAgC,GAAG;IAC9C,0BAA0B,EAAK,0BAA0B,CAAC,0BAA0B,CAAC;IACrF,0BAA0B,EAAK,0BAA0B,CAAC,0BAA0B,CAAC;IACrF,6BAA6B,EAAE,0BAA0B,CAAC,6BAA6B,CAAC;CACF,CAAC;AAEzF,MAAM,CAAC,MAAM,mCAAmC,GAAG;IACjD,eAAe,EAAa,0BAA0B,CAAC,eAAe,CAAC;IACvE,kBAAkB,EAAU,0BAA0B,CAAC,kBAAkB,CAAC;IAC1E,kBAAkB,EAAU,0BAA0B,CAAC,kBAAkB,CAAC;IAC1E,0BAA0B,EAAE,0BAA0B,CAAC,0BAA0B,CAAC;IAClF,0BAA0B,EAAE,0BAA0B,CAAC,0BAA0B,CAAC;CACM,CAAC;AAU3F;;;;GAIG;AACH,MAAM,CAAC,MAAM,uCAAuC,GAAG;IACrD,eAAe,EAAE,uCAAuC,CAAC,KAAK,CAAC,cAAc;IAC7E,kBAAkB,EAAE,uCAAuC,CAAC,KAAK,CAAC,cAAc;IAChF,kBAAkB,EAAE,uCAAuC,CAAC,KAAK,CAAC,cAAc;IAChF,0BAA0B,EAAE,uCAAuC,CAAC,UAAU,CAAC,cAAc;IAC7F,0BAA0B,EAAE,uCAAuC,CAAC,UAAU,CAAC,cAAc;CACX,CAAC;AAErF,iFAAiF;AACjF,MAAM,UAAU,oCAAoC,CAClD,MAAoC,EACpC,OAAkC;IAElC,OAAO,uCAAuC,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC;AACrE,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,4BAA4B,CAC1C,MAAc;IAEd,OAAO,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,gCAAgC,EAAE,MAAM,CAAC,CAAC;AACxF,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,8BAA8B,CAC5C,MAAc;IAEd,OAAO,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,mCAAmC,EAAE,MAAM,CAAC,CAAC;AAC3F,CAAC;AAGD,SAAS,cAAc,CAAmB,cAA2C;IACnF,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC;AAED;mFACmF;AACnF,MAAM,CAAC,MAAM,+BAA+B,GAC1C,cAAc,CAAC,gCAAgC,CAAC,CAAC;AAEnD;mFACmF;AACnF,MAAM,CAAC,MAAM,kCAAkC,GAC7C,cAAc,CAAC,mCAAmC,CAAC,CAAC","sourcesContent":["import type { FileOrigin } from './file-origin.js';\nimport {\n HALL_CONTENT_SURFACE_NAMES_BY_WORK_TYPE,\n type HallContentSubItemSurface,\n} from '../constants/hall-content-routing.js';\n\n// Server-side mapping from hallLibrary/sub-item fileOrigin to the doc field\n// that receives the processed media-asset reference (never a URL — see\n// ttt-prod docs/design/media-assets-and-protected-serving.md).\n//\n// Owned in ttt-core because it's a contract fact about the upload\n// pipeline — same tier as TTT_MEDIA_SPECS and PATH_BUILDERS. Frontend\n// never reads this. Processors look the field up after deriving the\n// target doc path from the typed IDs in targetInfo.\n//\n// The Partial<Record<FileOrigin, string>> constraint guarantees only\n// valid FileOrigin strings are keys.\nexport const HALL_LIBRARY_TARGET_FIELDS = {\n 'hallLibrary-cover-square': 'coverSquareAssetId',\n 'hallLibrary-cover-poster': 'coverPosterAssetId',\n 'hallLibrary-cover-cinematic': 'coverCinematicAssetId',\n 'chapter-photo': 'photoAssetId',\n 'tune-track-photo': 'photoAssetId',\n 'tune-track-audio': 'audioAssetId',\n 'television-episode-photo': 'photoAssetId',\n 'television-episode-video': 'videoAssetId',\n} as const satisfies Partial<Record<FileOrigin, string>>;\n\nexport type HallLibraryFileOrigin = keyof typeof HALL_LIBRARY_TARGET_FIELDS;\nexport type HallLibraryTargetField = typeof HALL_LIBRARY_TARGET_FIELDS[HallLibraryFileOrigin];\n\n// The same map split by WRITE LEVEL. A cover origin attaches its field on the hall\n// PARENT (the Work's tale/tune/television section doc); a sub-item origin attaches on a\n// chapter / track / episode doc. A processor owns exactly one level, so indexing the whole\n// map there types the write against fields the document it writes never declares.\n//\n// Both subsets are derived from the one map above — no field name is restated — and the\n// `satisfies Pick<...>` constraints close the partition at compile time: an origin added to\n// the parent map lands in one of the two key unions and fails to build until it is listed.\nexport type HallLibraryCoverFileOrigin =\n Extract<HallLibraryFileOrigin, `hallLibrary-cover-${string}`>;\nexport type HallLibrarySubItemFileOrigin =\n Exclude<HallLibraryFileOrigin, HallLibraryCoverFileOrigin>;\n\nexport const HALL_LIBRARY_COVER_TARGET_FIELDS = {\n 'hallLibrary-cover-square': HALL_LIBRARY_TARGET_FIELDS['hallLibrary-cover-square'],\n 'hallLibrary-cover-poster': HALL_LIBRARY_TARGET_FIELDS['hallLibrary-cover-poster'],\n 'hallLibrary-cover-cinematic': HALL_LIBRARY_TARGET_FIELDS['hallLibrary-cover-cinematic'],\n} as const satisfies Pick<typeof HALL_LIBRARY_TARGET_FIELDS, HallLibraryCoverFileOrigin>;\n\nexport const HALL_LIBRARY_SUB_ITEM_TARGET_FIELDS = {\n 'chapter-photo': HALL_LIBRARY_TARGET_FIELDS['chapter-photo'],\n 'tune-track-photo': HALL_LIBRARY_TARGET_FIELDS['tune-track-photo'],\n 'tune-track-audio': HALL_LIBRARY_TARGET_FIELDS['tune-track-audio'],\n 'television-episode-photo': HALL_LIBRARY_TARGET_FIELDS['television-episode-photo'],\n 'television-episode-video': HALL_LIBRARY_TARGET_FIELDS['television-episode-video'],\n} as const satisfies Pick<typeof HALL_LIBRARY_TARGET_FIELDS, HallLibrarySubItemFileOrigin>;\n\nexport type HallLibraryCoverTargetField =\n typeof HALL_LIBRARY_COVER_TARGET_FIELDS[HallLibraryCoverFileOrigin];\nexport type HallLibrarySubItemTargetField =\n typeof HALL_LIBRARY_SUB_ITEM_TARGET_FIELDS[HallLibrarySubItemFileOrigin];\n\n/** The working sub-item surface addressed by a Hall-library sub-item upload. */\nexport type HallLibrarySubItemSurface = HallContentSubItemSurface;\n\n/**\n * Canonical upload-origin → working-sub-item routing. The processor uses this to derive\n * publicationArgs, and the publication adapter uses the same declaration to reject a\n * malformed persisted job before it can attach a media field to the wrong document shape.\n */\nexport const HALL_LIBRARY_SUB_ITEM_SURFACE_BY_ORIGIN = {\n 'chapter-photo': HALL_CONTENT_SURFACE_NAMES_BY_WORK_TYPE.Tales.subItemSurface,\n 'tune-track-photo': HALL_CONTENT_SURFACE_NAMES_BY_WORK_TYPE.Tunes.subItemSurface,\n 'tune-track-audio': HALL_CONTENT_SURFACE_NAMES_BY_WORK_TYPE.Tunes.subItemSurface,\n 'television-episode-photo': HALL_CONTENT_SURFACE_NAMES_BY_WORK_TYPE.Television.subItemSurface,\n 'television-episode-video': HALL_CONTENT_SURFACE_NAMES_BY_WORK_TYPE.Television.subItemSurface,\n} as const satisfies Record<HallLibrarySubItemFileOrigin, HallLibrarySubItemSurface>;\n\n/** True when this origin is valid for the addressed working sub-item surface. */\nexport function isHallLibrarySubItemOriginForSurface(\n origin: HallLibrarySubItemFileOrigin,\n surface: HallLibrarySubItemSurface,\n): boolean {\n return HALL_LIBRARY_SUB_ITEM_SURFACE_BY_ORIGIN[origin] === surface;\n}\n\n/** True when the origin writes a cover field on the hall parent / Work section doc. */\nexport function isHallLibraryCoverFileOrigin(\n origin: string,\n): origin is HallLibraryCoverFileOrigin {\n return Object.prototype.hasOwnProperty.call(HALL_LIBRARY_COVER_TARGET_FIELDS, origin);\n}\n\n/** True when the origin writes a media field on a chapter / track / episode doc. */\nexport function isHallLibrarySubItemFileOrigin(\n origin: string,\n): origin is HallLibrarySubItemFileOrigin {\n return Object.prototype.hasOwnProperty.call(HALL_LIBRARY_SUB_ITEM_TARGET_FIELDS, origin);\n}\n\n\nfunction distinctFields<F extends string>(fieldsByOrigin: Readonly<Record<string, F>>): readonly F[] {\n return [...new Set(Object.values(fieldsByOrigin))];\n}\n\n/** Every asset-reference field a Hall parent (the Work's tale / tune / television section, and its\n * published Hall item) can carry — derived from the cover map, never restated. */\nexport const HALL_LIBRARY_COVER_ASSET_FIELDS: readonly HallLibraryCoverTargetField[] =\n distinctFields(HALL_LIBRARY_COVER_TARGET_FIELDS);\n\n/** Every asset-reference field a chapter / track / episode can carry — derived from the sub-item\n * map, never restated (several origins share one field, so each appears once). */\nexport const HALL_LIBRARY_SUB_ITEM_ASSET_FIELDS: readonly HallLibrarySubItemTargetField[] =\n distinctFields(HALL_LIBRARY_SUB_ITEM_TARGET_FIELDS);\n"]}
1
+ {"version":3,"file":"hall-library-target-fields.js","sourceRoot":"","sources":["../../src/media/hall-library-target-fields.ts"],"names":[],"mappings":"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","sourcesContent":["import type { FileOrigin } from './file-origin.js';\nimport {\n HALL_CONTENT_SURFACE_NAMES_BY_WORK_TYPE,\n type HallContentSubItemSurface,\n} from '../constants/hall-content-routing.js';\nimport { WORK_SECTION_PATHS_BY_TYPE, type WorkSectionPaths } from '../paths/work-section-paths.js';\nimport { WORK_PROJECT_TYPE_KEYS } from '../types/content.js';\n\n// Server-side mapping from hallLibrary/sub-item fileOrigin to the doc field\n// that receives the processed media-asset reference (never a URL — see\n// ttt-prod docs/design/media-assets-and-protected-serving.md).\n//\n// Owned in ttt-core because it's a contract fact about the upload\n// pipeline — same tier as TTT_MEDIA_SPECS and PATH_BUILDERS. Frontend\n// never reads this. Processors look the field up after deriving the\n// target doc path from the typed IDs in targetInfo.\n//\n// The Partial<Record<FileOrigin, string>> constraint guarantees only\n// valid FileOrigin strings are keys.\nexport const HALL_LIBRARY_TARGET_FIELDS = {\n 'hallLibrary-cover-square': 'coverSquareAssetId',\n 'hallLibrary-cover-poster': 'coverPosterAssetId',\n 'hallLibrary-cover-cinematic': 'coverCinematicAssetId',\n 'chapter-photo': 'photoAssetId',\n 'tune-track-photo': 'photoAssetId',\n 'tune-track-audio': 'audioAssetId',\n 'television-episode-photo': 'photoAssetId',\n 'television-episode-video': 'videoAssetId',\n} as const satisfies Partial<Record<FileOrigin, string>>;\n\nexport type HallLibraryFileOrigin = keyof typeof HALL_LIBRARY_TARGET_FIELDS;\nexport type HallLibraryTargetField = typeof HALL_LIBRARY_TARGET_FIELDS[HallLibraryFileOrigin];\n\n// The same map split by WRITE LEVEL. A cover origin attaches its field on the hall\n// PARENT (the Work's tale/tune/television section doc); a sub-item origin attaches on a\n// chapter / track / episode doc. A processor owns exactly one level, so indexing the whole\n// map there types the write against fields the document it writes never declares.\n//\n// Both subsets are derived from the one map above — no field name is restated — and the\n// `satisfies Pick<...>` constraints close the partition at compile time: an origin added to\n// the parent map lands in one of the two key unions and fails to build until it is listed.\nexport type HallLibraryCoverFileOrigin =\n Extract<HallLibraryFileOrigin, `hallLibrary-cover-${string}`>;\nexport type HallLibrarySubItemFileOrigin =\n Exclude<HallLibraryFileOrigin, HallLibraryCoverFileOrigin>;\n\nexport const HALL_LIBRARY_COVER_TARGET_FIELDS = {\n 'hallLibrary-cover-square': HALL_LIBRARY_TARGET_FIELDS['hallLibrary-cover-square'],\n 'hallLibrary-cover-poster': HALL_LIBRARY_TARGET_FIELDS['hallLibrary-cover-poster'],\n 'hallLibrary-cover-cinematic': HALL_LIBRARY_TARGET_FIELDS['hallLibrary-cover-cinematic'],\n} as const satisfies Pick<typeof HALL_LIBRARY_TARGET_FIELDS, HallLibraryCoverFileOrigin>;\n\nexport const HALL_LIBRARY_SUB_ITEM_TARGET_FIELDS = {\n 'chapter-photo': HALL_LIBRARY_TARGET_FIELDS['chapter-photo'],\n 'tune-track-photo': HALL_LIBRARY_TARGET_FIELDS['tune-track-photo'],\n 'tune-track-audio': HALL_LIBRARY_TARGET_FIELDS['tune-track-audio'],\n 'television-episode-photo': HALL_LIBRARY_TARGET_FIELDS['television-episode-photo'],\n 'television-episode-video': HALL_LIBRARY_TARGET_FIELDS['television-episode-video'],\n} as const satisfies Pick<typeof HALL_LIBRARY_TARGET_FIELDS, HallLibrarySubItemFileOrigin>;\n\nexport type HallLibraryCoverTargetField =\n typeof HALL_LIBRARY_COVER_TARGET_FIELDS[HallLibraryCoverFileOrigin];\nexport type HallLibrarySubItemTargetField =\n typeof HALL_LIBRARY_SUB_ITEM_TARGET_FIELDS[HallLibrarySubItemFileOrigin];\n\n/** The working sub-item surface addressed by a Hall-library sub-item upload. */\nexport type HallLibrarySubItemSurface = HallContentSubItemSurface;\n\n/**\n * Canonical upload-origin → working-sub-item routing. The processor uses this to derive\n * publicationArgs, and the publication adapter uses the same declaration to reject a\n * malformed persisted job before it can attach a media field to the wrong document shape.\n */\nexport const HALL_LIBRARY_SUB_ITEM_SURFACE_BY_ORIGIN = {\n 'chapter-photo': HALL_CONTENT_SURFACE_NAMES_BY_WORK_TYPE.Tales.subItemSurface,\n 'tune-track-photo': HALL_CONTENT_SURFACE_NAMES_BY_WORK_TYPE.Tunes.subItemSurface,\n 'tune-track-audio': HALL_CONTENT_SURFACE_NAMES_BY_WORK_TYPE.Tunes.subItemSurface,\n 'television-episode-photo': HALL_CONTENT_SURFACE_NAMES_BY_WORK_TYPE.Television.subItemSurface,\n 'television-episode-video': HALL_CONTENT_SURFACE_NAMES_BY_WORK_TYPE.Television.subItemSurface,\n} as const satisfies Record<HallLibrarySubItemFileOrigin, HallLibrarySubItemSurface>;\n\n/** Where one sub-item upload lands: the working surface it addresses, the canonical builder of\n * that surface's sub-item document, and the field it fills. */\nexport interface HallLibrarySubItemMediaSlot {\n readonly surface: HallLibrarySubItemSurface;\n readonly ownerDoc: WorkSectionPaths['subItem'];\n readonly field: HallLibrarySubItemTargetField;\n}\n\nfunction subItemBuilderForSurface(surface: HallLibrarySubItemSurface): WorkSectionPaths['subItem'] {\n const workType = WORK_PROJECT_TYPE_KEYS.find(\n (type) => HALL_CONTENT_SURFACE_NAMES_BY_WORK_TYPE[type].subItemSurface === surface,\n );\n if (!workType) throw new Error(`no Work type owns the sub-item surface ${surface}`);\n return WORK_SECTION_PATHS_BY_TYPE[workType].subItem;\n}\n\n/**\n * One entry per sub-item upload origin, derived from the routing and field maps above: a writer\n * takes the document it writes AND the field it fills from the same lookup, so the two cannot name\n * different origins, and a job whose addressed surface is not its entry's surface is refused.\n */\nexport const HALL_LIBRARY_SUB_ITEM_MEDIA_SLOTS: Readonly<Record<HallLibrarySubItemFileOrigin, HallLibrarySubItemMediaSlot>> =\n Object.freeze(\n Object.fromEntries(\n (Object.keys(HALL_LIBRARY_SUB_ITEM_SURFACE_BY_ORIGIN) as HallLibrarySubItemFileOrigin[]).map((origin) => [\n origin,\n Object.freeze({\n surface: HALL_LIBRARY_SUB_ITEM_SURFACE_BY_ORIGIN[origin],\n ownerDoc: subItemBuilderForSurface(HALL_LIBRARY_SUB_ITEM_SURFACE_BY_ORIGIN[origin]),\n field: HALL_LIBRARY_SUB_ITEM_TARGET_FIELDS[origin],\n }),\n ]),\n ) as Record<HallLibrarySubItemFileOrigin, HallLibrarySubItemMediaSlot>,\n );\n\n/** True when the origin writes a cover field on the hall parent / Work section doc. */\nexport function isHallLibraryCoverFileOrigin(\n origin: string,\n): origin is HallLibraryCoverFileOrigin {\n return Object.prototype.hasOwnProperty.call(HALL_LIBRARY_COVER_TARGET_FIELDS, origin);\n}\n\n/** True when the origin writes a media field on a chapter / track / episode doc. */\nexport function isHallLibrarySubItemFileOrigin(\n origin: string,\n): origin is HallLibrarySubItemFileOrigin {\n return Object.prototype.hasOwnProperty.call(HALL_LIBRARY_SUB_ITEM_TARGET_FIELDS, origin);\n}\n\n\nfunction distinctFields<F extends string>(fieldsByOrigin: Readonly<Record<string, F>>): readonly F[] {\n return [...new Set(Object.values(fieldsByOrigin))];\n}\n\n/** Every asset-reference field a Hall parent (the Work's tale / tune / television section, and its\n * published Hall item) can carry — derived from the cover map, never restated. */\nexport const HALL_LIBRARY_COVER_ASSET_FIELDS: readonly HallLibraryCoverTargetField[] =\n distinctFields(HALL_LIBRARY_COVER_TARGET_FIELDS);\n\n/** Every asset-reference field a chapter / track / episode can carry — derived from the sub-item\n * map, never restated (several origins share one field, so each appears once). */\nexport const HALL_LIBRARY_SUB_ITEM_ASSET_FIELDS: readonly HallLibrarySubItemTargetField[] =\n distinctFields(HALL_LIBRARY_SUB_ITEM_TARGET_FIELDS);\n"]}
@@ -762,8 +762,8 @@ export declare const SafetyStagedActionSchema: z.ZodDiscriminatedUnion<[z.ZodObj
762
762
  reasonInternal: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
763
763
  reasonUserFacing: z.ZodString;
764
764
  role: z.ZodEnum<{
765
- uploader: "uploader";
766
765
  requester: "requester";
766
+ uploader: "uploader";
767
767
  distributor: "distributor";
768
768
  questionable: "questionable";
769
769
  }>;
@@ -817,8 +817,8 @@ export declare const SafetyCaseInputSchema: z.ZodObject<{
817
817
  reasonInternal: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
818
818
  reasonUserFacing: z.ZodString;
819
819
  role: z.ZodEnum<{
820
- uploader: "uploader";
821
820
  requester: "requester";
821
+ uploader: "uploader";
822
822
  distributor: "distributor";
823
823
  questionable: "questionable";
824
824
  }>;
@@ -17,16 +17,16 @@ export type GetOwnAuditionEntryStatusInput = z.infer<typeof GetOwnAuditionEntryS
17
17
  /** `none` — no entry; `visible` — an entry the caller can read; `underReview` — an entry moderation hid. */
18
18
  export declare const OWN_AUDITION_ENTRY_STATUS_VALUES: readonly ["none", "visible", "underReview"];
19
19
  export declare const OwnAuditionEntryStatusSchema: z.ZodEnum<{
20
- underReview: "underReview";
21
20
  none: "none";
21
+ underReview: "underReview";
22
22
  visible: "visible";
23
23
  }>;
24
24
  export type OwnAuditionEntryStatus = z.infer<typeof OwnAuditionEntryStatusSchema>;
25
25
  export declare const GetOwnAuditionEntryStatusResultSchema: z.ZodObject<{
26
26
  auditionId: z.ZodString;
27
27
  entryStatus: z.ZodEnum<{
28
- underReview: "underReview";
29
28
  none: "none";
29
+ underReview: "underReview";
30
30
  visible: "visible";
31
31
  }>;
32
32
  }, z.core.$strip>;
@@ -28,8 +28,8 @@ export declare const CommandAccountActionInputSchema: z.ZodObject<{
28
28
  reasonInternal: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
29
29
  reasonUserFacing: z.ZodString;
30
30
  role: z.ZodEnum<{
31
- uploader: "uploader";
32
31
  requester: "requester";
32
+ uploader: "uploader";
33
33
  distributor: "distributor";
34
34
  questionable: "questionable";
35
35
  }>;
@@ -444,6 +444,7 @@ export declare const TakeItDownRequestConsoleRowSchema: z.ZodObject<{
444
444
  workProject: "workProject";
445
445
  workRealm: "workRealm";
446
446
  audition: "audition";
447
+ url: "url";
447
448
  username: "username";
448
449
  mediaAsset: "mediaAsset";
449
450
  hallItem: "hallItem";
@@ -457,7 +458,6 @@ export declare const TakeItDownRequestConsoleRowSchema: z.ZodObject<{
457
458
  guildInviteMessage: "guildInviteMessage";
458
459
  conversationFile: "conversationFile";
459
460
  guildChatMessage: "guildChatMessage";
460
- url: "url";
461
461
  additionalText: "additionalText";
462
462
  }>;
463
463
  surfaceLabel: z.ZodString;
@@ -893,6 +893,7 @@ export declare const GetSafetyCaseConsoleResultSchema: z.ZodObject<{
893
893
  workProject: "workProject";
894
894
  workRealm: "workRealm";
895
895
  audition: "audition";
896
+ url: "url";
896
897
  username: "username";
897
898
  mediaAsset: "mediaAsset";
898
899
  hallItem: "hallItem";
@@ -906,7 +907,6 @@ export declare const GetSafetyCaseConsoleResultSchema: z.ZodObject<{
906
907
  guildInviteMessage: "guildInviteMessage";
907
908
  conversationFile: "conversationFile";
908
909
  guildChatMessage: "guildChatMessage";
909
- url: "url";
910
910
  additionalText: "additionalText";
911
911
  }>;
912
912
  surfaceLabel: z.ZodString;
@@ -1369,6 +1369,7 @@ export declare const SafetyCaseConsoleRowChangeSchema: z.ZodDiscriminatedUnion<[
1369
1369
  workProject: "workProject";
1370
1370
  workRealm: "workRealm";
1371
1371
  audition: "audition";
1372
+ url: "url";
1372
1373
  username: "username";
1373
1374
  mediaAsset: "mediaAsset";
1374
1375
  hallItem: "hallItem";
@@ -1382,7 +1383,6 @@ export declare const SafetyCaseConsoleRowChangeSchema: z.ZodDiscriminatedUnion<[
1382
1383
  guildInviteMessage: "guildInviteMessage";
1383
1384
  conversationFile: "conversationFile";
1384
1385
  guildChatMessage: "guildChatMessage";
1385
- url: "url";
1386
1386
  additionalText: "additionalText";
1387
1387
  }>;
1388
1388
  surfaceLabel: z.ZodString;
@@ -1782,6 +1782,7 @@ export declare const SafetyCaseConsolePatchSchema: z.ZodObject<{
1782
1782
  workProject: "workProject";
1783
1783
  workRealm: "workRealm";
1784
1784
  audition: "audition";
1785
+ url: "url";
1785
1786
  username: "username";
1786
1787
  mediaAsset: "mediaAsset";
1787
1788
  hallItem: "hallItem";
@@ -1795,7 +1796,6 @@ export declare const SafetyCaseConsolePatchSchema: z.ZodObject<{
1795
1796
  guildInviteMessage: "guildInviteMessage";
1796
1797
  conversationFile: "conversationFile";
1797
1798
  guildChatMessage: "guildChatMessage";
1798
- url: "url";
1799
1799
  additionalText: "additionalText";
1800
1800
  }>;
1801
1801
  surfaceLabel: z.ZodString;
@@ -2246,6 +2246,7 @@ export declare const DecideTakeItDownValidityResultSchema: z.ZodObject<{
2246
2246
  workProject: "workProject";
2247
2247
  workRealm: "workRealm";
2248
2248
  audition: "audition";
2249
+ url: "url";
2249
2250
  username: "username";
2250
2251
  mediaAsset: "mediaAsset";
2251
2252
  hallItem: "hallItem";
@@ -2259,7 +2260,6 @@ export declare const DecideTakeItDownValidityResultSchema: z.ZodObject<{
2259
2260
  guildInviteMessage: "guildInviteMessage";
2260
2261
  conversationFile: "conversationFile";
2261
2262
  guildChatMessage: "guildChatMessage";
2262
- url: "url";
2263
2263
  additionalText: "additionalText";
2264
2264
  }>;
2265
2265
  surfaceLabel: z.ZodString;
@@ -2717,6 +2717,7 @@ export declare const SetNciiMinorAssessmentResultSchema: z.ZodObject<{
2717
2717
  workProject: "workProject";
2718
2718
  workRealm: "workRealm";
2719
2719
  audition: "audition";
2720
+ url: "url";
2720
2721
  username: "username";
2721
2722
  mediaAsset: "mediaAsset";
2722
2723
  hallItem: "hallItem";
@@ -2730,7 +2731,6 @@ export declare const SetNciiMinorAssessmentResultSchema: z.ZodObject<{
2730
2731
  guildInviteMessage: "guildInviteMessage";
2731
2732
  conversationFile: "conversationFile";
2732
2733
  guildChatMessage: "guildChatMessage";
2733
- url: "url";
2734
2734
  additionalText: "additionalText";
2735
2735
  }>;
2736
2736
  surfaceLabel: z.ZodString;
@@ -3175,6 +3175,7 @@ export declare const RefetchProtectedCaseContextResultSchema: z.ZodObject<{
3175
3175
  workProject: "workProject";
3176
3176
  workRealm: "workRealm";
3177
3177
  audition: "audition";
3178
+ url: "url";
3178
3179
  username: "username";
3179
3180
  mediaAsset: "mediaAsset";
3180
3181
  hallItem: "hallItem";
@@ -3188,7 +3189,6 @@ export declare const RefetchProtectedCaseContextResultSchema: z.ZodObject<{
3188
3189
  guildInviteMessage: "guildInviteMessage";
3189
3190
  conversationFile: "conversationFile";
3190
3191
  guildChatMessage: "guildChatMessage";
3191
- url: "url";
3192
3192
  additionalText: "additionalText";
3193
3193
  }>;
3194
3194
  surfaceLabel: z.ZodString;
@@ -3633,6 +3633,7 @@ export declare const MarkNcmecPortalCompleteResultSchema: z.ZodObject<{
3633
3633
  workProject: "workProject";
3634
3634
  workRealm: "workRealm";
3635
3635
  audition: "audition";
3636
+ url: "url";
3636
3637
  username: "username";
3637
3638
  mediaAsset: "mediaAsset";
3638
3639
  hallItem: "hallItem";
@@ -3646,7 +3647,6 @@ export declare const MarkNcmecPortalCompleteResultSchema: z.ZodObject<{
3646
3647
  guildInviteMessage: "guildInviteMessage";
3647
3648
  conversationFile: "conversationFile";
3648
3649
  guildChatMessage: "guildChatMessage";
3649
- url: "url";
3650
3650
  additionalText: "additionalText";
3651
3651
  }>;
3652
3652
  surfaceLabel: z.ZodString;
@@ -4090,6 +4090,7 @@ export declare const ReopenSafetyCaseResultSchema: z.ZodObject<{
4090
4090
  workProject: "workProject";
4091
4091
  workRealm: "workRealm";
4092
4092
  audition: "audition";
4093
+ url: "url";
4093
4094
  username: "username";
4094
4095
  mediaAsset: "mediaAsset";
4095
4096
  hallItem: "hallItem";
@@ -4103,7 +4104,6 @@ export declare const ReopenSafetyCaseResultSchema: z.ZodObject<{
4103
4104
  guildInviteMessage: "guildInviteMessage";
4104
4105
  conversationFile: "conversationFile";
4105
4106
  guildChatMessage: "guildChatMessage";
4106
- url: "url";
4107
4107
  additionalText: "additionalText";
4108
4108
  }>;
4109
4109
  surfaceLabel: z.ZodString;
@@ -4558,6 +4558,7 @@ export declare const AdminReplayDeadLetterResultSchema: z.ZodDiscriminatedUnion<
4558
4558
  workProject: "workProject";
4559
4559
  workRealm: "workRealm";
4560
4560
  audition: "audition";
4561
+ url: "url";
4561
4562
  username: "username";
4562
4563
  mediaAsset: "mediaAsset";
4563
4564
  hallItem: "hallItem";
@@ -4571,7 +4572,6 @@ export declare const AdminReplayDeadLetterResultSchema: z.ZodDiscriminatedUnion<
4571
4572
  guildInviteMessage: "guildInviteMessage";
4572
4573
  conversationFile: "conversationFile";
4573
4574
  guildChatMessage: "guildChatMessage";
4574
- url: "url";
4575
4575
  additionalText: "additionalText";
4576
4576
  }>;
4577
4577
  surfaceLabel: z.ZodString;
@@ -5031,6 +5031,7 @@ export declare const AdminReplayDeadLetterResultSchema: z.ZodDiscriminatedUnion<
5031
5031
  workProject: "workProject";
5032
5032
  workRealm: "workRealm";
5033
5033
  audition: "audition";
5034
+ url: "url";
5034
5035
  username: "username";
5035
5036
  mediaAsset: "mediaAsset";
5036
5037
  hallItem: "hallItem";
@@ -5044,7 +5045,6 @@ export declare const AdminReplayDeadLetterResultSchema: z.ZodDiscriminatedUnion<
5044
5045
  guildInviteMessage: "guildInviteMessage";
5045
5046
  conversationFile: "conversationFile";
5046
5047
  guildChatMessage: "guildChatMessage";
5047
- url: "url";
5048
5048
  additionalText: "additionalText";
5049
5049
  }>;
5050
5050
  surfaceLabel: z.ZodString;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttt-productions/ttt-core",
3
- "version": "0.79.80",
3
+ "version": "0.79.83",
4
4
  "description": "Core types, Firestore path constants, and shared constants for TTT Productions",
5
5
  "repository": {
6
6
  "type": "git",
@@ -118,8 +118,8 @@
118
118
  "@ttt-productions/edge-protocol-core": "^0.1.12",
119
119
  "@ttt-productions/input-format-core": "^0.1.1",
120
120
  "@ttt-productions/media-schemas": "^0.14.9",
121
- "@ttt-productions/notification-core": "^0.15.13",
122
- "@ttt-productions/report-core": "^0.16.14",
121
+ "@ttt-productions/notification-core": "^0.15.14",
122
+ "@ttt-productions/report-core": "^0.16.16",
123
123
  "zod": "^4.4.3"
124
124
  },
125
125
  "author": "DJ (TTT Productions)",