@ttt-productions/ttt-core 0.78.26 → 0.78.27
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.
- package/dist/constants/app-mode.d.ts +9 -0
- package/dist/constants/app-mode.d.ts.map +1 -1
- package/dist/constants/app-mode.js +22 -0
- package/dist/constants/app-mode.js.map +1 -1
- package/dist/constants/chat.d.ts +8 -0
- package/dist/constants/chat.d.ts.map +1 -1
- package/dist/constants/chat.js +9 -0
- package/dist/constants/chat.js.map +1 -1
- package/dist/doc-schemas/messaging.d.ts +1 -0
- package/dist/doc-schemas/messaging.d.ts.map +1 -1
- package/dist/doc-schemas/messaging.js +9 -0
- package/dist/doc-schemas/messaging.js.map +1 -1
- package/dist/doc-schemas/registry.d.ts +2 -0
- package/dist/doc-schemas/registry.d.ts.map +1 -1
- package/dist/doc-schemas/work-project.d.ts +1 -0
- package/dist/doc-schemas/work-project.d.ts.map +1 -1
- package/dist/doc-schemas/work-project.js +8 -0
- package/dist/doc-schemas/work-project.js.map +1 -1
- package/package.json +2 -2
|
@@ -21,6 +21,10 @@ export interface TttLimits {
|
|
|
21
21
|
maxFileFolders: number;
|
|
22
22
|
maxWorkFiles: number;
|
|
23
23
|
maxWorkFileStorageBytes: number;
|
|
24
|
+
/** Chat-ATTACHMENT storage per Work (stored output bytes across all of the
|
|
25
|
+
* Work's chat channels). Separate from `maxWorkFileStorageBytes` — the file
|
|
26
|
+
* system and chat are distinct containers with distinct caps. */
|
|
27
|
+
maxChatAttachmentStorageBytes: number;
|
|
24
28
|
maxWorkProjectAuditions: number;
|
|
25
29
|
maxCommissionListings: number;
|
|
26
30
|
maxChapters: number;
|
|
@@ -29,6 +33,11 @@ export interface TttLimits {
|
|
|
29
33
|
maxTuneTracks: number;
|
|
30
34
|
maxTelevisionEpisodes: number;
|
|
31
35
|
};
|
|
36
|
+
/** Guild-INVITE conversation container (a 1:1 invite thread with no Work behind it). */
|
|
37
|
+
guildInvite: {
|
|
38
|
+
/** Chat-attachment storage per invite thread (stored output bytes). */
|
|
39
|
+
maxChatAttachmentStorageBytes: number;
|
|
40
|
+
};
|
|
32
41
|
hall: {
|
|
33
42
|
maxSubmitBatch: number;
|
|
34
43
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-mode.d.ts","sourceRoot":"","sources":["../../src/constants/app-mode.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEzC,8EAA8E;AAC9E,eAAO,MAAM,QAAQ,EAAE,OAAmB,CAAC;AAE3C,qDAAqD;AACrD,eAAO,MAAM,MAAM,GAAI,CAAC,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,KAAG,CACM,CAAC;AAEvD,yDAAyD;AACzD,MAAM,MAAM,eAAe,GAAG,GAAG,MAAM,IAAI,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC;AAE1E,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,eAAe,CAAC;CACzB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE;QACJ,cAAc,EAAE,MAAM,CAAC;QACvB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,yBAAyB,EAAE,MAAM,CAAC;KACnC,CAAC;IACF,WAAW,EAAE;QACX,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,YAAY,EAAE,MAAM,CAAC;QACrB,uBAAuB,EAAE,MAAM,CAAC;QAChC,uBAAuB,EAAE,MAAM,CAAC;QAChC,qBAAqB,EAAE,MAAM,CAAC;QAC9B,WAAW,EAAE,MAAM,CAAC;QACpB,oFAAoF;QACpF,uBAAuB,EAAE,MAAM,CAAC;QAChC,aAAa,EAAE,MAAM,CAAC;QACtB,qBAAqB,EAAE,MAAM,CAAC;KAC/B,CAAC;IACF,IAAI,EAAE;QACJ,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,OAAO,EAAE;QACP,wBAAwB,EAAE,MAAM,CAAC;QACjC,qBAAqB,EAAE,MAAM,CAAC;KAC/B,CAAC;IACF,gFAAgF;IAChF,UAAU,EAAE;QACV,MAAM,EAAE,cAAc,CAAC;QACvB,YAAY,EAAE,cAAc,CAAC;QAC7B,aAAa,EAAE,cAAc,CAAC;QAC9B,IAAI,EAAE,cAAc,CAAC;QACrB,UAAU,EAAE,cAAc,CAAC;QAC3B,gBAAgB,EAAE,cAAc,CAAC;QACjC,kBAAkB,EAAE,cAAc,CAAC;QACnC,YAAY,EAAE,cAAc,CAAC;QAC7B,UAAU,EAAE,cAAc,CAAC;QAC3B,aAAa,EAAE,cAAc,CAAC;QAC9B,UAAU,EAAE,cAAc,CAAC;QAC3B,cAAc,EAAE,cAAc,CAAC;QAC/B,cAAc,EAAE,cAAc,CAAC;QAC/B,gBAAgB,EAAE,cAAc,CAAC;QACjC,MAAM,EAAE,cAAc,CAAC;QACvB,eAAe,EAAE,cAAc,CAAC;QAChC,kBAAkB,EAAE,cAAc,CAAC;QACnC,WAAW,EAAE,cAAc,CAAC;QAC5B,sBAAsB,EAAE,cAAc,CAAC;QACvC,oBAAoB,EAAE,cAAc,CAAC;QACrC,sBAAsB,EAAE,cAAc,CAAC;QACvC,QAAQ,EAAE,cAAc,CAAC;QACzB,iBAAiB,EAAE,cAAc,CAAC;QAClC,aAAa,EAAE,cAAc,CAAC;QAC9B,kBAAkB,EAAE,cAAc,CAAC;QACnC,cAAc,EAAE,cAAc,CAAC;QAC/B,eAAe,EAAE,cAAc,CAAC;KACjC,CAAC;CACH;AAED,eAAO,MAAM,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"app-mode.d.ts","sourceRoot":"","sources":["../../src/constants/app-mode.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEzC,8EAA8E;AAC9E,eAAO,MAAM,QAAQ,EAAE,OAAmB,CAAC;AAE3C,qDAAqD;AACrD,eAAO,MAAM,MAAM,GAAI,CAAC,EAAE,SAAS,CAAC,EAAE,MAAM,CAAC,KAAG,CACM,CAAC;AAEvD,yDAAyD;AACzD,MAAM,MAAM,eAAe,GAAG,GAAG,MAAM,IAAI,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC;AAE1E,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,eAAe,CAAC;CACzB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE;QACJ,cAAc,EAAE,MAAM,CAAC;QACvB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,yBAAyB,EAAE,MAAM,CAAC;KACnC,CAAC;IACF,WAAW,EAAE;QACX,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,YAAY,EAAE,MAAM,CAAC;QACrB,uBAAuB,EAAE,MAAM,CAAC;QAChC;;0EAEkE;QAClE,6BAA6B,EAAE,MAAM,CAAC;QACtC,uBAAuB,EAAE,MAAM,CAAC;QAChC,qBAAqB,EAAE,MAAM,CAAC;QAC9B,WAAW,EAAE,MAAM,CAAC;QACpB,oFAAoF;QACpF,uBAAuB,EAAE,MAAM,CAAC;QAChC,aAAa,EAAE,MAAM,CAAC;QACtB,qBAAqB,EAAE,MAAM,CAAC;KAC/B,CAAC;IACF,wFAAwF;IACxF,WAAW,EAAE;QACX,uEAAuE;QACvE,6BAA6B,EAAE,MAAM,CAAC;KACvC,CAAC;IACF,IAAI,EAAE;QACJ,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,OAAO,EAAE;QACP,wBAAwB,EAAE,MAAM,CAAC;QACjC,qBAAqB,EAAE,MAAM,CAAC;KAC/B,CAAC;IACF,gFAAgF;IAChF,UAAU,EAAE;QACV,MAAM,EAAE,cAAc,CAAC;QACvB,YAAY,EAAE,cAAc,CAAC;QAC7B,aAAa,EAAE,cAAc,CAAC;QAC9B,IAAI,EAAE,cAAc,CAAC;QACrB,UAAU,EAAE,cAAc,CAAC;QAC3B,gBAAgB,EAAE,cAAc,CAAC;QACjC,kBAAkB,EAAE,cAAc,CAAC;QACnC,YAAY,EAAE,cAAc,CAAC;QAC7B,UAAU,EAAE,cAAc,CAAC;QAC3B,aAAa,EAAE,cAAc,CAAC;QAC9B,UAAU,EAAE,cAAc,CAAC;QAC3B,cAAc,EAAE,cAAc,CAAC;QAC/B,cAAc,EAAE,cAAc,CAAC;QAC/B,gBAAgB,EAAE,cAAc,CAAC;QACjC,MAAM,EAAE,cAAc,CAAC;QACvB,eAAe,EAAE,cAAc,CAAC;QAChC,kBAAkB,EAAE,cAAc,CAAC;QACnC,WAAW,EAAE,cAAc,CAAC;QAC5B,sBAAsB,EAAE,cAAc,CAAC;QACvC,oBAAoB,EAAE,cAAc,CAAC;QACrC,sBAAsB,EAAE,cAAc,CAAC;QACvC,QAAQ,EAAE,cAAc,CAAC;QACzB,iBAAiB,EAAE,cAAc,CAAC;QAClC,aAAa,EAAE,cAAc,CAAC;QAC9B,kBAAkB,EAAE,cAAc,CAAC;QACnC,cAAc,EAAE,cAAc,CAAC;QAC/B,eAAe,EAAE,cAAc,CAAC;KACjC,CAAC;CACH;AAED,eAAO,MAAM,cAAc,EAAE,SA4F5B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,SA+EzB,CAAC;AAEF;uEACuE;AACvE,eAAO,MAAM,aAAa,EAAE,SAA+C,CAAC"}
|
|
@@ -25,6 +25,14 @@ export const CHARTER_LIMITS = {
|
|
|
25
25
|
maxFileFolders: 10,
|
|
26
26
|
maxWorkFiles: 100,
|
|
27
27
|
maxWorkFileStorageBytes: 2_684_354_560, // 2.5 GiB
|
|
28
|
+
// Chat-attachment storage is QUOTA'D PER CONTAINER (DJ ruling 2026-07-25).
|
|
29
|
+
// Counted on STORED OUTPUT bytes (what actually sits in R2 after transcode),
|
|
30
|
+
// never on raw upload bytes. Rationale: a per-file `maxBytes` cap alone bounds
|
|
31
|
+
// one upload but nothing stops unbounded accumulation across thousands of chat
|
|
32
|
+
// messages — this is the abuse brake on that. Deliberately generous so real
|
|
33
|
+
// collaboration never hits it: 2 GiB is thousands of chat images or hours of
|
|
34
|
+
// transcoded chat audio for a single charter Work.
|
|
35
|
+
maxChatAttachmentStorageBytes: 2_147_483_648, // 2 GiB
|
|
28
36
|
maxWorkProjectAuditions: 3,
|
|
29
37
|
maxCommissionListings: 3,
|
|
30
38
|
maxChapters: 5,
|
|
@@ -34,6 +42,12 @@ export const CHARTER_LIMITS = {
|
|
|
34
42
|
maxTuneTracks: 5,
|
|
35
43
|
maxTelevisionEpisodes: 3,
|
|
36
44
|
},
|
|
45
|
+
// A guild-invite thread is a 1:1 negotiation with no Work behind it, so it gets a
|
|
46
|
+
// much smaller container quota than a Work — the same 250 MiB in BOTH modes,
|
|
47
|
+
// because the flip to full-live does not make an invite conversation any longer.
|
|
48
|
+
// Same stored-output accounting and the same abuse-brake rationale as the Work
|
|
49
|
+
// quota above. DJ ruling 2026-07-25.
|
|
50
|
+
guildInvite: { maxChatAttachmentStorageBytes: 262_144_000 }, // 250 MiB
|
|
37
51
|
hall: { maxSubmitBatch: 10 },
|
|
38
52
|
batches: { trendingFeedProcessLimit: 250, maxFeedbackSubmitters: 25 },
|
|
39
53
|
rateLimits: {
|
|
@@ -104,6 +118,11 @@ export const FULL_LIMITS = {
|
|
|
104
118
|
maxFileFolders: 25,
|
|
105
119
|
maxWorkFiles: 1000,
|
|
106
120
|
maxWorkFileStorageBytes: 26_843_545_600, // 25 GiB
|
|
121
|
+
// 10 GiB (full): the same per-container chat-attachment quota as charter, scaled
|
|
122
|
+
// for a public-launch Work with a large guild chatting for months. Still a hard
|
|
123
|
+
// ceiling on unbounded R2 accumulation. See the CHARTER_LIMITS note above.
|
|
124
|
+
// DJ ruling 2026-07-25.
|
|
125
|
+
maxChatAttachmentStorageBytes: 10_737_418_240, // 10 GiB
|
|
107
126
|
maxWorkProjectAuditions: 10,
|
|
108
127
|
maxCommissionListings: 10,
|
|
109
128
|
maxChapters: 50,
|
|
@@ -114,6 +133,9 @@ export const FULL_LIMITS = {
|
|
|
114
133
|
maxTuneTracks: 50,
|
|
115
134
|
maxTelevisionEpisodes: 25,
|
|
116
135
|
},
|
|
136
|
+
// Invite threads are the same 250 MiB in both modes — an invite negotiation is not
|
|
137
|
+
// longer at full-live. See the CHARTER_LIMITS note above. DJ ruling 2026-07-25.
|
|
138
|
+
guildInvite: { maxChatAttachmentStorageBytes: 262_144_000 }, // 250 MiB
|
|
117
139
|
hall: { maxSubmitBatch: 50 },
|
|
118
140
|
batches: { trendingFeedProcessLimit: 1000, maxFeedbackSubmitters: 100 },
|
|
119
141
|
rateLimits: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-mode.js","sourceRoot":"","sources":["../../src/constants/app-mode.ts"],"names":[],"mappings":"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","sourcesContent":["// App mode + the charter/full limit sets — the single published constant that\n// drives the whole app's cost posture. The flip to full-live is: change\n// APP_MODE → publish ttt-core → install in ttt-prod (root + functions) →\n// deploy. There is NO runtime mode flag and NO console toggle.\n// See ttt-prod docs/design/charter-season-and-app-mode.md.\n//\n// Only real cost/abuse drivers vary by mode: media specs (ttt-media-specs.ts),\n// rate-limit values, count caps, batch sizes. Text-length limits and payment\n// min/max are deliberately mode-invariant — with ONE ruled exception (DJ\n// 2026-07-13): chapter body content (maxChapterContentLength), because it\n// bounds threshold-review reading effort per item during charter season.\n\nexport type AppMode = 'charter' | 'full';\n\n/** The deployed mode. Changing this constant (and publishing) IS the flip. */\nexport const APP_MODE: AppMode = 'charter';\n\n/** Pick the active value for a mode-varied limit. */\nexport const byMode = <T>(charter: T, full: T): T =>\n (APP_MODE as AppMode) === 'charter' ? charter : full;\n\n/** Upstash-style sliding-window duration, e.g. '1 h'. */\nexport type RateLimitWindow = `${number} ${'ms' | 's' | 'm' | 'h' | 'd'}`;\n\nexport interface RateLimitValue {\n maxRequests: number;\n window: RateLimitWindow;\n}\n\nexport interface TttLimits {\n mode: AppMode;\n user: {\n maxCraftSkills: number;\n maxOwnedWorkProjects: number;\n maxAssociatedWorkProjects: number;\n };\n workProject: {\n maxGuildSize: number;\n maxFileFolders: number;\n maxWorkFiles: number;\n maxWorkFileStorageBytes: number;\n maxWorkProjectAuditions: number;\n maxCommissionListings: number;\n maxChapters: number;\n /** Chapter BODY length (chars) — the one mode-varied text limit (DJ 2026-07-13). */\n maxChapterContentLength: number;\n maxTuneTracks: number;\n maxTelevisionEpisodes: number;\n };\n hall: {\n maxSubmitBatch: number;\n };\n batches: {\n trendingFeedProcessLimit: number;\n maxFeedbackSubmitters: number;\n };\n /** Values for the backend rate limiters. Prefixes/factory stay in functions. */\n rateLimits: {\n UPLOAD: RateLimitValue;\n ADMIN_UPLOAD: RateLimitValue;\n CONTENT_WRITE: RateLimitValue;\n VOTE: RateLimitValue;\n MODERATION: RateLimitValue;\n SENSITIVE_ACTION: RateLimitValue;\n DISPLAY_NAME_CHECK: RateLimitValue;\n CHAT_MESSAGE: RateLimitValue;\n ADMIN_TASK: RateLimitValue;\n APPEAL_REVIEW: RateLimitValue;\n BAN_ACTION: RateLimitValue;\n SHARE_TRANSFER: RateLimitValue;\n CONTENT_REPORT: RateLimitValue;\n SHORT_LINK_CLICK: RateLimitValue;\n FOLLOW: RateLimitValue;\n MENTION_HISTORY: RateLimitValue;\n ADMIN_MESSAGE_READ: RateLimitValue;\n USER_LOOKUP: RateLimitValue;\n NOTIFICATION_BROADCAST: RateLimitValue;\n NOTIFICATION_ARCHIVE: RateLimitValue;\n NOTIFICATION_MARK_SEEN: RateLimitValue;\n FEEDBACK: RateLimitValue;\n SHORT_LINK_CREATE: RateLimitValue;\n INVITE_ACTION: RateLimitValue;\n LIBRARY_SUBMISSION: RateLimitValue;\n CHANNEL_CREATE: RateLimitValue;\n CHECKOUT_CREATE: RateLimitValue;\n };\n}\n\nexport const CHARTER_LIMITS: TttLimits = {\n mode: 'charter',\n user: {\n maxCraftSkills: 8,\n maxOwnedWorkProjects: 3,\n maxAssociatedWorkProjects: 10,\n },\n workProject: {\n maxGuildSize: 25,\n maxFileFolders: 10,\n maxWorkFiles: 100,\n maxWorkFileStorageBytes: 2_684_354_560, // 2.5 GiB\n maxWorkProjectAuditions: 3,\n maxCommissionListings: 3,\n maxChapters: 5,\n // ~5,000 words — a full real chapter, while keeping the human threshold-review\n // reading effort per item bounded during charter season.\n maxChapterContentLength: 30_000,\n maxTuneTracks: 5,\n maxTelevisionEpisodes: 3,\n },\n hall: { maxSubmitBatch: 10 },\n batches: { trendingFeedProcessLimit: 250, maxFeedbackSubmitters: 25 },\n rateLimits: {\n // Uploads are charged ONCE per upload (in startUpload); the processor-side\n // check is a non-charging guard.\n UPLOAD: { maxRequests: 15, window: '1 h' },\n // A separate HIGHER bucket for uploads performed through the sanctioned admin\n // authority path — never an exemption. Bulk admin setup work (creating 3\n // auditions is ~5 uploads) exhausts the 15/h user bucket; 60/h covers a real\n // bulk admin session while keeping a brake on a compromised admin token and on\n // third-party quota/cost (Vision / Video Intelligence / R2). DJ ruling 2026-07-25.\n ADMIN_UPLOAD: { maxRequests: 60, window: '1 h' },\n // General content-write throttle for the non-upload write callables (text posts,\n // craft-skill edits, support-thread starts) that used to charge UPLOAD. Sharing\n // the 15/h charter upload window meant heavy text posting blocked real uploads\n // and vice versa; a separate 30/h bucket keeps each cost driver on its own\n // ceiling. DJ ruling 2026-07-25.\n CONTENT_WRITE: { maxRequests: 30, window: '1 h' },\n VOTE: { maxRequests: 100, window: '1 h' },\n MODERATION: { maxRequests: 50, window: '1 h' },\n // 30/h: one bucket is shared by ~35 callables (register, become-artisan,\n // create-work, invites, trades, appeals, …) — a real first-hour artisan does\n // 10-15 legitimate sensitive actions; 5/h blocked the intended golden path\n // (proven live by the hosted-dev E2E, 2026-07-07). DJ ruling 2026-07-08.\n SENSITIVE_ACTION: { maxRequests: 30, window: '1 h' },\n // 120/h (charter): checkDisplayNameAvailable is enforceAppCheck:true, so\n // reCAPTCHA-Enterprise attestation is the real abuse gate — this bucket is a\n // cost/DoS ceiling, not the security boundary. It is IP-keyed (pre-registration,\n // no uid yet) and the register form fires it debounced-LIVE as you type, so one\n // legit registrant spends ~3-8 checks and shared NAT/CGNAT multiplies that across\n // everyone on the IP. The old 20/h false-rejected legitimate shared-IP users and\n // could not fit a full hosted-dev E2E suite run on one IP. DJ ruling 2026-07-21.\n DISPLAY_NAME_CHECK: { maxRequests: 120, window: '1 h' },\n CHAT_MESSAGE: { maxRequests: 125, window: '1 h' },\n ADMIN_TASK: { maxRequests: 60, window: '1 h' },\n APPEAL_REVIEW: { maxRequests: 30, window: '1 h' },\n BAN_ACTION: { maxRequests: 20, window: '1 h' },\n SHARE_TRANSFER: { maxRequests: 10, window: '1 h' },\n CONTENT_REPORT: { maxRequests: 5, window: '1 h' },\n SHORT_LINK_CLICK: { maxRequests: 60, window: '1 h' },\n FOLLOW: { maxRequests: 20, window: '1 m' },\n MENTION_HISTORY: { maxRequests: 120, window: '1 h' },\n ADMIN_MESSAGE_READ: { maxRequests: 60, window: '1 h' },\n // Admin exact-account lookup (searchPublicUsers / lookupUserByEmailOrUid) — a read, so a\n // generous per-minute bucket that still backstops a scripted enumeration sweep. Admin-only\n // and not a cost driver, so the value is the same in both modes (like MODERATION/ADMIN_TASK).\n USER_LOOKUP: { maxRequests: 30, window: '1 m' },\n NOTIFICATION_BROADCAST: { maxRequests: 10, window: '1 h' },\n NOTIFICATION_ARCHIVE: { maxRequests: 120, window: '1 h' },\n NOTIFICATION_MARK_SEEN: { maxRequests: 120, window: '1 h' },\n FEEDBACK: { maxRequests: 10, window: '1 h' },\n SHORT_LINK_CREATE: { maxRequests: 30, window: '1 h' },\n INVITE_ACTION: { maxRequests: 30, window: '1 h' },\n LIBRARY_SUBMISSION: { maxRequests: 10, window: '1 h' },\n CHANNEL_CREATE: { maxRequests: 5, window: '1 h' },\n CHECKOUT_CREATE: { maxRequests: 5, window: '1 h' },\n },\n};\n\nexport const FULL_LIMITS: TttLimits = {\n mode: 'full',\n user: {\n maxCraftSkills: 24,\n maxOwnedWorkProjects: 25,\n maxAssociatedWorkProjects: 100,\n },\n workProject: {\n maxGuildSize: 250,\n maxFileFolders: 25,\n maxWorkFiles: 1000,\n maxWorkFileStorageBytes: 26_843_545_600, // 25 GiB\n maxWorkProjectAuditions: 10,\n maxCommissionListings: 10,\n maxChapters: 50,\n // The intentional design ceiling (~17,000 words; trivially inside Firestore's\n // 1 MiB doc limit) — the audit trail deliberately stores field LENGTHS, not\n // content, because chapters can be this large (runUpdateChapterDetails).\n maxChapterContentLength: 100_000,\n maxTuneTracks: 50,\n maxTelevisionEpisodes: 25,\n },\n hall: { maxSubmitBatch: 50 },\n batches: { trendingFeedProcessLimit: 1000, maxFeedbackSubmitters: 100 },\n rateLimits: {\n UPLOAD: { maxRequests: 30, window: '1 h' },\n // 120/h (full): the same sanctioned-admin-path upload bucket as charter, scaled\n // with UPLOAD — always HIGHER than the user bucket, never an exemption, so a\n // compromised admin token and third-party media cost stay bounded. See the\n // CHARTER_LIMITS note above. DJ ruling 2026-07-25.\n ADMIN_UPLOAD: { maxRequests: 120, window: '1 h' },\n // 60/h (full): the same non-upload content-write bucket as charter, scaled with\n // UPLOAD so text writes and media uploads never consume each other's ceiling.\n // See the CHARTER_LIMITS note above. DJ ruling 2026-07-25.\n CONTENT_WRITE: { maxRequests: 60, window: '1 h' },\n VOTE: { maxRequests: 200, window: '1 h' },\n MODERATION: { maxRequests: 50, window: '1 h' },\n // 60/h: full-mode power users managing several works do dozens of legitimate\n // management actions per hour; still a hard backstop against scripts.\n // DJ ruling 2026-07-08 (charter 30 / full 60, single bucket; a bucket split\n // is filed post-launch in ttt-prod docs/post-launch/).\n SENSITIVE_ACTION: { maxRequests: 60, window: '1 h' },\n // 300/h (full): same reasoning as the charter value above (App-Check-gated\n // cost ceiling, IP-keyed, debounced-live). Public-launch CGNAT exposure is far\n // larger — hundreds of concurrent legit registrants can sit behind one carrier\n // IP — so err generous; the only cost of \"too high\" is trivial Firestore reads,\n // while \"too low\" false-rejects real users. Raise on evidence (watch prod logs\n // for legit 429s) rather than pre-emptively tightening. DJ ruling 2026-07-21.\n DISPLAY_NAME_CHECK: { maxRequests: 300, window: '1 h' },\n CHAT_MESSAGE: { maxRequests: 150, window: '1 h' },\n ADMIN_TASK: { maxRequests: 60, window: '1 h' },\n APPEAL_REVIEW: { maxRequests: 30, window: '1 h' },\n BAN_ACTION: { maxRequests: 20, window: '1 h' },\n SHARE_TRANSFER: { maxRequests: 10, window: '1 h' },\n CONTENT_REPORT: { maxRequests: 20, window: '1 h' },\n SHORT_LINK_CLICK: { maxRequests: 60, window: '1 h' },\n FOLLOW: { maxRequests: 60, window: '1 m' },\n MENTION_HISTORY: { maxRequests: 120, window: '1 h' },\n ADMIN_MESSAGE_READ: { maxRequests: 60, window: '1 h' },\n // Admin exact-account lookup — same read bucket in both modes (see CHARTER_LIMITS note).\n USER_LOOKUP: { maxRequests: 30, window: '1 m' },\n NOTIFICATION_BROADCAST: { maxRequests: 10, window: '1 h' },\n NOTIFICATION_ARCHIVE: { maxRequests: 120, window: '1 h' },\n NOTIFICATION_MARK_SEEN: { maxRequests: 120, window: '1 h' },\n FEEDBACK: { maxRequests: 10, window: '1 h' },\n SHORT_LINK_CREATE: { maxRequests: 30, window: '1 h' },\n INVITE_ACTION: { maxRequests: 60, window: '1 h' },\n LIBRARY_SUBMISSION: { maxRequests: 20, window: '1 h' },\n CHANNEL_CREATE: { maxRequests: 20, window: '1 h' },\n CHECKOUT_CREATE: { maxRequests: 20, window: '1 h' },\n },\n};\n\n/** The resolved limit set for the deployed mode. Import THIS (or the alias\n * constants that re-export from it), never CHARTER_/FULL_ directly. */\nexport const ACTIVE_LIMITS: TttLimits = byMode(CHARTER_LIMITS, FULL_LIMITS);\n"]}
|
|
1
|
+
{"version":3,"file":"app-mode.js","sourceRoot":"","sources":["../../src/constants/app-mode.ts"],"names":[],"mappings":"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","sourcesContent":["// App mode + the charter/full limit sets — the single published constant that\n// drives the whole app's cost posture. The flip to full-live is: change\n// APP_MODE → publish ttt-core → install in ttt-prod (root + functions) →\n// deploy. There is NO runtime mode flag and NO console toggle.\n// See ttt-prod docs/design/charter-season-and-app-mode.md.\n//\n// Only real cost/abuse drivers vary by mode: media specs (ttt-media-specs.ts),\n// rate-limit values, count caps, batch sizes. Text-length limits and payment\n// min/max are deliberately mode-invariant — with ONE ruled exception (DJ\n// 2026-07-13): chapter body content (maxChapterContentLength), because it\n// bounds threshold-review reading effort per item during charter season.\n\nexport type AppMode = 'charter' | 'full';\n\n/** The deployed mode. Changing this constant (and publishing) IS the flip. */\nexport const APP_MODE: AppMode = 'charter';\n\n/** Pick the active value for a mode-varied limit. */\nexport const byMode = <T>(charter: T, full: T): T =>\n (APP_MODE as AppMode) === 'charter' ? charter : full;\n\n/** Upstash-style sliding-window duration, e.g. '1 h'. */\nexport type RateLimitWindow = `${number} ${'ms' | 's' | 'm' | 'h' | 'd'}`;\n\nexport interface RateLimitValue {\n maxRequests: number;\n window: RateLimitWindow;\n}\n\nexport interface TttLimits {\n mode: AppMode;\n user: {\n maxCraftSkills: number;\n maxOwnedWorkProjects: number;\n maxAssociatedWorkProjects: number;\n };\n workProject: {\n maxGuildSize: number;\n maxFileFolders: number;\n maxWorkFiles: number;\n maxWorkFileStorageBytes: number;\n /** Chat-ATTACHMENT storage per Work (stored output bytes across all of the\n * Work's chat channels). Separate from `maxWorkFileStorageBytes` — the file\n * system and chat are distinct containers with distinct caps. */\n maxChatAttachmentStorageBytes: number;\n maxWorkProjectAuditions: number;\n maxCommissionListings: number;\n maxChapters: number;\n /** Chapter BODY length (chars) — the one mode-varied text limit (DJ 2026-07-13). */\n maxChapterContentLength: number;\n maxTuneTracks: number;\n maxTelevisionEpisodes: number;\n };\n /** Guild-INVITE conversation container (a 1:1 invite thread with no Work behind it). */\n guildInvite: {\n /** Chat-attachment storage per invite thread (stored output bytes). */\n maxChatAttachmentStorageBytes: number;\n };\n hall: {\n maxSubmitBatch: number;\n };\n batches: {\n trendingFeedProcessLimit: number;\n maxFeedbackSubmitters: number;\n };\n /** Values for the backend rate limiters. Prefixes/factory stay in functions. */\n rateLimits: {\n UPLOAD: RateLimitValue;\n ADMIN_UPLOAD: RateLimitValue;\n CONTENT_WRITE: RateLimitValue;\n VOTE: RateLimitValue;\n MODERATION: RateLimitValue;\n SENSITIVE_ACTION: RateLimitValue;\n DISPLAY_NAME_CHECK: RateLimitValue;\n CHAT_MESSAGE: RateLimitValue;\n ADMIN_TASK: RateLimitValue;\n APPEAL_REVIEW: RateLimitValue;\n BAN_ACTION: RateLimitValue;\n SHARE_TRANSFER: RateLimitValue;\n CONTENT_REPORT: RateLimitValue;\n SHORT_LINK_CLICK: RateLimitValue;\n FOLLOW: RateLimitValue;\n MENTION_HISTORY: RateLimitValue;\n ADMIN_MESSAGE_READ: RateLimitValue;\n USER_LOOKUP: RateLimitValue;\n NOTIFICATION_BROADCAST: RateLimitValue;\n NOTIFICATION_ARCHIVE: RateLimitValue;\n NOTIFICATION_MARK_SEEN: RateLimitValue;\n FEEDBACK: RateLimitValue;\n SHORT_LINK_CREATE: RateLimitValue;\n INVITE_ACTION: RateLimitValue;\n LIBRARY_SUBMISSION: RateLimitValue;\n CHANNEL_CREATE: RateLimitValue;\n CHECKOUT_CREATE: RateLimitValue;\n };\n}\n\nexport const CHARTER_LIMITS: TttLimits = {\n mode: 'charter',\n user: {\n maxCraftSkills: 8,\n maxOwnedWorkProjects: 3,\n maxAssociatedWorkProjects: 10,\n },\n workProject: {\n maxGuildSize: 25,\n maxFileFolders: 10,\n maxWorkFiles: 100,\n maxWorkFileStorageBytes: 2_684_354_560, // 2.5 GiB\n // Chat-attachment storage is QUOTA'D PER CONTAINER (DJ ruling 2026-07-25).\n // Counted on STORED OUTPUT bytes (what actually sits in R2 after transcode),\n // never on raw upload bytes. Rationale: a per-file `maxBytes` cap alone bounds\n // one upload but nothing stops unbounded accumulation across thousands of chat\n // messages — this is the abuse brake on that. Deliberately generous so real\n // collaboration never hits it: 2 GiB is thousands of chat images or hours of\n // transcoded chat audio for a single charter Work.\n maxChatAttachmentStorageBytes: 2_147_483_648, // 2 GiB\n maxWorkProjectAuditions: 3,\n maxCommissionListings: 3,\n maxChapters: 5,\n // ~5,000 words — a full real chapter, while keeping the human threshold-review\n // reading effort per item bounded during charter season.\n maxChapterContentLength: 30_000,\n maxTuneTracks: 5,\n maxTelevisionEpisodes: 3,\n },\n // A guild-invite thread is a 1:1 negotiation with no Work behind it, so it gets a\n // much smaller container quota than a Work — the same 250 MiB in BOTH modes,\n // because the flip to full-live does not make an invite conversation any longer.\n // Same stored-output accounting and the same abuse-brake rationale as the Work\n // quota above. DJ ruling 2026-07-25.\n guildInvite: { maxChatAttachmentStorageBytes: 262_144_000 }, // 250 MiB\n hall: { maxSubmitBatch: 10 },\n batches: { trendingFeedProcessLimit: 250, maxFeedbackSubmitters: 25 },\n rateLimits: {\n // Uploads are charged ONCE per upload (in startUpload); the processor-side\n // check is a non-charging guard.\n UPLOAD: { maxRequests: 15, window: '1 h' },\n // A separate HIGHER bucket for uploads performed through the sanctioned admin\n // authority path — never an exemption. Bulk admin setup work (creating 3\n // auditions is ~5 uploads) exhausts the 15/h user bucket; 60/h covers a real\n // bulk admin session while keeping a brake on a compromised admin token and on\n // third-party quota/cost (Vision / Video Intelligence / R2). DJ ruling 2026-07-25.\n ADMIN_UPLOAD: { maxRequests: 60, window: '1 h' },\n // General content-write throttle for the non-upload write callables (text posts,\n // craft-skill edits, support-thread starts) that used to charge UPLOAD. Sharing\n // the 15/h charter upload window meant heavy text posting blocked real uploads\n // and vice versa; a separate 30/h bucket keeps each cost driver on its own\n // ceiling. DJ ruling 2026-07-25.\n CONTENT_WRITE: { maxRequests: 30, window: '1 h' },\n VOTE: { maxRequests: 100, window: '1 h' },\n MODERATION: { maxRequests: 50, window: '1 h' },\n // 30/h: one bucket is shared by ~35 callables (register, become-artisan,\n // create-work, invites, trades, appeals, …) — a real first-hour artisan does\n // 10-15 legitimate sensitive actions; 5/h blocked the intended golden path\n // (proven live by the hosted-dev E2E, 2026-07-07). DJ ruling 2026-07-08.\n SENSITIVE_ACTION: { maxRequests: 30, window: '1 h' },\n // 120/h (charter): checkDisplayNameAvailable is enforceAppCheck:true, so\n // reCAPTCHA-Enterprise attestation is the real abuse gate — this bucket is a\n // cost/DoS ceiling, not the security boundary. It is IP-keyed (pre-registration,\n // no uid yet) and the register form fires it debounced-LIVE as you type, so one\n // legit registrant spends ~3-8 checks and shared NAT/CGNAT multiplies that across\n // everyone on the IP. The old 20/h false-rejected legitimate shared-IP users and\n // could not fit a full hosted-dev E2E suite run on one IP. DJ ruling 2026-07-21.\n DISPLAY_NAME_CHECK: { maxRequests: 120, window: '1 h' },\n CHAT_MESSAGE: { maxRequests: 125, window: '1 h' },\n ADMIN_TASK: { maxRequests: 60, window: '1 h' },\n APPEAL_REVIEW: { maxRequests: 30, window: '1 h' },\n BAN_ACTION: { maxRequests: 20, window: '1 h' },\n SHARE_TRANSFER: { maxRequests: 10, window: '1 h' },\n CONTENT_REPORT: { maxRequests: 5, window: '1 h' },\n SHORT_LINK_CLICK: { maxRequests: 60, window: '1 h' },\n FOLLOW: { maxRequests: 20, window: '1 m' },\n MENTION_HISTORY: { maxRequests: 120, window: '1 h' },\n ADMIN_MESSAGE_READ: { maxRequests: 60, window: '1 h' },\n // Admin exact-account lookup (searchPublicUsers / lookupUserByEmailOrUid) — a read, so a\n // generous per-minute bucket that still backstops a scripted enumeration sweep. Admin-only\n // and not a cost driver, so the value is the same in both modes (like MODERATION/ADMIN_TASK).\n USER_LOOKUP: { maxRequests: 30, window: '1 m' },\n NOTIFICATION_BROADCAST: { maxRequests: 10, window: '1 h' },\n NOTIFICATION_ARCHIVE: { maxRequests: 120, window: '1 h' },\n NOTIFICATION_MARK_SEEN: { maxRequests: 120, window: '1 h' },\n FEEDBACK: { maxRequests: 10, window: '1 h' },\n SHORT_LINK_CREATE: { maxRequests: 30, window: '1 h' },\n INVITE_ACTION: { maxRequests: 30, window: '1 h' },\n LIBRARY_SUBMISSION: { maxRequests: 10, window: '1 h' },\n CHANNEL_CREATE: { maxRequests: 5, window: '1 h' },\n CHECKOUT_CREATE: { maxRequests: 5, window: '1 h' },\n },\n};\n\nexport const FULL_LIMITS: TttLimits = {\n mode: 'full',\n user: {\n maxCraftSkills: 24,\n maxOwnedWorkProjects: 25,\n maxAssociatedWorkProjects: 100,\n },\n workProject: {\n maxGuildSize: 250,\n maxFileFolders: 25,\n maxWorkFiles: 1000,\n maxWorkFileStorageBytes: 26_843_545_600, // 25 GiB\n // 10 GiB (full): the same per-container chat-attachment quota as charter, scaled\n // for a public-launch Work with a large guild chatting for months. Still a hard\n // ceiling on unbounded R2 accumulation. See the CHARTER_LIMITS note above.\n // DJ ruling 2026-07-25.\n maxChatAttachmentStorageBytes: 10_737_418_240, // 10 GiB\n maxWorkProjectAuditions: 10,\n maxCommissionListings: 10,\n maxChapters: 50,\n // The intentional design ceiling (~17,000 words; trivially inside Firestore's\n // 1 MiB doc limit) — the audit trail deliberately stores field LENGTHS, not\n // content, because chapters can be this large (runUpdateChapterDetails).\n maxChapterContentLength: 100_000,\n maxTuneTracks: 50,\n maxTelevisionEpisodes: 25,\n },\n // Invite threads are the same 250 MiB in both modes — an invite negotiation is not\n // longer at full-live. See the CHARTER_LIMITS note above. DJ ruling 2026-07-25.\n guildInvite: { maxChatAttachmentStorageBytes: 262_144_000 }, // 250 MiB\n hall: { maxSubmitBatch: 50 },\n batches: { trendingFeedProcessLimit: 1000, maxFeedbackSubmitters: 100 },\n rateLimits: {\n UPLOAD: { maxRequests: 30, window: '1 h' },\n // 120/h (full): the same sanctioned-admin-path upload bucket as charter, scaled\n // with UPLOAD — always HIGHER than the user bucket, never an exemption, so a\n // compromised admin token and third-party media cost stay bounded. See the\n // CHARTER_LIMITS note above. DJ ruling 2026-07-25.\n ADMIN_UPLOAD: { maxRequests: 120, window: '1 h' },\n // 60/h (full): the same non-upload content-write bucket as charter, scaled with\n // UPLOAD so text writes and media uploads never consume each other's ceiling.\n // See the CHARTER_LIMITS note above. DJ ruling 2026-07-25.\n CONTENT_WRITE: { maxRequests: 60, window: '1 h' },\n VOTE: { maxRequests: 200, window: '1 h' },\n MODERATION: { maxRequests: 50, window: '1 h' },\n // 60/h: full-mode power users managing several works do dozens of legitimate\n // management actions per hour; still a hard backstop against scripts.\n // DJ ruling 2026-07-08 (charter 30 / full 60, single bucket; a bucket split\n // is filed post-launch in ttt-prod docs/post-launch/).\n SENSITIVE_ACTION: { maxRequests: 60, window: '1 h' },\n // 300/h (full): same reasoning as the charter value above (App-Check-gated\n // cost ceiling, IP-keyed, debounced-live). Public-launch CGNAT exposure is far\n // larger — hundreds of concurrent legit registrants can sit behind one carrier\n // IP — so err generous; the only cost of \"too high\" is trivial Firestore reads,\n // while \"too low\" false-rejects real users. Raise on evidence (watch prod logs\n // for legit 429s) rather than pre-emptively tightening. DJ ruling 2026-07-21.\n DISPLAY_NAME_CHECK: { maxRequests: 300, window: '1 h' },\n CHAT_MESSAGE: { maxRequests: 150, window: '1 h' },\n ADMIN_TASK: { maxRequests: 60, window: '1 h' },\n APPEAL_REVIEW: { maxRequests: 30, window: '1 h' },\n BAN_ACTION: { maxRequests: 20, window: '1 h' },\n SHARE_TRANSFER: { maxRequests: 10, window: '1 h' },\n CONTENT_REPORT: { maxRequests: 20, window: '1 h' },\n SHORT_LINK_CLICK: { maxRequests: 60, window: '1 h' },\n FOLLOW: { maxRequests: 60, window: '1 m' },\n MENTION_HISTORY: { maxRequests: 120, window: '1 h' },\n ADMIN_MESSAGE_READ: { maxRequests: 60, window: '1 h' },\n // Admin exact-account lookup — same read bucket in both modes (see CHARTER_LIMITS note).\n USER_LOOKUP: { maxRequests: 30, window: '1 m' },\n NOTIFICATION_BROADCAST: { maxRequests: 10, window: '1 h' },\n NOTIFICATION_ARCHIVE: { maxRequests: 120, window: '1 h' },\n NOTIFICATION_MARK_SEEN: { maxRequests: 120, window: '1 h' },\n FEEDBACK: { maxRequests: 10, window: '1 h' },\n SHORT_LINK_CREATE: { maxRequests: 30, window: '1 h' },\n INVITE_ACTION: { maxRequests: 60, window: '1 h' },\n LIBRARY_SUBMISSION: { maxRequests: 20, window: '1 h' },\n CHANNEL_CREATE: { maxRequests: 20, window: '1 h' },\n CHECKOUT_CREATE: { maxRequests: 20, window: '1 h' },\n },\n};\n\n/** The resolved limit set for the deployed mode. Import THIS (or the alias\n * constants that re-export from it), never CHARTER_/FULL_ directly. */\nexport const ACTIVE_LIMITS: TttLimits = byMode(CHARTER_LIMITS, FULL_LIMITS);\n"]}
|
package/dist/constants/chat.d.ts
CHANGED
|
@@ -14,4 +14,12 @@ export declare const MAX_CHAT_MESSAGE_LENGTH = 4000;
|
|
|
14
14
|
export declare const MAX_GUILD_CHAT_CHANNEL_NAME_LENGTH = 50;
|
|
15
15
|
/** Guild chat channel description — same single-owner rule as the name. */
|
|
16
16
|
export declare const MAX_GUILD_CHAT_CHANNEL_DESCRIPTION_LENGTH = 150;
|
|
17
|
+
/** Total chat-attachment STORED-OUTPUT bytes allowed across all of one Work's chat
|
|
18
|
+
* channels. Mode-varied (charter 2 GiB / full 10 GiB; DJ ruling 2026-07-25). Counted
|
|
19
|
+
* against `allWorkProjects/{workProjectId}.chatAttachmentBytesUsed`. */
|
|
20
|
+
export declare const MAX_WORK_CHAT_ATTACHMENT_STORAGE_BYTES: number;
|
|
21
|
+
/** Total chat-attachment STORED-OUTPUT bytes allowed in one guild-invite thread (no Work
|
|
22
|
+
* behind it). 250 MiB in BOTH modes (DJ ruling 2026-07-25). Counted against
|
|
23
|
+
* `guildInviteConversations/{guildInviteId}.chatAttachmentBytesUsed`. */
|
|
24
|
+
export declare const MAX_INVITE_THREAD_CHAT_ATTACHMENT_STORAGE_BYTES: number;
|
|
17
25
|
//# sourceMappingURL=chat.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/constants/chat.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/constants/chat.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAE5C;4FAC4F;AAC5F,eAAO,MAAM,kCAAkC,KAAK,CAAC;AAErD,2EAA2E;AAC3E,eAAO,MAAM,yCAAyC,MAAM,CAAC;AAE7D;;yEAEyE;AACzE,eAAO,MAAM,sCAAsC,QACM,CAAC;AAE1D;;0EAE0E;AAC1E,eAAO,MAAM,+CAA+C,QACH,CAAC"}
|
package/dist/constants/chat.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ACTIVE_LIMITS } from './app-mode.js';
|
|
1
2
|
/**
|
|
2
3
|
* Maximum chat message length (characters) used by ttt-core's chat callable
|
|
3
4
|
* and system-message-action schemas for backend validation.
|
|
@@ -14,4 +15,12 @@ export const MAX_CHAT_MESSAGE_LENGTH = 4000;
|
|
|
14
15
|
export const MAX_GUILD_CHAT_CHANNEL_NAME_LENGTH = 50;
|
|
15
16
|
/** Guild chat channel description — same single-owner rule as the name. */
|
|
16
17
|
export const MAX_GUILD_CHAT_CHANNEL_DESCRIPTION_LENGTH = 150;
|
|
18
|
+
/** Total chat-attachment STORED-OUTPUT bytes allowed across all of one Work's chat
|
|
19
|
+
* channels. Mode-varied (charter 2 GiB / full 10 GiB; DJ ruling 2026-07-25). Counted
|
|
20
|
+
* against `allWorkProjects/{workProjectId}.chatAttachmentBytesUsed`. */
|
|
21
|
+
export const MAX_WORK_CHAT_ATTACHMENT_STORAGE_BYTES = ACTIVE_LIMITS.workProject.maxChatAttachmentStorageBytes;
|
|
22
|
+
/** Total chat-attachment STORED-OUTPUT bytes allowed in one guild-invite thread (no Work
|
|
23
|
+
* behind it). 250 MiB in BOTH modes (DJ ruling 2026-07-25). Counted against
|
|
24
|
+
* `guildInviteConversations/{guildInviteId}.chatAttachmentBytesUsed`. */
|
|
25
|
+
export const MAX_INVITE_THREAD_CHAT_ATTACHMENT_STORAGE_BYTES = ACTIVE_LIMITS.guildInvite.maxChatAttachmentStorageBytes;
|
|
17
26
|
//# sourceMappingURL=chat.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.js","sourceRoot":"","sources":["../../src/constants/chat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAC;AAE5C;4FAC4F;AAC5F,MAAM,CAAC,MAAM,kCAAkC,GAAG,EAAE,CAAC;AAErD,2EAA2E;AAC3E,MAAM,CAAC,MAAM,yCAAyC,GAAG,GAAG,CAAC","sourcesContent":["/**\n * Maximum chat message length (characters) used by ttt-core's chat callable\n * and system-message-action schemas for backend validation.\n *\n * Split ownership by design: chat-core owns its own UI/runtime default\n * (`MAX_CHAT_MESSAGE_LENGTH` in `chat-core/src/constants.ts`); ttt-core owns\n * the value used by callable wire validation. The values are intentionally\n * aligned at 4000; consumers wanting a different limit should override at\n * their own call site rather than expecting cross-package coordination.\n */\nexport const MAX_CHAT_MESSAGE_LENGTH = 4000;\n\n/** Guild chat channel name — one owner for the create/update callable schemas AND the\n * channel form (whose zod previously carried its own 50 while the backend allowed 100). */\nexport const MAX_GUILD_CHAT_CHANNEL_NAME_LENGTH = 50;\n\n/** Guild chat channel description — same single-owner rule as the name. */\nexport const MAX_GUILD_CHAT_CHANNEL_DESCRIPTION_LENGTH = 150;\n"]}
|
|
1
|
+
{"version":3,"file":"chat.js","sourceRoot":"","sources":["../../src/constants/chat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAC;AAE5C;4FAC4F;AAC5F,MAAM,CAAC,MAAM,kCAAkC,GAAG,EAAE,CAAC;AAErD,2EAA2E;AAC3E,MAAM,CAAC,MAAM,yCAAyC,GAAG,GAAG,CAAC;AAE7D;;yEAEyE;AACzE,MAAM,CAAC,MAAM,sCAAsC,GACjD,aAAa,CAAC,WAAW,CAAC,6BAA6B,CAAC;AAE1D;;0EAE0E;AAC1E,MAAM,CAAC,MAAM,+CAA+C,GAC1D,aAAa,CAAC,WAAW,CAAC,6BAA6B,CAAC","sourcesContent":["import { ACTIVE_LIMITS } from './app-mode.js';\n\n/**\n * Maximum chat message length (characters) used by ttt-core's chat callable\n * and system-message-action schemas for backend validation.\n *\n * Split ownership by design: chat-core owns its own UI/runtime default\n * (`MAX_CHAT_MESSAGE_LENGTH` in `chat-core/src/constants.ts`); ttt-core owns\n * the value used by callable wire validation. The values are intentionally\n * aligned at 4000; consumers wanting a different limit should override at\n * their own call site rather than expecting cross-package coordination.\n */\nexport const MAX_CHAT_MESSAGE_LENGTH = 4000;\n\n/** Guild chat channel name — one owner for the create/update callable schemas AND the\n * channel form (whose zod previously carried its own 50 while the backend allowed 100). */\nexport const MAX_GUILD_CHAT_CHANNEL_NAME_LENGTH = 50;\n\n/** Guild chat channel description — same single-owner rule as the name. */\nexport const MAX_GUILD_CHAT_CHANNEL_DESCRIPTION_LENGTH = 150;\n\n/** Total chat-attachment STORED-OUTPUT bytes allowed across all of one Work's chat\n * channels. Mode-varied (charter 2 GiB / full 10 GiB; DJ ruling 2026-07-25). Counted\n * against `allWorkProjects/{workProjectId}.chatAttachmentBytesUsed`. */\nexport const MAX_WORK_CHAT_ATTACHMENT_STORAGE_BYTES =\n ACTIVE_LIMITS.workProject.maxChatAttachmentStorageBytes;\n\n/** Total chat-attachment STORED-OUTPUT bytes allowed in one guild-invite thread (no Work\n * behind it). 250 MiB in BOTH modes (DJ ruling 2026-07-25). Counted against\n * `guildInviteConversations/{guildInviteId}.chatAttachmentBytesUsed`. */\nexport const MAX_INVITE_THREAD_CHAT_ATTACHMENT_STORAGE_BYTES =\n ACTIVE_LIMITS.guildInvite.maxChatAttachmentStorageBytes;\n"]}
|
|
@@ -75,6 +75,7 @@ export declare const GuildInviteConversationSchema: z.ZodObject<{
|
|
|
75
75
|
recipientConfirmed: z.ZodBoolean;
|
|
76
76
|
lastMessage: z.ZodOptional<z.ZodString>;
|
|
77
77
|
lastMessageAt: z.ZodOptional<z.ZodString>;
|
|
78
|
+
chatAttachmentBytesUsed: z.ZodOptional<z.ZodNumber>;
|
|
78
79
|
}, z.core.$strip>;
|
|
79
80
|
export type GuildInviteConversation = z.infer<typeof GuildInviteConversationSchema>;
|
|
80
81
|
export declare const AdminDispatchContextRefSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messaging.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/messaging.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;iBAwBjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAQtE,eAAO,MAAM,6BAA6B
|
|
1
|
+
{"version":3,"file":"messaging.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/messaging.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;iBAwBjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAQtE,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuCxC,CAAC;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAMpF,eAAO,MAAM,6BAA6B;;;;;;;;;;2BASxC,CAAC;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAEpF,eAAO,MAAM,4BAA4B;;;EAAkC,CAAC;AAC5E,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAElF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAsB9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAShE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAqB9B,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC"}
|
|
@@ -68,6 +68,15 @@ export const GuildInviteConversationSchema = z.object({
|
|
|
68
68
|
recipientConfirmed: z.boolean(),
|
|
69
69
|
lastMessage: z.string().optional(),
|
|
70
70
|
lastMessageAt: z.string().optional(),
|
|
71
|
+
// Running total of chat-attachment STORED-OUTPUT bytes in THIS invite thread, checked
|
|
72
|
+
// against MAX_INVITE_THREAD_CHAT_ATTACHMENT_STORAGE_BYTES (250 MiB in both modes; DJ
|
|
73
|
+
// ruling 2026-07-25). An invite thread has no Work behind it, so it carries its own
|
|
74
|
+
// container quota rather than charging the Work's. Absent ⇒ 0 — never initialized on
|
|
75
|
+
// create and needs no backfill; the first finalize writes it via an increment, so every
|
|
76
|
+
// pre-existing invite reads as 0 used. Maintained at asset finalize (+ stored bytes) and
|
|
77
|
+
// retire (− stored bytes), with a pessimistic pre-check at startUpload.
|
|
78
|
+
// Backend-only-writable.
|
|
79
|
+
chatAttachmentBytesUsed: z.number().optional(),
|
|
71
80
|
});
|
|
72
81
|
// Typed context ref carried by a dispatch thread born from a review send-back, a
|
|
73
82
|
// moderation placeholder, or a published change request — lets the admin queue card
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messaging.js","sourceRoot":"","sources":["../../src/doc-schemas/messaging.ts"],"names":[],"mappings":"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","sourcesContent":["// Messaging parent-thread Firestore document SCHEMAS — guildChatChannels, the\n// guildInviteConversations shell, and pendingAdminDispatches. Per-message body shapes\n// live in @ttt-productions/chat-core (ChatMessageV1); ttt-core owns the thread docs.\n// Types inferred via z.infer.\n\nimport { z } from 'zod';\nimport { ReplyToSchema, ChatAttachmentSchema } from '@ttt-productions/chat-schemas';\nimport { InviteSourceSchema } from '../schemas/work-project-management.js';\nimport { guildInviteConversationStatusSchema } from '../schemas/atoms.js';\n\nconst userRefSchema = z.object({ uid: z.string() });\n\nexport const GuildChatChannelSchema = z.object({\n guildChatChannelId: z.string(),\n workProjectId: z.string(),\n channelName: z.string(),\n description: z.string().optional(),\n requiredGuildStandings: z.array(z.string()),\n allowedUserIds: z.array(z.string()),\n createdAt: z.number(),\n // NOTE: createdBy here is a flat uid string (unlike the `{ uid }` object form on\n // most other docs). Preserved as-is; flagged in the schema-registry recon.\n createdBy: z.string(),\n lastMessageAt: z.string().optional(),\n lastMessage: z.string().optional(),\n messageCount: z.number(),\n isArchived: z.boolean(),\n // Delete/tombstone marker (ttt-prod docs/design/chat-realtime-system.md \"Channel lifecycle semantics\").\n // Independent of `isArchived`: archive = visible-under-a-toggle, delete = gone from every user's\n // UI with grants revoked and sends rejected DO-side; storage is RETAINED (never a physical purge).\n // Optional, absent ⇒ false, so existing/seeded channels need no backfill. Backend-only-writable.\n isDeleted: z.boolean().optional(),\n // Monotonic config version for the chat-realtime sync layer (Contract B). Bumped by\n // each channel create / edit / archive / delete in the authoritative txn; the\n // `config` chatSyncEvents + channel-scoped fanout key on it. Absent ⇒ 0.\n configVersion: z.number().optional(),\n});\nexport type GuildChatChannel = z.infer<typeof GuildChatChannelSchema>;\n\n// The guildInviteConversations/{guildInviteId} doc as actually written by inviteUserToGuild\n// (and mutated by the accept/decline/finalize/cancel callables). This is the single source of\n// truth — the former duplicate `GuildInviteSchema` in ./work-project.ts was a stale, narrower\n// shape that the callable bypassed with an `as unknown as` cast. The inviter is `createdBy`\n// (== `sender`); there is no separate `workSteward`/`workProjectTitle` field (the title lives in\n// `workProject.workingTitle`).\nexport const GuildInviteConversationSchema = z.object({\n guildInviteId: z.string(),\n workProjectId: z.string(),\n relatedUserIds: z.array(z.string()),\n // Title/description are NOT snapshotted (Display Identity Invariant — resolve at render\n // from publicWorkProjects by id). `type` (Tales/Tunes/Television) is an immutable\n // classification, not display text, and IS consumed by an invites-list type filter\n // (guild-invites-section.tsx), so it stays. Triggers read only `workProjectId`.\n workProject: z.object({\n workProjectId: z.string(),\n type: z.string(),\n }),\n createdBy: userRefSchema,\n sender: userRefSchema,\n recipient: userRefSchema,\n stakeSharesOffered: z.number(),\n source: InviteSourceSchema,\n // State machine: pending → accepted (transient, trigger-consumed) → finalized (terminal\n // success), or pending → declined / cancelled (terminal failure). No 'error' state is ever\n // written (dead state removed 2026-07-03). See ttt-prod\n // docs/design/work-guild-membership-and-stake.md for the invite lifecycle.\n status: guildInviteConversationStatusSchema,\n createdAt: z.number(),\n updatedAt: z.number(),\n lastUpdatedAt: z.number(),\n finalizedAt: z.number().optional(),\n senderConfirmed: z.boolean(),\n recipientConfirmed: z.boolean(),\n lastMessage: z.string().optional(),\n lastMessageAt: z.string().optional(),\n});\nexport type GuildInviteConversation = z.infer<typeof GuildInviteConversationSchema>;\n\n// Typed context ref carried by a dispatch thread born from a review send-back, a\n// moderation placeholder, or a published change request — lets the admin queue card\n// say what the thread is about without parsing the subject line. Extensible union;\n// server-validated against the thread's party (never trusted raw from the client).\nexport const AdminDispatchContextRefSchema = z.discriminatedUnion('kind', [\n z.object({ kind: z.literal('thresholdItem'), thresholdItemId: z.string() }),\n z.object({\n kind: z.literal('hallContent'),\n hallItemId: z.string(),\n // null ⇒ the hall parent DETAIL; set ⇒ a chapter/track/episode sub-item.\n subItemId: z.string().nullable(),\n }),\n z.object({ kind: z.literal('hallContentChangeRequest'), changeRequestId: z.string() }),\n]);\nexport type AdminDispatchContextRef = z.infer<typeof AdminDispatchContextRefSchema>;\n\nexport const AdminDispatchPartyKindSchema = z.enum(['user', 'workProject']);\nexport type AdminDispatchPartyKind = z.infer<typeof AdminDispatchPartyKindSchema>;\n\nexport const AdminDispatchSchema = z.object({\n adminDispatchId: z.string(),\n // Party-generic dispatch: the platform corresponds with a PARTY — a user or a\n // workProject. Absent ⇒ 'user' (every pre-generalization thread). For 'user'\n // threads `userId` is the thread owner (the sole member-side authority). For\n // 'workProject' threads `workProjectId` is set, read/reply authority is ACTIVE\n // GUILDMATE standing evaluated server-side (never a stored member list), and\n // `userId` holds the INITIATING member's uid for attribution only — it is never\n // a work-thread authority.\n partyKind: AdminDispatchPartyKindSchema.optional(),\n workProjectId: z.string().optional(),\n contextRef: AdminDispatchContextRefSchema.optional(),\n userId: z.string(),\n initiatorUserId: z.string(),\n initiatedBy: z.enum(['user', 'admin']),\n subject: z.string(),\n status: z.enum(['open', 'user_reply', 'admin_reply', 'closed_resolved', 'closed_unresolved']),\n createdAt: z.number(),\n lastUpdatedAt: z.number(),\n readByAdmin: z.boolean(),\n readByUser: z.boolean(),\n closedBy: z.string().optional(),\n});\nexport type AdminDispatch = z.infer<typeof AdminDispatchSchema>;\n\n// Per-message body for admin-support `conversationMessages` — the ONE chat surface still\n// transported through Firestore (guild channel + invite messages are realtime-only, served\n// by the chat Worker Durable Object). Written by runSendGuildChatMessage (senderId/text/\n// createdAt + optional replyTo/attachment); the admin-dispatch INITIAL message\n// (runStartAdminSupportThread) additionally stores `messageId`. This is the STORED shape — a relaxed\n// @ttt-productions/chat-core ChatMessageV1: `messageId` is the doc id (only sometimes persisted) and\n// `threadId` is not stored. Reuses the chat-schemas Zod shapes for attachment + replyTo.\nexport const ChatMessageV1Schema = z.object({\n senderId: z.string(),\n text: z.string(),\n createdAt: z.number(),\n messageId: z.string().optional(),\n threadId: z.string().optional(),\n type: z.string().optional(),\n // Rides on the realtime invite-thread envelope (chat Worker invite Durable Object);\n // guild-invite messages are realtime-only — there is no Firestore inviteMessages\n // subcollection. Optional so the same body schema still fits the guildChat /\n // admin-dispatch messages that don't carry it.\n guildInviteId: z.string().optional(),\n attachment: ChatAttachmentSchema.optional(),\n replyTo: ReplyToSchema.optional(),\n isSystemMessage: z.boolean().optional(),\n meta: z.record(z.string(), z.unknown()).optional(),\n // Moderation tombstone flag — the single-doc `hidden` flip written by the admin\n // moderateReportedContent pipeline (the admin-work-message itemType). Backend-only\n // writable (conversationMessages is callable-only in rules); absent ⇒ visible.\n // Thread views render a hidden message as a moderation tombstone.\n hidden: z.boolean().optional(),\n});\nexport type ChatMessageV1Doc = z.infer<typeof ChatMessageV1Schema>;\n"]}
|
|
1
|
+
{"version":3,"file":"messaging.js","sourceRoot":"","sources":["../../src/doc-schemas/messaging.ts"],"names":[],"mappings":"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","sourcesContent":["// Messaging parent-thread Firestore document SCHEMAS — guildChatChannels, the\n// guildInviteConversations shell, and pendingAdminDispatches. Per-message body shapes\n// live in @ttt-productions/chat-core (ChatMessageV1); ttt-core owns the thread docs.\n// Types inferred via z.infer.\n\nimport { z } from 'zod';\nimport { ReplyToSchema, ChatAttachmentSchema } from '@ttt-productions/chat-schemas';\nimport { InviteSourceSchema } from '../schemas/work-project-management.js';\nimport { guildInviteConversationStatusSchema } from '../schemas/atoms.js';\n\nconst userRefSchema = z.object({ uid: z.string() });\n\nexport const GuildChatChannelSchema = z.object({\n guildChatChannelId: z.string(),\n workProjectId: z.string(),\n channelName: z.string(),\n description: z.string().optional(),\n requiredGuildStandings: z.array(z.string()),\n allowedUserIds: z.array(z.string()),\n createdAt: z.number(),\n // NOTE: createdBy here is a flat uid string (unlike the `{ uid }` object form on\n // most other docs). Preserved as-is; flagged in the schema-registry recon.\n createdBy: z.string(),\n lastMessageAt: z.string().optional(),\n lastMessage: z.string().optional(),\n messageCount: z.number(),\n isArchived: z.boolean(),\n // Delete/tombstone marker (ttt-prod docs/design/chat-realtime-system.md \"Channel lifecycle semantics\").\n // Independent of `isArchived`: archive = visible-under-a-toggle, delete = gone from every user's\n // UI with grants revoked and sends rejected DO-side; storage is RETAINED (never a physical purge).\n // Optional, absent ⇒ false, so existing/seeded channels need no backfill. Backend-only-writable.\n isDeleted: z.boolean().optional(),\n // Monotonic config version for the chat-realtime sync layer (Contract B). Bumped by\n // each channel create / edit / archive / delete in the authoritative txn; the\n // `config` chatSyncEvents + channel-scoped fanout key on it. Absent ⇒ 0.\n configVersion: z.number().optional(),\n});\nexport type GuildChatChannel = z.infer<typeof GuildChatChannelSchema>;\n\n// The guildInviteConversations/{guildInviteId} doc as actually written by inviteUserToGuild\n// (and mutated by the accept/decline/finalize/cancel callables). This is the single source of\n// truth — the former duplicate `GuildInviteSchema` in ./work-project.ts was a stale, narrower\n// shape that the callable bypassed with an `as unknown as` cast. The inviter is `createdBy`\n// (== `sender`); there is no separate `workSteward`/`workProjectTitle` field (the title lives in\n// `workProject.workingTitle`).\nexport const GuildInviteConversationSchema = z.object({\n guildInviteId: z.string(),\n workProjectId: z.string(),\n relatedUserIds: z.array(z.string()),\n // Title/description are NOT snapshotted (Display Identity Invariant — resolve at render\n // from publicWorkProjects by id). `type` (Tales/Tunes/Television) is an immutable\n // classification, not display text, and IS consumed by an invites-list type filter\n // (guild-invites-section.tsx), so it stays. Triggers read only `workProjectId`.\n workProject: z.object({\n workProjectId: z.string(),\n type: z.string(),\n }),\n createdBy: userRefSchema,\n sender: userRefSchema,\n recipient: userRefSchema,\n stakeSharesOffered: z.number(),\n source: InviteSourceSchema,\n // State machine: pending → accepted (transient, trigger-consumed) → finalized (terminal\n // success), or pending → declined / cancelled (terminal failure). No 'error' state is ever\n // written (dead state removed 2026-07-03). See ttt-prod\n // docs/design/work-guild-membership-and-stake.md for the invite lifecycle.\n status: guildInviteConversationStatusSchema,\n createdAt: z.number(),\n updatedAt: z.number(),\n lastUpdatedAt: z.number(),\n finalizedAt: z.number().optional(),\n senderConfirmed: z.boolean(),\n recipientConfirmed: z.boolean(),\n lastMessage: z.string().optional(),\n lastMessageAt: z.string().optional(),\n // Running total of chat-attachment STORED-OUTPUT bytes in THIS invite thread, checked\n // against MAX_INVITE_THREAD_CHAT_ATTACHMENT_STORAGE_BYTES (250 MiB in both modes; DJ\n // ruling 2026-07-25). An invite thread has no Work behind it, so it carries its own\n // container quota rather than charging the Work's. Absent ⇒ 0 — never initialized on\n // create and needs no backfill; the first finalize writes it via an increment, so every\n // pre-existing invite reads as 0 used. Maintained at asset finalize (+ stored bytes) and\n // retire (− stored bytes), with a pessimistic pre-check at startUpload.\n // Backend-only-writable.\n chatAttachmentBytesUsed: z.number().optional(),\n});\nexport type GuildInviteConversation = z.infer<typeof GuildInviteConversationSchema>;\n\n// Typed context ref carried by a dispatch thread born from a review send-back, a\n// moderation placeholder, or a published change request — lets the admin queue card\n// say what the thread is about without parsing the subject line. Extensible union;\n// server-validated against the thread's party (never trusted raw from the client).\nexport const AdminDispatchContextRefSchema = z.discriminatedUnion('kind', [\n z.object({ kind: z.literal('thresholdItem'), thresholdItemId: z.string() }),\n z.object({\n kind: z.literal('hallContent'),\n hallItemId: z.string(),\n // null ⇒ the hall parent DETAIL; set ⇒ a chapter/track/episode sub-item.\n subItemId: z.string().nullable(),\n }),\n z.object({ kind: z.literal('hallContentChangeRequest'), changeRequestId: z.string() }),\n]);\nexport type AdminDispatchContextRef = z.infer<typeof AdminDispatchContextRefSchema>;\n\nexport const AdminDispatchPartyKindSchema = z.enum(['user', 'workProject']);\nexport type AdminDispatchPartyKind = z.infer<typeof AdminDispatchPartyKindSchema>;\n\nexport const AdminDispatchSchema = z.object({\n adminDispatchId: z.string(),\n // Party-generic dispatch: the platform corresponds with a PARTY — a user or a\n // workProject. Absent ⇒ 'user' (every pre-generalization thread). For 'user'\n // threads `userId` is the thread owner (the sole member-side authority). For\n // 'workProject' threads `workProjectId` is set, read/reply authority is ACTIVE\n // GUILDMATE standing evaluated server-side (never a stored member list), and\n // `userId` holds the INITIATING member's uid for attribution only — it is never\n // a work-thread authority.\n partyKind: AdminDispatchPartyKindSchema.optional(),\n workProjectId: z.string().optional(),\n contextRef: AdminDispatchContextRefSchema.optional(),\n userId: z.string(),\n initiatorUserId: z.string(),\n initiatedBy: z.enum(['user', 'admin']),\n subject: z.string(),\n status: z.enum(['open', 'user_reply', 'admin_reply', 'closed_resolved', 'closed_unresolved']),\n createdAt: z.number(),\n lastUpdatedAt: z.number(),\n readByAdmin: z.boolean(),\n readByUser: z.boolean(),\n closedBy: z.string().optional(),\n});\nexport type AdminDispatch = z.infer<typeof AdminDispatchSchema>;\n\n// Per-message body for admin-support `conversationMessages` — the ONE chat surface still\n// transported through Firestore (guild channel + invite messages are realtime-only, served\n// by the chat Worker Durable Object). Written by runSendGuildChatMessage (senderId/text/\n// createdAt + optional replyTo/attachment); the admin-dispatch INITIAL message\n// (runStartAdminSupportThread) additionally stores `messageId`. This is the STORED shape — a relaxed\n// @ttt-productions/chat-core ChatMessageV1: `messageId` is the doc id (only sometimes persisted) and\n// `threadId` is not stored. Reuses the chat-schemas Zod shapes for attachment + replyTo.\nexport const ChatMessageV1Schema = z.object({\n senderId: z.string(),\n text: z.string(),\n createdAt: z.number(),\n messageId: z.string().optional(),\n threadId: z.string().optional(),\n type: z.string().optional(),\n // Rides on the realtime invite-thread envelope (chat Worker invite Durable Object);\n // guild-invite messages are realtime-only — there is no Firestore inviteMessages\n // subcollection. Optional so the same body schema still fits the guildChat /\n // admin-dispatch messages that don't carry it.\n guildInviteId: z.string().optional(),\n attachment: ChatAttachmentSchema.optional(),\n replyTo: ReplyToSchema.optional(),\n isSystemMessage: z.boolean().optional(),\n meta: z.record(z.string(), z.unknown()).optional(),\n // Moderation tombstone flag — the single-doc `hidden` flip written by the admin\n // moderateReportedContent pipeline (the admin-work-message itemType). Backend-only\n // writable (conversationMessages is callable-only in rules); absent ⇒ visible.\n // Thread views render a hidden message as a moderation tombstone.\n hidden: z.boolean().optional(),\n});\nexport type ChatMessageV1Doc = z.infer<typeof ChatMessageV1Schema>;\n"]}
|
|
@@ -354,6 +354,7 @@ export declare const COLLECTION_SCHEMAS: {
|
|
|
354
354
|
amount: z.ZodNumber;
|
|
355
355
|
createdAt: z.ZodNumber;
|
|
356
356
|
}, z.core.$strip>>>;
|
|
357
|
+
chatAttachmentBytesUsed: z.ZodOptional<z.ZodNumber>;
|
|
357
358
|
moderationRetitleRequired: z.ZodOptional<z.ZodBoolean>;
|
|
358
359
|
moderationRetitleReason: z.ZodOptional<z.ZodString>;
|
|
359
360
|
moderationClearedFields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
@@ -639,6 +640,7 @@ export declare const COLLECTION_SCHEMAS: {
|
|
|
639
640
|
recipientConfirmed: z.ZodBoolean;
|
|
640
641
|
lastMessage: z.ZodOptional<z.ZodString>;
|
|
641
642
|
lastMessageAt: z.ZodOptional<z.ZodString>;
|
|
643
|
+
chatAttachmentBytesUsed: z.ZodOptional<z.ZodNumber>;
|
|
642
644
|
}, z.core.$strip>;
|
|
643
645
|
readonly 'squareStreetzFeed/activePosts/socialPosts/{postId}': z.ZodObject<{
|
|
644
646
|
postId: z.ZodString;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/registry.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAgM7B,eAAO,MAAM,kBAAkB
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/registry.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAgM7B,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyNkB,CAAC;AAElD,MAAM,MAAM,wBAAwB,GAAG,MAAM,OAAO,kBAAkB,CAAC;AAEvE;;;;;;;;;GASG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;CAmBiC,CAAC;AAEvE;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,MAAM,EAOvC,CAAC"}
|
|
@@ -73,6 +73,7 @@ export declare const FullWorkProjectSchema: z.ZodObject<{
|
|
|
73
73
|
amount: z.ZodNumber;
|
|
74
74
|
createdAt: z.ZodNumber;
|
|
75
75
|
}, z.core.$strip>>>;
|
|
76
|
+
chatAttachmentBytesUsed: z.ZodOptional<z.ZodNumber>;
|
|
76
77
|
moderationRetitleRequired: z.ZodOptional<z.ZodBoolean>;
|
|
77
78
|
moderationRetitleReason: z.ZodOptional<z.ZodString>;
|
|
78
79
|
moderationClearedFields: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"work-project.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/work-project.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,eAAO,MAAM,qBAAqB;;;EAAiC,CAAC;AACpE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;iBAyC9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,yBAAyB;;;;;;;;iBAKpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E,eAAO,MAAM,wBAAwB;;;kBAGpC,CAAC;AACF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,eAAO,MAAM,qBAAqB
|
|
1
|
+
{"version":3,"file":"work-project.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/work-project.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,eAAO,MAAM,qBAAqB;;;EAAiC,CAAC;AACpE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;iBAyC9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,yBAAyB;;;;;;;;iBAKpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E,eAAO,MAAM,wBAAwB;;;kBAGpC,CAAC;AACF,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAsChC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAGpE,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgBlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAWxE,4EAA4E;AAC5E,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;iBAoB/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,mGAAmG;AACnG,eAAO,MAAM,cAAc;;;;;;;;;;;;iBAUzB,CAAC;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAGtD,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoC1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC"}
|
|
@@ -76,6 +76,14 @@ export const FullWorkProjectSchema = z.object({
|
|
|
76
76
|
workRealmId: z.string(),
|
|
77
77
|
realmCanonStatus: z.enum(['canon', 'nonCanon']),
|
|
78
78
|
pendingStakeShares: PendingStakeSharesSchema.optional(),
|
|
79
|
+
// Running total of chat-attachment STORED-OUTPUT bytes across all of this Work's chat
|
|
80
|
+
// channels, checked against MAX_WORK_CHAT_ATTACHMENT_STORAGE_BYTES (charter 2 GiB /
|
|
81
|
+
// full 10 GiB; DJ ruling 2026-07-25). Absent ⇒ 0 — the field is never initialized on
|
|
82
|
+
// create and needs no backfill; the first finalize writes it via an increment, so
|
|
83
|
+
// every pre-existing Work reads as 0 used. Maintained at asset finalize (+ stored
|
|
84
|
+
// bytes) and retire (− stored bytes), with a pessimistic pre-check at startUpload.
|
|
85
|
+
// Backend-only-writable.
|
|
86
|
+
chatAttachmentBytesUsed: z.number().optional(),
|
|
79
87
|
// Moderation "require retitle" remedy (work/realm report path). When an admin
|
|
80
88
|
// upholds a report on an abusive public title/description, they may replace the
|
|
81
89
|
// text with a generic placeholder and set this flag; the steward is prompted to
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"work-project.js","sourceRoot":"","sources":["../../src/doc-schemas/work-project.ts"],"names":[],"mappings":"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","sourcesContent":["// WorkProject / Realm / Guild Firestore document SCHEMAS — single source of truth.\n// Covers allWorkProjects/{workProjectId}, its guildmateUsers/publicGuildmateUsers/\n// workAssets subcollections, publicWorkProjects/{workProjectId}, workRealms/{workRealmId},\n// and the guildInviteConversations invite shell. Types are inferred via z.infer so a\n// document's shape and its TypeScript type cannot drift apart.\n//\n// Terminology: the current-owner field is `workStewardUid` (locked rename from the old\n// `ownerUid`; see ttt-prod docs/design/terminology-naming-convention.md — Steward row). The original\n// creator is `foundingArtisanUid` (locked rename from the old `createdByUid`; Founding Artisan).\n\nimport { z } from 'zod';\nimport { HALL_WING_TYPE_KEYS, WORK_PROJECT_TYPE_KEYS } from '../types/content.js';\nimport { isGuildStandingId, type GuildStandingId } from '../permissions/index.js';\n\nconst guildStandingIdSchema = z.custom<GuildStandingId>(isGuildStandingId);\nconst userRefSchema = z.object({ uid: z.string() });\n\nexport const GuildmateStatusSchema = z.enum(['active', 'departed']);\nexport type GuildmateStatus = z.infer<typeof GuildmateStatusSchema>;\n\nexport const GuildmateUserSchema = z.object({\n uid: z.string(),\n guildStandings: z.array(guildStandingIdSchema),\n tradeProfessions: z.array(z.string()),\n stakeShareCount: z.number(),\n joinedAt: z.number(),\n status: GuildmateStatusSchema,\n /**\n * Holder kind for this stake entry. Absent/`'user'` = a real guildmate person.\n * `'foundingWork'` = the realm founding-Work holder (keyed by the founding\n * workProjectId, NOT a user uid).\n */\n holderType: z.enum(['user', 'foundingWork']).optional(),\n /**\n * Per-(user, workProject) monotonic INPUT-trigger version for the chat\n * channel-auth projection (chat-edge-rebuild Contract B / P3). Absent ⇒ 0.\n * Bumped atomically in the authoritative mutation on member create/reactivate,\n * departure/removal, standing change, AND trade-profession change; the\n * `workChannelsForUser` fanout keys on the POST-increment value. It NEVER\n * increments or replaces the per-pair OUTPUT `channelAuthVersion`.\n */\n guildAuthInputVersion: z.number().optional(),\n /**\n * N3 data-deletion / account-end forfeiture tombstone. Set together with\n * `status: 'departed'` when a member leaves involuntarily-of-record: their\n * stake shares STAY in the immutable 1000-split (never removed) but are\n * forfeited — the future payout engine routes a tombstone's slice to the\n * community fund and excludes it from active distribution. `departedReason`\n * distinguishes the cause; `'bannedForCause'` is reserved for the future\n * ban-forfeiture path (included now so it needs no second package publish).\n *\n * `'selfLeave'` is DIFFERENT share semantics: a PRE-PUBLISH voluntary guild\n * exit (leaveWorkProject). There the 1000-split is still fluid, so the\n * member's `stakeShareCount` is ZEROED and returned to the pool for the\n * steward to re-allocate — NOT retained as a community-fund tombstone. A\n * self-leave is impossible once `status: 'published'` (the stake-share freeze\n * blocks it), so the tombstone and the pool-return dispositions never overlap\n * in a single Work's lifecycle.\n */\n departedReason: z.enum(['voluntaryDeletion', 'bannedForCause', 'selfLeave']).optional(),\n departedAt: z.number().optional(),\n});\nexport type GuildmateUser = z.infer<typeof GuildmateUserSchema>;\n\nexport const PublicGuildmateUserSchema = z.object({\n uid: z.string(),\n tradeProfessions: z.array(z.string()),\n joinedAt: z.number(),\n status: GuildmateStatusSchema,\n});\nexport type PublicGuildmateUser = z.infer<typeof PublicGuildmateUserSchema>;\n\nexport const PendingStakeSharesSchema = z.record(\n z.string(),\n z.object({ amount: z.number(), createdAt: z.number() }),\n);\nexport type PendingStakeShares = z.infer<typeof PendingStakeSharesSchema>;\n\nexport const FullWorkProjectSchema = z.object({\n workProjectId: z.string(),\n createdOn: z.number(),\n type: z.string(),\n workingDescription: z.string(),\n workingTitle: z.string(),\n hallWingType: z.enum(HALL_WING_TYPE_KEYS),\n createdBy: userRefSchema,\n status: z.enum(['open', 'pendingVerification', 'published', 'rejected']),\n guildmateUserIds: z.record(z.string(), z.boolean()).optional(),\n invitedUserIds: z.record(z.string(), z.boolean()).optional(),\n workRealmId: z.string(),\n realmCanonStatus: z.enum(['canon', 'nonCanon']),\n pendingStakeShares: PendingStakeSharesSchema.optional(),\n // Moderation \"require retitle\" remedy (work/realm report path). When an admin\n // upholds a report on an abusive public title/description, they may replace the\n // text with a generic placeholder and set this flag; the steward is prompted to\n // re-enter compliant text the next time they open the work (unpublished = direct\n // self-edit clears it; published = via the post-launch change-request flow).\n // Distinct from the `publicWorkHidden` hide (DMCA/copyright) — this keeps the\n // work visible under the placeholder. Backend-only-writable.\n moderationRetitleRequired: z.boolean().optional(),\n moderationRetitleReason: z.string().optional(),\n // Per-field extension of the retitle remedy (uniform with the Tale/Tune/Television content family):\n // which text fields ('title', 'description', …) an admin cleared to a placeholder — \"all or any\",\n // instead of the always-both retitle — and the operator's reason surfaced on the steward's edit\n // surface. Empty/absent when nothing was cleared. Backend-only-writable.\n moderationClearedFields: z.array(z.string()).optional(),\n moderationClearedReason: z.string().optional(),\n moderatedAt: z.number().optional(),\n});\nexport type FullWorkProject = z.infer<typeof FullWorkProjectSchema>;\n\n// Top-level safe signed-in-user Work shell / search projection. Server/callable-written only.\nexport const PublicWorkProjectSchema = z.object({\n workProjectId: z.string(),\n publicWorkStatus: z.enum(['draft', 'released']),\n publicWorkHidden: z.boolean(),\n workRealmId: z.string(),\n realmCanonStatus: z.enum(['canon', 'nonCanon']),\n type: z.enum(WORK_PROJECT_TYPE_KEYS),\n hallWingType: z.enum(HALL_WING_TYPE_KEYS),\n workingTitle: z.string(),\n workingTitle_lowercase: z.string(),\n workingDescription: z.string(),\n coverAssetId: z.string().optional(),\n workStewardUid: z.string(),\n foundingArtisanUid: z.string(),\n createdOn: z.number(),\n updatedOn: z.number(),\n});\nexport type PublicWorkProject = z.infer<typeof PublicWorkProjectSchema>;\n\n// ===========================================================================\n// Work-project FILE FOLDER system (S7) — supersedes the flat workAssets model.\n// A default folder (every active guildmate views/uploads) + custom folders whose\n// audience is controlled by TRADE PROFESSIONS, while file-system ADMINISTRATION is\n// controlled by guild standings (StewardOwner / WorkProjectManager / WorkAssetAdmin).\n// See ttt-prod docs/design/work-project-file-folders.md. Realm sharing of a file is the\n// `realmFileCanonStatus` seam on the file's mediaAssets doc (media-assets.ts).\n// ===========================================================================\n\n/** `allWorkProjects/{workProjectId}/workFileFolders/{workFileFolderId}`. */\nexport const WorkFileFolderSchema = z.object({\n workFileFolderId: z.string(),\n workProjectId: z.string(),\n name: z.string(),\n // The auto-created \"All Guildmates\" folder (view/upload open to every active\n // guildmate; delete/manage needs file-admin). Exactly one per work project.\n isDefault: z.boolean(),\n // Custom-folder access — trade-profession ids (TRADE_PROFESSION_OPTIONS). Empty\n // on the default folder; file admins always see/manage every folder regardless.\n canViewTradeProfessions: z.array(z.string()),\n canUploadTradeProfessions: z.array(z.string()),\n canDeleteTradeProfessions: z.array(z.string()),\n fileCount: z.number(),\n /** Sum of this folder's files' `sizeBytes`. Maintained alongside `fileCount`\n * (increment on upload, decrement on delete); the project-wide storage usage +\n * `MAX_WORK_FILE_STORAGE_BYTES` cap are computed by summing this across folders. */\n storageBytes: z.number(),\n createdBy: userRefSchema,\n createdAt: z.number(),\n updatedAt: z.number(),\n});\nexport type WorkFileFolder = z.infer<typeof WorkFileFolderSchema>;\n\n/** `allWorkProjects/{workProjectId}/workFileFolders/{workFileFolderId}/workFiles/{workFileId}`. */\nexport const WorkFileSchema = z.object({\n workFileId: z.string(),\n workProjectId: z.string(),\n workFileFolderId: z.string(),\n name: z.string(),\n mediaAssetId: z.string(),\n contentType: z.string(),\n sizeBytes: z.number(),\n uploadedBy: userRefSchema,\n createdAt: z.number(),\n});\nexport type WorkFile = z.infer<typeof WorkFileSchema>;\n\n// Realm source of truth and Realm search/tag surface. Server/callable-written only.\nexport const WorkRealmSchema = z.object({\n workRealmId: z.string(),\n realmType: z.enum(['public', 'standalone']),\n realmStatus: z.enum(['draft', 'released']),\n realmHidden: z.boolean(),\n workingTitle: z.string(),\n workingTitle_lowercase: z.string(),\n workingDescription: z.string(),\n // Square realm cover art (the 'realm-cover' upload origin; processor-written).\n // Optional while the realm is a DRAFT; releasing the realm REQUIRES it — the\n // realm release callable enforces presence (never required at founding, so a\n // work creation is never blocked on realm art).\n realmCoverAssetId: z.string().optional(),\n workStewardUid: z.string(),\n foundingArtisanUid: z.string(),\n foundingWorkProjectId: z.string(),\n createdOn: z.number(),\n updatedOn: z.number(),\n // MONOTONIC publish lock (R1 ruling, 2026-07-12): set true by the hall publish\n // core the first time any work in this realm publishes, and never unset — even\n // if that work later unpublishes (the realm name already went public). While\n // absent/false, realm info is direct-edit; once true, realm text changes route\n // exclusively through the change-request pipeline (surface 'workRealm').\n // Backend-only-writable.\n hasEverPublishedWork: z.boolean().optional(),\n // Moderation \"require retitle\" remedy (see FullWorkProject above) — admin\n // replaces an abusive realm title/description with a placeholder + sets this so\n // the steward must re-enter compliant text. Distinct from `realmHidden` (the\n // DMCA/copyright takedown). Backend-only-writable.\n moderationRetitleRequired: z.boolean().optional(),\n moderationRetitleReason: z.string().optional(),\n // Per-field extension of the retitle remedy (see FullWorkProject) — which realm text fields an\n // admin cleared to a placeholder (\"all or any\"), plus the operator's reason. Backend-only-writable.\n moderationClearedFields: z.array(z.string()).optional(),\n moderationClearedReason: z.string().optional(),\n moderatedAt: z.number().optional(),\n});\nexport type WorkRealm = z.infer<typeof WorkRealmSchema>;\n"]}
|
|
1
|
+
{"version":3,"file":"work-project.js","sourceRoot":"","sources":["../../src/doc-schemas/work-project.ts"],"names":[],"mappings":"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","sourcesContent":["// WorkProject / Realm / Guild Firestore document SCHEMAS — single source of truth.\n// Covers allWorkProjects/{workProjectId}, its guildmateUsers/publicGuildmateUsers/\n// workAssets subcollections, publicWorkProjects/{workProjectId}, workRealms/{workRealmId},\n// and the guildInviteConversations invite shell. Types are inferred via z.infer so a\n// document's shape and its TypeScript type cannot drift apart.\n//\n// Terminology: the current-owner field is `workStewardUid` (locked rename from the old\n// `ownerUid`; see ttt-prod docs/design/terminology-naming-convention.md — Steward row). The original\n// creator is `foundingArtisanUid` (locked rename from the old `createdByUid`; Founding Artisan).\n\nimport { z } from 'zod';\nimport { HALL_WING_TYPE_KEYS, WORK_PROJECT_TYPE_KEYS } from '../types/content.js';\nimport { isGuildStandingId, type GuildStandingId } from '../permissions/index.js';\n\nconst guildStandingIdSchema = z.custom<GuildStandingId>(isGuildStandingId);\nconst userRefSchema = z.object({ uid: z.string() });\n\nexport const GuildmateStatusSchema = z.enum(['active', 'departed']);\nexport type GuildmateStatus = z.infer<typeof GuildmateStatusSchema>;\n\nexport const GuildmateUserSchema = z.object({\n uid: z.string(),\n guildStandings: z.array(guildStandingIdSchema),\n tradeProfessions: z.array(z.string()),\n stakeShareCount: z.number(),\n joinedAt: z.number(),\n status: GuildmateStatusSchema,\n /**\n * Holder kind for this stake entry. Absent/`'user'` = a real guildmate person.\n * `'foundingWork'` = the realm founding-Work holder (keyed by the founding\n * workProjectId, NOT a user uid).\n */\n holderType: z.enum(['user', 'foundingWork']).optional(),\n /**\n * Per-(user, workProject) monotonic INPUT-trigger version for the chat\n * channel-auth projection (chat-edge-rebuild Contract B / P3). Absent ⇒ 0.\n * Bumped atomically in the authoritative mutation on member create/reactivate,\n * departure/removal, standing change, AND trade-profession change; the\n * `workChannelsForUser` fanout keys on the POST-increment value. It NEVER\n * increments or replaces the per-pair OUTPUT `channelAuthVersion`.\n */\n guildAuthInputVersion: z.number().optional(),\n /**\n * N3 data-deletion / account-end forfeiture tombstone. Set together with\n * `status: 'departed'` when a member leaves involuntarily-of-record: their\n * stake shares STAY in the immutable 1000-split (never removed) but are\n * forfeited — the future payout engine routes a tombstone's slice to the\n * community fund and excludes it from active distribution. `departedReason`\n * distinguishes the cause; `'bannedForCause'` is reserved for the future\n * ban-forfeiture path (included now so it needs no second package publish).\n *\n * `'selfLeave'` is DIFFERENT share semantics: a PRE-PUBLISH voluntary guild\n * exit (leaveWorkProject). There the 1000-split is still fluid, so the\n * member's `stakeShareCount` is ZEROED and returned to the pool for the\n * steward to re-allocate — NOT retained as a community-fund tombstone. A\n * self-leave is impossible once `status: 'published'` (the stake-share freeze\n * blocks it), so the tombstone and the pool-return dispositions never overlap\n * in a single Work's lifecycle.\n */\n departedReason: z.enum(['voluntaryDeletion', 'bannedForCause', 'selfLeave']).optional(),\n departedAt: z.number().optional(),\n});\nexport type GuildmateUser = z.infer<typeof GuildmateUserSchema>;\n\nexport const PublicGuildmateUserSchema = z.object({\n uid: z.string(),\n tradeProfessions: z.array(z.string()),\n joinedAt: z.number(),\n status: GuildmateStatusSchema,\n});\nexport type PublicGuildmateUser = z.infer<typeof PublicGuildmateUserSchema>;\n\nexport const PendingStakeSharesSchema = z.record(\n z.string(),\n z.object({ amount: z.number(), createdAt: z.number() }),\n);\nexport type PendingStakeShares = z.infer<typeof PendingStakeSharesSchema>;\n\nexport const FullWorkProjectSchema = z.object({\n workProjectId: z.string(),\n createdOn: z.number(),\n type: z.string(),\n workingDescription: z.string(),\n workingTitle: z.string(),\n hallWingType: z.enum(HALL_WING_TYPE_KEYS),\n createdBy: userRefSchema,\n status: z.enum(['open', 'pendingVerification', 'published', 'rejected']),\n guildmateUserIds: z.record(z.string(), z.boolean()).optional(),\n invitedUserIds: z.record(z.string(), z.boolean()).optional(),\n workRealmId: z.string(),\n realmCanonStatus: z.enum(['canon', 'nonCanon']),\n pendingStakeShares: PendingStakeSharesSchema.optional(),\n // Running total of chat-attachment STORED-OUTPUT bytes across all of this Work's chat\n // channels, checked against MAX_WORK_CHAT_ATTACHMENT_STORAGE_BYTES (charter 2 GiB /\n // full 10 GiB; DJ ruling 2026-07-25). Absent ⇒ 0 — the field is never initialized on\n // create and needs no backfill; the first finalize writes it via an increment, so\n // every pre-existing Work reads as 0 used. Maintained at asset finalize (+ stored\n // bytes) and retire (− stored bytes), with a pessimistic pre-check at startUpload.\n // Backend-only-writable.\n chatAttachmentBytesUsed: z.number().optional(),\n // Moderation \"require retitle\" remedy (work/realm report path). When an admin\n // upholds a report on an abusive public title/description, they may replace the\n // text with a generic placeholder and set this flag; the steward is prompted to\n // re-enter compliant text the next time they open the work (unpublished = direct\n // self-edit clears it; published = via the post-launch change-request flow).\n // Distinct from the `publicWorkHidden` hide (DMCA/copyright) — this keeps the\n // work visible under the placeholder. Backend-only-writable.\n moderationRetitleRequired: z.boolean().optional(),\n moderationRetitleReason: z.string().optional(),\n // Per-field extension of the retitle remedy (uniform with the Tale/Tune/Television content family):\n // which text fields ('title', 'description', …) an admin cleared to a placeholder — \"all or any\",\n // instead of the always-both retitle — and the operator's reason surfaced on the steward's edit\n // surface. Empty/absent when nothing was cleared. Backend-only-writable.\n moderationClearedFields: z.array(z.string()).optional(),\n moderationClearedReason: z.string().optional(),\n moderatedAt: z.number().optional(),\n});\nexport type FullWorkProject = z.infer<typeof FullWorkProjectSchema>;\n\n// Top-level safe signed-in-user Work shell / search projection. Server/callable-written only.\nexport const PublicWorkProjectSchema = z.object({\n workProjectId: z.string(),\n publicWorkStatus: z.enum(['draft', 'released']),\n publicWorkHidden: z.boolean(),\n workRealmId: z.string(),\n realmCanonStatus: z.enum(['canon', 'nonCanon']),\n type: z.enum(WORK_PROJECT_TYPE_KEYS),\n hallWingType: z.enum(HALL_WING_TYPE_KEYS),\n workingTitle: z.string(),\n workingTitle_lowercase: z.string(),\n workingDescription: z.string(),\n coverAssetId: z.string().optional(),\n workStewardUid: z.string(),\n foundingArtisanUid: z.string(),\n createdOn: z.number(),\n updatedOn: z.number(),\n});\nexport type PublicWorkProject = z.infer<typeof PublicWorkProjectSchema>;\n\n// ===========================================================================\n// Work-project FILE FOLDER system (S7) — supersedes the flat workAssets model.\n// A default folder (every active guildmate views/uploads) + custom folders whose\n// audience is controlled by TRADE PROFESSIONS, while file-system ADMINISTRATION is\n// controlled by guild standings (StewardOwner / WorkProjectManager / WorkAssetAdmin).\n// See ttt-prod docs/design/work-project-file-folders.md. Realm sharing of a file is the\n// `realmFileCanonStatus` seam on the file's mediaAssets doc (media-assets.ts).\n// ===========================================================================\n\n/** `allWorkProjects/{workProjectId}/workFileFolders/{workFileFolderId}`. */\nexport const WorkFileFolderSchema = z.object({\n workFileFolderId: z.string(),\n workProjectId: z.string(),\n name: z.string(),\n // The auto-created \"All Guildmates\" folder (view/upload open to every active\n // guildmate; delete/manage needs file-admin). Exactly one per work project.\n isDefault: z.boolean(),\n // Custom-folder access — trade-profession ids (TRADE_PROFESSION_OPTIONS). Empty\n // on the default folder; file admins always see/manage every folder regardless.\n canViewTradeProfessions: z.array(z.string()),\n canUploadTradeProfessions: z.array(z.string()),\n canDeleteTradeProfessions: z.array(z.string()),\n fileCount: z.number(),\n /** Sum of this folder's files' `sizeBytes`. Maintained alongside `fileCount`\n * (increment on upload, decrement on delete); the project-wide storage usage +\n * `MAX_WORK_FILE_STORAGE_BYTES` cap are computed by summing this across folders. */\n storageBytes: z.number(),\n createdBy: userRefSchema,\n createdAt: z.number(),\n updatedAt: z.number(),\n});\nexport type WorkFileFolder = z.infer<typeof WorkFileFolderSchema>;\n\n/** `allWorkProjects/{workProjectId}/workFileFolders/{workFileFolderId}/workFiles/{workFileId}`. */\nexport const WorkFileSchema = z.object({\n workFileId: z.string(),\n workProjectId: z.string(),\n workFileFolderId: z.string(),\n name: z.string(),\n mediaAssetId: z.string(),\n contentType: z.string(),\n sizeBytes: z.number(),\n uploadedBy: userRefSchema,\n createdAt: z.number(),\n});\nexport type WorkFile = z.infer<typeof WorkFileSchema>;\n\n// Realm source of truth and Realm search/tag surface. Server/callable-written only.\nexport const WorkRealmSchema = z.object({\n workRealmId: z.string(),\n realmType: z.enum(['public', 'standalone']),\n realmStatus: z.enum(['draft', 'released']),\n realmHidden: z.boolean(),\n workingTitle: z.string(),\n workingTitle_lowercase: z.string(),\n workingDescription: z.string(),\n // Square realm cover art (the 'realm-cover' upload origin; processor-written).\n // Optional while the realm is a DRAFT; releasing the realm REQUIRES it — the\n // realm release callable enforces presence (never required at founding, so a\n // work creation is never blocked on realm art).\n realmCoverAssetId: z.string().optional(),\n workStewardUid: z.string(),\n foundingArtisanUid: z.string(),\n foundingWorkProjectId: z.string(),\n createdOn: z.number(),\n updatedOn: z.number(),\n // MONOTONIC publish lock (R1 ruling, 2026-07-12): set true by the hall publish\n // core the first time any work in this realm publishes, and never unset — even\n // if that work later unpublishes (the realm name already went public). While\n // absent/false, realm info is direct-edit; once true, realm text changes route\n // exclusively through the change-request pipeline (surface 'workRealm').\n // Backend-only-writable.\n hasEverPublishedWork: z.boolean().optional(),\n // Moderation \"require retitle\" remedy (see FullWorkProject above) — admin\n // replaces an abusive realm title/description with a placeholder + sets this so\n // the steward must re-enter compliant text. Distinct from `realmHidden` (the\n // DMCA/copyright takedown). Backend-only-writable.\n moderationRetitleRequired: z.boolean().optional(),\n moderationRetitleReason: z.string().optional(),\n // Per-field extension of the retitle remedy (see FullWorkProject) — which realm text fields an\n // admin cleared to a placeholder (\"all or any\"), plus the operator's reason. Backend-only-writable.\n moderationClearedFields: z.array(z.string()).optional(),\n moderationClearedReason: z.string().optional(),\n moderatedAt: z.number().optional(),\n});\nexport type WorkRealm = z.infer<typeof WorkRealmSchema>;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttt-productions/ttt-core",
|
|
3
|
-
"version": "0.78.
|
|
3
|
+
"version": "0.78.27",
|
|
4
4
|
"description": "Core types, Firestore path constants, and shared constants for TTT Productions",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
},
|
|
115
115
|
"dependencies": {
|
|
116
116
|
"@ttt-productions/audit-core": "^0.7.1",
|
|
117
|
-
"@ttt-productions/chat-schemas": "^0.9.
|
|
117
|
+
"@ttt-productions/chat-schemas": "^0.9.4",
|
|
118
118
|
"@ttt-productions/edge-protocol-core": "^0.1.5",
|
|
119
119
|
"@ttt-productions/media-schemas": "^0.14.3",
|
|
120
120
|
"@ttt-productions/notification-core": "^0.15.5",
|