@ttt-productions/ttt-core 0.78.26 → 0.79.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/capabilities/capability-registry.d.ts +2 -2
- package/dist/capabilities/capability-registry.d.ts.map +1 -1
- package/dist/capabilities/capability-registry.js +5 -5
- package/dist/capabilities/capability-registry.js.map +1 -1
- package/dist/capabilities/messaging-surfaces.d.ts.map +1 -1
- package/dist/capabilities/messaging-surfaces.js +7 -3
- package/dist/capabilities/messaging-surfaces.js.map +1 -1
- 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 +17 -0
- package/dist/constants/app-mode.js.map +1 -1
- package/dist/constants/business-content.d.ts +0 -2
- package/dist/constants/business-content.d.ts.map +1 -1
- package/dist/constants/business-content.js +0 -2
- package/dist/constants/business-content.js.map +1 -1
- package/dist/constants/conversation-files.d.ts +7 -0
- package/dist/constants/conversation-files.d.ts.map +1 -0
- package/dist/constants/conversation-files.js +14 -0
- package/dist/constants/conversation-files.js.map +1 -0
- package/dist/constants/index.d.ts +1 -0
- package/dist/constants/index.d.ts.map +1 -1
- package/dist/constants/index.js +1 -0
- package/dist/constants/index.js.map +1 -1
- package/dist/doc-schemas/chat-sync.d.ts +0 -4
- package/dist/doc-schemas/chat-sync.d.ts.map +1 -1
- package/dist/doc-schemas/chat-sync.js +2 -9
- package/dist/doc-schemas/chat-sync.js.map +1 -1
- package/dist/doc-schemas/commissions.d.ts +2 -2
- package/dist/doc-schemas/media-activation-jobs.d.ts +3 -8
- package/dist/doc-schemas/media-activation-jobs.d.ts.map +1 -1
- package/dist/doc-schemas/media-assets.d.ts +22 -34
- package/dist/doc-schemas/media-assets.d.ts.map +1 -1
- package/dist/doc-schemas/media-assets.js +24 -21
- package/dist/doc-schemas/media-assets.js.map +1 -1
- package/dist/doc-schemas/messaging.d.ts +41 -19
- package/dist/doc-schemas/messaging.d.ts.map +1 -1
- package/dist/doc-schemas/messaging.js +64 -4
- package/dist/doc-schemas/messaging.js.map +1 -1
- package/dist/doc-schemas/moderation.d.ts +1 -1
- package/dist/doc-schemas/ncii/allegations.d.ts +21 -9
- package/dist/doc-schemas/ncii/allegations.d.ts.map +1 -1
- package/dist/doc-schemas/ncii/cases.d.ts +10 -4
- package/dist/doc-schemas/ncii/cases.d.ts.map +1 -1
- package/dist/doc-schemas/ncii/holds.d.ts +10 -4
- package/dist/doc-schemas/ncii/holds.d.ts.map +1 -1
- package/dist/doc-schemas/ncii/removal.d.ts +13 -7
- package/dist/doc-schemas/ncii/removal.d.ts.map +1 -1
- package/dist/doc-schemas/ncii/requests.d.ts +11 -5
- package/dist/doc-schemas/ncii/requests.d.ts.map +1 -1
- package/dist/doc-schemas/registry.d.ts +148 -119
- package/dist/doc-schemas/registry.d.ts.map +1 -1
- package/dist/doc-schemas/registry.js +5 -1
- package/dist/doc-schemas/registry.js.map +1 -1
- package/dist/doc-schemas/safety/case.d.ts +10 -4
- package/dist/doc-schemas/safety/case.d.ts.map +1 -1
- package/dist/doc-schemas/safety/case.js +4 -3
- package/dist/doc-schemas/safety/case.js.map +1 -1
- package/dist/doc-schemas/safety/evidence.d.ts +2 -3
- package/dist/doc-schemas/safety/evidence.d.ts.map +1 -1
- package/dist/doc-schemas/safety/foundation.d.ts +15 -8
- package/dist/doc-schemas/safety/foundation.d.ts.map +1 -1
- package/dist/doc-schemas/safety/foundation.js +32 -6
- package/dist/doc-schemas/safety/foundation.js.map +1 -1
- package/dist/doc-schemas/safety/holds.d.ts +1 -1
- package/dist/doc-schemas/safety/report.d.ts +25 -10
- package/dist/doc-schemas/safety/report.d.ts.map +1 -1
- package/dist/doc-schemas/safety/report.js +2 -1
- package/dist/doc-schemas/safety/report.js.map +1 -1
- package/dist/ids/chat-ids.d.ts +1 -2
- package/dist/ids/chat-ids.d.ts.map +1 -1
- package/dist/ids/chat-ids.js +1 -4
- package/dist/ids/chat-ids.js.map +1 -1
- package/dist/media/conversation-file-ref.d.ts +13 -0
- package/dist/media/conversation-file-ref.d.ts.map +1 -0
- package/dist/media/conversation-file-ref.js +37 -0
- package/dist/media/conversation-file-ref.js.map +1 -0
- package/dist/media/domain-events-admin.d.ts +1 -1
- package/dist/media/domain-events-social.d.ts +0 -7
- package/dist/media/domain-events-social.d.ts.map +1 -1
- package/dist/media/domain-events-social.js +2 -13
- package/dist/media/domain-events-social.js.map +1 -1
- package/dist/media/domain-events.d.ts +1 -7
- package/dist/media/domain-events.d.ts.map +1 -1
- package/dist/media/domain-events.js +1 -2
- package/dist/media/domain-events.js.map +1 -1
- package/dist/media/edge-serving-contract.d.ts +6 -11
- package/dist/media/edge-serving-contract.d.ts.map +1 -1
- package/dist/media/edge-serving-contract.js.map +1 -1
- package/dist/media/file-origin.d.ts +1 -1
- package/dist/media/file-origin.d.ts.map +1 -1
- package/dist/media/file-origin.js +6 -1
- package/dist/media/file-origin.js.map +1 -1
- package/dist/media/index.d.ts +1 -0
- package/dist/media/index.d.ts.map +1 -1
- package/dist/media/index.js +1 -0
- package/dist/media/index.js.map +1 -1
- package/dist/media/pending-media.d.ts +25 -79
- package/dist/media/pending-media.d.ts.map +1 -1
- package/dist/media/photodna-coverage.js +1 -1
- package/dist/media/photodna-coverage.js.map +1 -1
- package/dist/media/start-upload.d.ts +1 -1
- package/dist/media/target-info.d.ts +6 -26
- package/dist/media/target-info.d.ts.map +1 -1
- package/dist/media/target-info.js +9 -35
- package/dist/media/target-info.js.map +1 -1
- package/dist/media/ttt-media-specs.d.ts.map +1 -1
- package/dist/media/ttt-media-specs.js +8 -5
- package/dist/media/ttt-media-specs.js.map +1 -1
- package/dist/media/upload-tray-display.js +1 -1
- package/dist/media/upload-tray-display.js.map +1 -1
- package/dist/paths/collection-refs.d.ts +2 -0
- package/dist/paths/collection-refs.d.ts.map +1 -1
- package/dist/paths/collection-refs.js +4 -0
- package/dist/paths/collection-refs.js.map +1 -1
- package/dist/paths/collections.d.ts +1 -0
- package/dist/paths/collections.d.ts.map +1 -1
- package/dist/paths/collections.js +7 -0
- package/dist/paths/collections.js.map +1 -1
- package/dist/paths/path-builders.d.ts +2 -0
- package/dist/paths/path-builders.d.ts.map +1 -1
- package/dist/paths/path-builders.js +5 -0
- package/dist/paths/path-builders.js.map +1 -1
- package/dist/report/report-config-values.d.ts +3 -1
- package/dist/report/report-config-values.d.ts.map +1 -1
- package/dist/report/report-config-values.js +5 -1
- package/dist/report/report-config-values.js.map +1 -1
- package/dist/safety/ncii-intake-derivations.d.ts.map +1 -1
- package/dist/safety/ncii-intake-derivations.js +17 -5
- package/dist/safety/ncii-intake-derivations.js.map +1 -1
- package/dist/schemas/admin.d.ts +3 -0
- package/dist/schemas/admin.d.ts.map +1 -1
- package/dist/schemas/admin.js +5 -0
- package/dist/schemas/admin.js.map +1 -1
- package/dist/schemas/chat.js +3 -3
- package/dist/schemas/chat.js.map +1 -1
- package/dist/schemas/commissions.d.ts +1 -1
- package/dist/schemas/media.d.ts +0 -4
- package/dist/schemas/media.d.ts.map +1 -1
- package/dist/schemas/media.js +5 -10
- package/dist/schemas/media.js.map +1 -1
- package/dist/schemas/ncii.d.ts +3 -0
- package/dist/schemas/ncii.d.ts.map +1 -1
- package/dist/schemas/notification.d.ts +1 -0
- package/dist/schemas/notification.d.ts.map +1 -1
- package/dist/types/audit.d.ts +1 -1
- package/dist/types/audit.d.ts.map +1 -1
- package/dist/types/audit.js.map +1 -1
- package/package.json +2 -2
|
@@ -2,7 +2,7 @@ import type { FileOrigin } from '../media/file-origin.js';
|
|
|
2
2
|
/** Every age/eligibility-gated capability id. Past-tense/imperative-neutral,
|
|
3
3
|
* dotted-namespace. Adding a value here REQUIRES adding it to CAPABILITY_REGISTRY
|
|
4
4
|
* (the exhaustive test enforces the 1:1). */
|
|
5
|
-
export type CapabilityId = 'account.becomeArtisan' | 'square.post' | 'square.acceptAgreements' | 'pledge.create' | 'messaging.guildInvite' | 'messaging.send' | 'messaging.
|
|
5
|
+
export type CapabilityId = 'account.becomeArtisan' | 'square.post' | 'square.acceptAgreements' | 'pledge.create' | 'messaging.guildInvite' | 'messaging.send' | 'messaging.fileShare' | 'collaboration.commissionProposal' | 'collaboration.auditionEntry' | 'stakeShares.hold' | 'upload.origin';
|
|
6
6
|
/** The age requirement a capability imposes. */
|
|
7
7
|
export type CapabilityAgeRequirement = 'adult18Plus' | 'none';
|
|
8
8
|
export interface CapabilityDefinition {
|
|
@@ -22,7 +22,7 @@ export interface CapabilityDefinition {
|
|
|
22
22
|
* just the create callable — Phase 6 item 3). Origins tied to artisan-only
|
|
23
23
|
* surfaces (collaboration, hall publication, work assets) are 18+ because only
|
|
24
24
|
* 18+ accounts can be artisan creators / hold stake shares. */
|
|
25
|
-
export declare const ADULT_ONLY_UPLOAD_ORIGINS: readonly ["squareStreetz", "commission-posting", "commission-proposal", "audition-prompt", "audition-entry", "hallLibrary-cover-square", "hallLibrary-cover-poster", "hallLibrary-cover-cinematic", "realm-cover", "chapter-photo", "tune-track-photo", "tune-track-audio", "television-episode-photo", "television-episode-video", "
|
|
25
|
+
export declare const ADULT_ONLY_UPLOAD_ORIGINS: readonly ["squareStreetz", "commission-posting", "commission-proposal", "audition-prompt", "audition-entry", "hallLibrary-cover-square", "hallLibrary-cover-poster", "hallLibrary-cover-cinematic", "realm-cover", "chapter-photo", "tune-track-photo", "tune-track-audio", "television-episode-photo", "television-episode-video", "conversation-file", "work-asset"];
|
|
26
26
|
export declare const CAPABILITY_REGISTRY: Record<CapabilityId, CapabilityDefinition>;
|
|
27
27
|
/** All capability ids (for exhaustiveness tests + iteration). */
|
|
28
28
|
export declare const ALL_CAPABILITY_IDS: CapabilityId[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capability-registry.d.ts","sourceRoot":"","sources":["../../src/capabilities/capability-registry.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D;;6CAE6C;AAC7C,MAAM,MAAM,YAAY,GACpB,uBAAuB,GACvB,aAAa,GACb,yBAAyB,GACzB,eAAe,GACf,uBAAuB,GACvB,gBAAgB,GAChB,
|
|
1
|
+
{"version":3,"file":"capability-registry.d.ts","sourceRoot":"","sources":["../../src/capabilities/capability-registry.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D;;6CAE6C;AAC7C,MAAM,MAAM,YAAY,GACpB,uBAAuB,GACvB,aAAa,GACb,yBAAyB,GACzB,eAAe,GACf,uBAAuB,GACvB,gBAAgB,GAChB,qBAAqB,GACrB,kCAAkC,GAClC,6BAA6B,GAC7B,kBAAkB,GAClB,eAAe,CAAC;AAEpB,gDAAgD;AAChD,MAAM,MAAM,wBAAwB,GAChC,aAAa,GACb,MAAM,CAAC;AAEX,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,YAAY,CAAC;IACjB,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAC;IACpB;mFAC+E;IAC/E,cAAc,EAAE,wBAAwB,CAAC;IACzC,8EAA8E;IAC9E,SAAS,EAAE,OAAO,CAAC;IACnB;4DACwD;IACxD,aAAa,EAAE,SAAS,UAAU,EAAE,CAAC;CACtC;AAED;;;+DAG+D;AAC/D,eAAO,MAAM,yBAAyB,wWAiBI,CAAC;AAE3C,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,YAAY,EAAE,oBAAoB,CA8E1E,CAAC;AAEF,iEAAiE;AACjE,eAAO,MAAM,kBAAkB,EAAuC,YAAY,EAAE,CAAC;AAErF;oDACoD;AACpD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,OAAO,CAAC;IAClB,wBAAwB,EAAE,MAAM,CAAC;CAClC;AAED,gEAAgE;AAChE,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,YAAY,EACxB,GAAG,EAAE,oBAAoB,GACxB,OAAO,CAIT;AAED,4CAA4C;AAC5C,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAElE"}
|
|
@@ -25,7 +25,7 @@ export const ADULT_ONLY_UPLOAD_ORIGINS = [
|
|
|
25
25
|
'tune-track-audio',
|
|
26
26
|
'television-episode-photo',
|
|
27
27
|
'television-episode-video',
|
|
28
|
-
'
|
|
28
|
+
'conversation-file',
|
|
29
29
|
'work-asset',
|
|
30
30
|
];
|
|
31
31
|
export const CAPABILITY_REGISTRY = {
|
|
@@ -71,12 +71,12 @@ export const CAPABILITY_REGISTRY = {
|
|
|
71
71
|
bilateral: true,
|
|
72
72
|
uploadOrigins: [],
|
|
73
73
|
},
|
|
74
|
-
'messaging.
|
|
75
|
-
id: 'messaging.
|
|
76
|
-
description: '
|
|
74
|
+
'messaging.fileShare': {
|
|
75
|
+
id: 'messaging.fileShare',
|
|
76
|
+
description: 'Share a Conversation File in an invite / admin-support conversation.',
|
|
77
77
|
ageRequirement: 'adult18Plus',
|
|
78
78
|
bilateral: true,
|
|
79
|
-
uploadOrigins: ['
|
|
79
|
+
uploadOrigins: ['conversation-file'],
|
|
80
80
|
},
|
|
81
81
|
'collaboration.commissionProposal': {
|
|
82
82
|
id: 'collaboration.commissionProposal',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capability-registry.js","sourceRoot":"","sources":["../../src/capabilities/capability-registry.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,8EAA8E;AAC9E,8EAA8E;AAC9E,wEAAwE;AACxE,6EAA6E;AAC7E,6EAA6E;AAC7E,4EAA4E;AAC5E,+EAA+E;AAuC/E;;;+DAG+D;AAC/D,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,eAAe;IACf,oBAAoB;IACpB,qBAAqB;IACrB,iBAAiB;IACjB,gBAAgB;IAChB,0BAA0B;IAC1B,0BAA0B;IAC1B,6BAA6B;IAC7B,aAAa;IACb,eAAe;IACf,kBAAkB;IAClB,kBAAkB;IAClB,0BAA0B;IAC1B,0BAA0B;IAC1B
|
|
1
|
+
{"version":3,"file":"capability-registry.js","sourceRoot":"","sources":["../../src/capabilities/capability-registry.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,8EAA8E;AAC9E,8EAA8E;AAC9E,wEAAwE;AACxE,6EAA6E;AAC7E,6EAA6E;AAC7E,4EAA4E;AAC5E,+EAA+E;AAuC/E;;;+DAG+D;AAC/D,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,eAAe;IACf,oBAAoB;IACpB,qBAAqB;IACrB,iBAAiB;IACjB,gBAAgB;IAChB,0BAA0B;IAC1B,0BAA0B;IAC1B,6BAA6B;IAC7B,aAAa;IACb,eAAe;IACf,kBAAkB;IAClB,kBAAkB;IAClB,0BAA0B;IAC1B,0BAA0B;IAC1B,mBAAmB;IACnB,YAAY;CAC4B,CAAC;AAE3C,MAAM,CAAC,MAAM,mBAAmB,GAA+C;IAC7E,uBAAuB,EAAE;QACvB,EAAE,EAAE,uBAAuB;QAC3B,WAAW,EAAE,kEAAkE;QAC/E,cAAc,EAAE,aAAa;QAC7B,SAAS,EAAE,KAAK;QAChB,aAAa,EAAE,EAAE;KAClB;IACD,aAAa,EAAE;QACb,EAAE,EAAE,aAAa;QACjB,WAAW,EAAE,+BAA+B;QAC5C,cAAc,EAAE,aAAa;QAC7B,SAAS,EAAE,KAAK;QAChB,aAAa,EAAE,CAAC,eAAe,CAAC;KACjC;IACD,yBAAyB,EAAE;QACzB,EAAE,EAAE,yBAAyB;QAC7B,WAAW,EAAE,+CAA+C;QAC5D,cAAc,EAAE,aAAa;QAC7B,SAAS,EAAE,KAAK;QAChB,aAAa,EAAE,EAAE;KAClB;IACD,eAAe,EAAE;QACf,EAAE,EAAE,eAAe;QACnB,WAAW,EAAE,6DAA6D;QAC1E,cAAc,EAAE,aAAa;QAC7B,SAAS,EAAE,KAAK;QAChB,aAAa,EAAE,EAAE;KAClB;IACD,uBAAuB,EAAE;QACvB,EAAE,EAAE,uBAAuB;QAC3B,WAAW,EAAE,4DAA4D;QACzE,cAAc,EAAE,aAAa;QAC7B,SAAS,EAAE,IAAI;QACf,aAAa,EAAE,EAAE;KAClB;IACD,gBAAgB,EAAE;QAChB,EAAE,EAAE,gBAAgB;QACpB,WAAW,EAAE,sCAAsC;QACnD,cAAc,EAAE,aAAa;QAC7B,SAAS,EAAE,IAAI;QACf,aAAa,EAAE,EAAE;KAClB;IACD,qBAAqB,EAAE;QACrB,EAAE,EAAE,qBAAqB;QACzB,WAAW,EAAE,sEAAsE;QACnF,cAAc,EAAE,aAAa;QAC7B,SAAS,EAAE,IAAI;QACf,aAAa,EAAE,CAAC,mBAAmB,CAAC;KACrC;IACD,kCAAkC,EAAE;QAClC,EAAE,EAAE,kCAAkC;QACtC,WAAW,EAAE,+DAA+D;QAC5E,cAAc,EAAE,aAAa;QAC7B,SAAS,EAAE,KAAK;QAChB,aAAa,EAAE,CAAC,qBAAqB,CAAC;KACvC;IACD,6BAA6B,EAAE;QAC7B,EAAE,EAAE,6BAA6B;QACjC,WAAW,EAAE,2DAA2D;QACxE,cAAc,EAAE,aAAa;QAC7B,SAAS,EAAE,KAAK;QAChB,aAAa,EAAE,CAAC,gBAAgB,CAAC;KAClC;IACD,kBAAkB,EAAE;QAClB,EAAE,EAAE,kBAAkB;QACtB,WAAW,EAAE,iDAAiD;QAC9D,cAAc,EAAE,aAAa;QAC7B,SAAS,EAAE,KAAK;QAChB,aAAa,EAAE,EAAE;KAClB;IACD,eAAe,EAAE;QACf,EAAE,EAAE,eAAe;QACnB,WAAW,EAAE,iEAAiE;QAC9E,cAAc,EAAE,aAAa;QAC7B,SAAS,EAAE,KAAK;QAChB,aAAa,EAAE,yBAAyB;KACzC;CACF,CAAC;AAEF,iEAAiE;AACjE,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAmB,CAAC;AASrF,gEAAgE;AAChE,MAAM,UAAU,gBAAgB,CAC9B,UAAwB,EACxB,GAAyB;IAEzB,MAAM,GAAG,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAC5C,IAAI,GAAG,CAAC,cAAc,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IAC/C,OAAO,GAAG,CAAC,QAAQ,KAAK,IAAI,CAAC;AAC/B,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,0BAA0B,CAAC,MAAc;IACvD,OAAQ,yBAA+C,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC3E,CAAC","sourcesContent":["// ============================================================================\n// CAPABILITY REGISTRY — the ONE declaration of the age/eligibility capability\n// model (Phase 6). Consolidated here 2026-07-13 from the former byte-for-byte\n// mirrors in ttt-prod `src/lib/capabilities/capability-registry.ts` and\n// `functions/src/shared/capability-registry.ts` (both trees now import this;\n// the two-tree sync tests are deleted). Upload origins are compile-linked to\n// the canonical `FileOrigin` union — an origin rename fails the build here.\n// ============================================================================\n\nimport type { FileOrigin } from '../media/file-origin.js';\n\n/** Every age/eligibility-gated capability id. Past-tense/imperative-neutral,\n * dotted-namespace. Adding a value here REQUIRES adding it to CAPABILITY_REGISTRY\n * (the exhaustive test enforces the 1:1). */\nexport type CapabilityId =\n | 'account.becomeArtisan'\n | 'square.post'\n | 'square.acceptAgreements'\n | 'pledge.create'\n | 'messaging.guildInvite'\n | 'messaging.send'\n | 'messaging.fileShare'\n | 'collaboration.commissionProposal'\n | 'collaboration.auditionEntry'\n | 'stakeShares.hold'\n | 'upload.origin';\n\n/** The age requirement a capability imposes. */\nexport type CapabilityAgeRequirement =\n | 'adult18Plus' // both actor (and, for messaging, recipient) must be 18+\n | 'none'; // available to any eligible (13+) account\n\nexport interface CapabilityDefinition {\n id: CapabilityId;\n /** Human-facing summary (admin/debug only; not user copy). */\n description: string;\n /** The age gate. `adult18Plus` capabilities are server-enforced; the claim is\n * NOT the sole authority (accountCapabilityVersion + privateData re-check). */\n ageRequirement: CapabilityAgeRequirement;\n /** When true, BOTH ends must satisfy the requirement (no-minor-messaging). */\n bilateral: boolean;\n /** Upload origins this capability governs (for the startUpload gate). Empty\n * unless the capability is `upload.origin`-adjacent. */\n uploadOrigins: readonly FileOrigin[];\n}\n\n/** Upload origins that require an 18+ account to initiate (origin-level gate, not\n * just the create callable — Phase 6 item 3). Origins tied to artisan-only\n * surfaces (collaboration, hall publication, work assets) are 18+ because only\n * 18+ accounts can be artisan creators / hold stake shares. */\nexport const ADULT_ONLY_UPLOAD_ORIGINS = [\n 'squareStreetz',\n 'commission-posting',\n 'commission-proposal',\n 'audition-prompt',\n 'audition-entry',\n 'hallLibrary-cover-square',\n 'hallLibrary-cover-poster',\n 'hallLibrary-cover-cinematic',\n 'realm-cover',\n 'chapter-photo',\n 'tune-track-photo',\n 'tune-track-audio',\n 'television-episode-photo',\n 'television-episode-video',\n 'conversation-file',\n 'work-asset',\n] as const satisfies readonly FileOrigin[];\n\nexport const CAPABILITY_REGISTRY: Record<CapabilityId, CapabilityDefinition> = {\n 'account.becomeArtisan': {\n id: 'account.becomeArtisan',\n description: 'Become an artisan creator (privilege + stake-share eligibility).',\n ageRequirement: 'adult18Plus',\n bilateral: false,\n uploadOrigins: [],\n },\n 'square.post': {\n id: 'square.post',\n description: 'Create a Square Streetz post.',\n ageRequirement: 'adult18Plus',\n bilateral: false,\n uploadOrigins: ['squareStreetz'],\n },\n 'square.acceptAgreements': {\n id: 'square.acceptAgreements',\n description: 'Accept the Square Streetz posting agreements.',\n ageRequirement: 'adult18Plus',\n bilateral: false,\n uploadOrigins: [],\n },\n 'pledge.create': {\n id: 'pledge.create',\n description: 'Create a pledge / payment (18+ only, pledge-only payments).',\n ageRequirement: 'adult18Plus',\n bilateral: false,\n uploadOrigins: [],\n },\n 'messaging.guildInvite': {\n id: 'messaging.guildInvite',\n description: 'Send a guild invite (opens an invite-conversation thread).',\n ageRequirement: 'adult18Plus',\n bilateral: true,\n uploadOrigins: [],\n },\n 'messaging.send': {\n id: 'messaging.send',\n description: 'Send a chat / invite-thread message.',\n ageRequirement: 'adult18Plus',\n bilateral: true,\n uploadOrigins: [],\n },\n 'messaging.fileShare': {\n id: 'messaging.fileShare',\n description: 'Share a Conversation File in an invite / admin-support conversation.',\n ageRequirement: 'adult18Plus',\n bilateral: true,\n uploadOrigins: ['conversation-file'],\n },\n 'collaboration.commissionProposal': {\n id: 'collaboration.commissionProposal',\n description: 'Submit a commission proposal (artisan collaboration surface).',\n ageRequirement: 'adult18Plus',\n bilateral: false,\n uploadOrigins: ['commission-proposal'],\n },\n 'collaboration.auditionEntry': {\n id: 'collaboration.auditionEntry',\n description: 'Submit an audition entry (artisan collaboration surface).',\n ageRequirement: 'adult18Plus',\n bilateral: false,\n uploadOrigins: ['audition-entry'],\n },\n 'stakeShares.hold': {\n id: 'stakeShares.hold',\n description: 'Hold stake shares (guild membership / revenue).',\n ageRequirement: 'adult18Plus',\n bilateral: false,\n uploadOrigins: [],\n },\n 'upload.origin': {\n id: 'upload.origin',\n description: 'Initiate an upload for an adult-only origin (startUpload gate).',\n ageRequirement: 'adult18Plus',\n bilateral: false,\n uploadOrigins: ADULT_ONLY_UPLOAD_ORIGINS,\n },\n};\n\n/** All capability ids (for exhaustiveness tests + iteration). */\nexport const ALL_CAPABILITY_IDS = Object.keys(CAPABILITY_REGISTRY) as CapabilityId[];\n\n/** The actor's age-relevant view, derived server-side from privateData (the\n * claim is corroborating, never sole authority). */\nexport interface AgeCapabilityContext {\n is18Plus: boolean;\n accountCapabilityVersion: number;\n}\n\n/** Does this context satisfy a capability's age requirement? */\nexport function contextSatisfies(\n capability: CapabilityId,\n ctx: AgeCapabilityContext,\n): boolean {\n const def = CAPABILITY_REGISTRY[capability];\n if (def.ageRequirement === 'none') return true;\n return ctx.is18Plus === true;\n}\n\n/** Is the given upload origin 18+-gated? */\nexport function uploadOriginRequires18Plus(origin: string): boolean {\n return (ADULT_ONLY_UPLOAD_ORIGINS as readonly string[]).includes(origin);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messaging-surfaces.d.ts","sourceRoot":"","sources":["../../src/capabilities/messaging-surfaces.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAC/B,qCAAqC;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,UAAU,EAAE,YAAY,CAAC;IACzB,6EAA6E;IAC7E,sBAAsB,EAAE,OAAO,CAAC;IAChC,yDAAyD;IACzD,qBAAqB,EAAE,OAAO,CAAC;CAChC;AAED,eAAO,MAAM,kBAAkB,EAAE,SAAS,gBAAgB,
|
|
1
|
+
{"version":3,"file":"messaging-surfaces.d.ts","sourceRoot":"","sources":["../../src/capabilities/messaging-surfaces.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAC/B,qCAAqC;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,UAAU,EAAE,YAAY,CAAC;IACzB,6EAA6E;IAC7E,sBAAsB,EAAE,OAAO,CAAC;IAChC,yDAAyD;IACzD,qBAAqB,EAAE,OAAO,CAAC;CAChC;AAED,eAAO,MAAM,kBAAkB,EAAE,SAAS,gBAAgB,EAqChD,CAAC;AAEX,iDAAiD;AACjD,eAAO,MAAM,yBAAyB,UAAsC,CAAC"}
|
|
@@ -25,9 +25,13 @@ export const MESSAGING_SURFACES = [
|
|
|
25
25
|
checksRecipientAtSend: false,
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
// Conversation Files (guild-invite + admin-support conversations only — guild
|
|
29
|
+
// chat CHANNELS have no Conversation Files). The bilateral 18+ check runs at the
|
|
30
|
+
// origin gate inside `startUpload`, which authorizes the conversation before it
|
|
31
|
+
// reserves quota; there is no per-message send path to re-check.
|
|
32
|
+
id: 'conversationFile.share',
|
|
33
|
+
callable: 'startUpload',
|
|
34
|
+
capability: 'messaging.fileShare',
|
|
31
35
|
checksRecipientAtGrant: true,
|
|
32
36
|
checksRecipientAtSend: false,
|
|
33
37
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messaging-surfaces.js","sourceRoot":"","sources":["../../src/capabilities/messaging-surfaces.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,8EAA8E;AAC9E,+DAA+D;AAC/D,mDAAmD;AACnD,4EAA4E;AAC5E,wCAAwC;AACxC,+EAA+E;AAiB/E,MAAM,CAAC,MAAM,kBAAkB,GAAgC;IAC7D;QACE,EAAE,EAAE,kBAAkB;QACtB,QAAQ,EAAE,mBAAmB;QAC7B,UAAU,EAAE,uBAAuB;QACnC,sBAAsB,EAAE,IAAI;QAC5B,qBAAqB,EAAE,IAAI;KAC5B;IACD;QACE,yFAAyF;QACzF,+FAA+F;QAC/F,6FAA6F;QAC7F,0BAA0B;QAC1B,EAAE,EAAE,gBAAgB;QACpB,QAAQ,EAAE,eAAe;QACzB,UAAU,EAAE,gBAAgB;QAC5B,sBAAsB,EAAE,IAAI;QAC5B,qBAAqB,EAAE,KAAK;KAC7B;IACD;QACE,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"messaging-surfaces.js","sourceRoot":"","sources":["../../src/capabilities/messaging-surfaces.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,8EAA8E;AAC9E,+DAA+D;AAC/D,mDAAmD;AACnD,4EAA4E;AAC5E,wCAAwC;AACxC,+EAA+E;AAiB/E,MAAM,CAAC,MAAM,kBAAkB,GAAgC;IAC7D;QACE,EAAE,EAAE,kBAAkB;QACtB,QAAQ,EAAE,mBAAmB;QAC7B,UAAU,EAAE,uBAAuB;QACnC,sBAAsB,EAAE,IAAI;QAC5B,qBAAqB,EAAE,IAAI;KAC5B;IACD;QACE,yFAAyF;QACzF,+FAA+F;QAC/F,6FAA6F;QAC7F,0BAA0B;QAC1B,EAAE,EAAE,gBAAgB;QACpB,QAAQ,EAAE,eAAe;QACzB,UAAU,EAAE,gBAAgB;QAC5B,sBAAsB,EAAE,IAAI;QAC5B,qBAAqB,EAAE,KAAK;KAC7B;IACD;QACE,8EAA8E;QAC9E,iFAAiF;QACjF,gFAAgF;QAChF,iEAAiE;QACjE,EAAE,EAAE,wBAAwB;QAC5B,QAAQ,EAAE,aAAa;QACvB,UAAU,EAAE,qBAAqB;QACjC,sBAAsB,EAAE,IAAI;QAC5B,qBAAqB,EAAE,KAAK;KAC7B;IACD;QACE,EAAE,EAAE,yBAAyB;QAC7B,QAAQ,EAAE,eAAe;QACzB,UAAU,EAAE,gBAAgB;QAC5B,sBAAsB,EAAE,IAAI;QAC5B,qBAAqB,EAAE,KAAK;KAC7B;CACO,CAAC;AAEX,iDAAiD;AACjD,MAAM,CAAC,MAAM,yBAAyB,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC","sourcesContent":["// ============================================================================\n// NO-MINOR-MESSAGING — the ONE route/entry-point inventory. Consolidated here\n// 2026-07-13 from the former byte-for-byte mirrors in ttt-prod\n// `src/lib/capabilities/messaging-surfaces.ts` and\n// `functions/src/shared/messaging-surfaces.ts` (both trees now import this;\n// the two-tree sync tests are deleted).\n// ============================================================================\n\nimport type { CapabilityId } from './capability-registry.js';\n\nexport interface MessagingSurface {\n /** Stable id for the entry point. */\n id: string;\n /** The backend callable / worker that owns this surface. */\n callable: string;\n /** The messaging capability that gates it (MUST be a bilateral capability). */\n capability: CapabilityId;\n /** Whether the recipient is checked at GRANT time (e.g. invite creation). */\n checksRecipientAtGrant: boolean;\n /** Whether the recipient is (re)checked at SEND time. */\n checksRecipientAtSend: boolean;\n}\n\nexport const MESSAGING_SURFACES: readonly MessagingSurface[] = [\n {\n id: 'guildInvite.send',\n callable: 'inviteUserToGuild',\n capability: 'messaging.guildInvite',\n checksRecipientAtGrant: true,\n checksRecipientAtSend: true,\n },\n {\n // Realtime via the chat Worker DOs: the no-minor (18+) check is at CONNECT/GRANT time in\n // `mintChatGrant` (`authorizeChannelScope` → assertCapability('messaging.send')) per peer, NOT\n // re-checked per message; an access revoke closes the live socket. `sendGuildChatMessage` is\n // admin-support-only now.\n id: 'guildChat.send',\n callable: 'mintChatGrant',\n capability: 'messaging.send',\n checksRecipientAtGrant: true,\n checksRecipientAtSend: false,\n },\n {\n // Conversation Files (guild-invite + admin-support conversations only — guild\n // chat CHANNELS have no Conversation Files). The bilateral 18+ check runs at the\n // origin gate inside `startUpload`, which authorizes the conversation before it\n // reserves quota; there is no per-message send path to re-check.\n id: 'conversationFile.share',\n callable: 'startUpload',\n capability: 'messaging.fileShare',\n checksRecipientAtGrant: true,\n checksRecipientAtSend: false,\n },\n {\n id: 'inviteConversation.send',\n callable: 'mintChatGrant',\n capability: 'messaging.send',\n checksRecipientAtGrant: true,\n checksRecipientAtSend: false,\n },\n] as const;\n\n/** Surface ids (for the exhaustiveness test). */\nexport const ALL_MESSAGING_SURFACE_IDS = MESSAGING_SURFACES.map((s) => s.id);\n"]}
|
|
@@ -29,6 +29,15 @@ export interface TttLimits {
|
|
|
29
29
|
maxTuneTracks: number;
|
|
30
30
|
maxTelevisionEpisodes: number;
|
|
31
31
|
};
|
|
32
|
+
/** Conversation Files container caps — PER CONVERSATION (one guild-invite
|
|
33
|
+
* conversation or one admin-support dispatch thread). Both scopes share one cap
|
|
34
|
+
* set; guild chat channels have no Conversation Files. DJ ruling 2026-07-25. */
|
|
35
|
+
conversation: {
|
|
36
|
+
/** Published active Conversation Files allowed in one conversation. */
|
|
37
|
+
maxConversationFiles: number;
|
|
38
|
+
/** Published STORED-OUTPUT bytes allowed in one conversation. */
|
|
39
|
+
maxConversationFileStorageBytes: 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,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;;qFAEiF;IACjF,YAAY,EAAE;QACZ,uEAAuE;QACvE,oBAAoB,EAAE,MAAM,CAAC;QAC7B,iEAAiE;QACjE,+BAA+B,EAAE,MAAM,CAAC;KACzC,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,SAwF5B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,SA8EzB,CAAC;AAEF;uEACuE;AACvE,eAAO,MAAM,aAAa,EAAE,SAA+C,CAAC"}
|
|
@@ -34,6 +34,16 @@ export const CHARTER_LIMITS = {
|
|
|
34
34
|
maxTuneTracks: 5,
|
|
35
35
|
maxTelevisionEpisodes: 3,
|
|
36
36
|
},
|
|
37
|
+
// Conversation Files are QUOTA'D PER CONVERSATION (DJ ruling 2026-07-25). Counted on
|
|
38
|
+
// STORED OUTPUT bytes (what actually sits in R2 after transcode), never on raw upload
|
|
39
|
+
// bytes. Rationale: a per-file `maxBytes` cap alone bounds one upload but nothing stops
|
|
40
|
+
// unbounded accumulation across a long-running conversation — this is the abuse brake
|
|
41
|
+
// on that, and it is what `startUpload`'s reservation and the publication transfer both
|
|
42
|
+
// check. Charter: 10 files / 500 MiB per conversation.
|
|
43
|
+
conversation: {
|
|
44
|
+
maxConversationFiles: 10,
|
|
45
|
+
maxConversationFileStorageBytes: 524_288_000, // 500 MiB
|
|
46
|
+
},
|
|
37
47
|
hall: { maxSubmitBatch: 10 },
|
|
38
48
|
batches: { trendingFeedProcessLimit: 250, maxFeedbackSubmitters: 25 },
|
|
39
49
|
rateLimits: {
|
|
@@ -114,6 +124,13 @@ export const FULL_LIMITS = {
|
|
|
114
124
|
maxTuneTracks: 50,
|
|
115
125
|
maxTelevisionEpisodes: 25,
|
|
116
126
|
},
|
|
127
|
+
// 20 files / 1 GiB (full): the same per-conversation Conversation Files quota as
|
|
128
|
+
// charter, scaled for a public-launch conversation. Still a hard ceiling on
|
|
129
|
+
// unbounded R2 accumulation. See the CHARTER_LIMITS note above. DJ ruling 2026-07-25.
|
|
130
|
+
conversation: {
|
|
131
|
+
maxConversationFiles: 20,
|
|
132
|
+
maxConversationFileStorageBytes: 1_073_741_824, // 1 GiB
|
|
133
|
+
},
|
|
117
134
|
hall: { maxSubmitBatch: 50 },
|
|
118
135
|
batches: { trendingFeedProcessLimit: 1000, maxFeedbackSubmitters: 100 },
|
|
119
136
|
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 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 /** Conversation Files container caps — PER CONVERSATION (one guild-invite\n * conversation or one admin-support dispatch thread). Both scopes share one cap\n * set; guild chat channels have no Conversation Files. DJ ruling 2026-07-25. */\n conversation: {\n /** Published active Conversation Files allowed in one conversation. */\n maxConversationFiles: number;\n /** Published STORED-OUTPUT bytes allowed in one conversation. */\n maxConversationFileStorageBytes: 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 // Conversation Files are QUOTA'D PER CONVERSATION (DJ ruling 2026-07-25). Counted on\n // STORED OUTPUT bytes (what actually sits in R2 after transcode), never on raw upload\n // bytes. Rationale: a per-file `maxBytes` cap alone bounds one upload but nothing stops\n // unbounded accumulation across a long-running conversation — this is the abuse brake\n // on that, and it is what `startUpload`'s reservation and the publication transfer both\n // check. Charter: 10 files / 500 MiB per conversation.\n conversation: {\n maxConversationFiles: 10,\n maxConversationFileStorageBytes: 524_288_000, // 500 MiB\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 // 20 files / 1 GiB (full): the same per-conversation Conversation Files quota as\n // charter, scaled for a public-launch conversation. Still a hard ceiling on\n // unbounded R2 accumulation. See the CHARTER_LIMITS note above. DJ ruling 2026-07-25.\n conversation: {\n maxConversationFiles: 20,\n maxConversationFileStorageBytes: 1_073_741_824, // 1 GiB\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"]}
|
|
@@ -141,6 +141,4 @@ export declare const MAX_MENTION_DISPLAY_LENGTH = 30;
|
|
|
141
141
|
export declare const MAX_GUILD_INVITE_MESSAGE_LENGTH = 500;
|
|
142
142
|
/** Maximum length for a pledgePayment message. */
|
|
143
143
|
export declare const MAX_PLEDGE_PAYMENT_MESSAGE_LENGTH = 500;
|
|
144
|
-
/** Maximum length for a chat reply-to preview snippet stored on an attachment. */
|
|
145
|
-
export declare const MAX_CHAT_REPLY_PREVIEW_LENGTH = 280;
|
|
146
144
|
//# sourceMappingURL=business-content.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"business-content.d.ts","sourceRoot":"","sources":["../../src/constants/business-content.ts"],"names":[],"mappings":"AAWA,gGAAgG;AAChG,eAAO,MAAM,qCAAqC,MAAM,CAAC;AAIzD,8EAA8E;AAC9E,eAAO,MAAM,uBAAuB,QAAkD,CAAC;AAEvF,iEAAiE;AACjE,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAE7C,6CAA6C;AAC7C,eAAO,MAAM,2BAA2B,MAAgC,CAAC;AAEzE,kEAAkE;AAClE,eAAO,MAAM,iCAAiC,MAAM,CAAC;AAIrD;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,oEACqB,CAAC;AAE/D;;;;;GAKG;AACH,eAAO,MAAM,iCAAiC,2BAA2B,CAAC;AAC1E,eAAO,MAAM,iCAAiC,6CAA6C,CAAC;AAE5F;;;;;;;;GAQG;AACH,eAAO,MAAM,gCAAgC;;;;;;;;;CAYS,CAAC;AAEvD,8EAA8E;AAC9E,MAAM,MAAM,0BAA0B,GAAG,MAAM,OAAO,gCAAgC,CAAC;AAEvF;;;;;;;;GAQG;AACH,eAAO,MAAM,+BAA+B,8CAIlC,CAAC;AAEX;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;CASiB,CAAC;AAEvD;;;kEAGkE;AAClE,eAAO,MAAM,2BAA2B;;;;;;CAMG,CAAC;AAE5C;2FAC2F;AAC3F,eAAO,MAAM,qCAAqC,OAAO,CAAC;AAI1D;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,6BAA6B,QAEiC,CAAC;AAE5E,eAAO,MAAM,8BAA8B,QAMO,CAAC;AAInD;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB;;;;;CAKO,CAAC;AAI5C,4CAA4C;AAC5C,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAE7C;;4EAE4E;AAC5E,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAC9C,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAE9C,kDAAkD;AAClD,eAAO,MAAM,+BAA+B,OAAO,CAAC;AAEpD;;;;;GAKG;AACH,eAAO,MAAM,iCAAiC,SAAU,CAAC;AAIzD,+CAA+C;AAC/C,eAAO,MAAM,eAAe,MAAM,CAAC;AAEnC,yEAAyE;AACzE,eAAO,MAAM,YAAY,IAAI,CAAC;AAE9B,8EAA8E;AAC9E,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAI7C,iDAAiD;AACjD,eAAO,MAAM,+BAA+B,MAAM,CAAC;AAEnD,kDAAkD;AAClD,eAAO,MAAM,iCAAiC,MAAM,CAAC
|
|
1
|
+
{"version":3,"file":"business-content.d.ts","sourceRoot":"","sources":["../../src/constants/business-content.ts"],"names":[],"mappings":"AAWA,gGAAgG;AAChG,eAAO,MAAM,qCAAqC,MAAM,CAAC;AAIzD,8EAA8E;AAC9E,eAAO,MAAM,uBAAuB,QAAkD,CAAC;AAEvF,iEAAiE;AACjE,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAE7C,6CAA6C;AAC7C,eAAO,MAAM,2BAA2B,MAAgC,CAAC;AAEzE,kEAAkE;AAClE,eAAO,MAAM,iCAAiC,MAAM,CAAC;AAIrD;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,oEACqB,CAAC;AAE/D;;;;;GAKG;AACH,eAAO,MAAM,iCAAiC,2BAA2B,CAAC;AAC1E,eAAO,MAAM,iCAAiC,6CAA6C,CAAC;AAE5F;;;;;;;;GAQG;AACH,eAAO,MAAM,gCAAgC;;;;;;;;;CAYS,CAAC;AAEvD,8EAA8E;AAC9E,MAAM,MAAM,0BAA0B,GAAG,MAAM,OAAO,gCAAgC,CAAC;AAEvF;;;;;;;;GAQG;AACH,eAAO,MAAM,+BAA+B,8CAIlC,CAAC;AAEX;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;CASiB,CAAC;AAEvD;;;kEAGkE;AAClE,eAAO,MAAM,2BAA2B;;;;;;CAMG,CAAC;AAE5C;2FAC2F;AAC3F,eAAO,MAAM,qCAAqC,OAAO,CAAC;AAI1D;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,6BAA6B,QAEiC,CAAC;AAE5E,eAAO,MAAM,8BAA8B,QAMO,CAAC;AAInD;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB;;;;;CAKO,CAAC;AAI5C,4CAA4C;AAC5C,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAE7C;;4EAE4E;AAC5E,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAC9C,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAE9C,kDAAkD;AAClD,eAAO,MAAM,+BAA+B,OAAO,CAAC;AAEpD;;;;;GAKG;AACH,eAAO,MAAM,iCAAiC,SAAU,CAAC;AAIzD,+CAA+C;AAC/C,eAAO,MAAM,eAAe,MAAM,CAAC;AAEnC,yEAAyE;AACzE,eAAO,MAAM,YAAY,IAAI,CAAC;AAE9B,8EAA8E;AAC9E,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAI7C,iDAAiD;AACjD,eAAO,MAAM,+BAA+B,MAAM,CAAC;AAEnD,kDAAkD;AAClD,eAAO,MAAM,iCAAiC,MAAM,CAAC"}
|
|
@@ -164,6 +164,4 @@ export const MAX_MENTION_DISPLAY_LENGTH = 30;
|
|
|
164
164
|
export const MAX_GUILD_INVITE_MESSAGE_LENGTH = 500;
|
|
165
165
|
/** Maximum length for a pledgePayment message. */
|
|
166
166
|
export const MAX_PLEDGE_PAYMENT_MESSAGE_LENGTH = 500;
|
|
167
|
-
/** Maximum length for a chat reply-to preview snippet stored on an attachment. */
|
|
168
|
-
export const MAX_CHAT_REPLY_PREVIEW_LENGTH = 280;
|
|
169
167
|
//# sourceMappingURL=business-content.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"business-content.js","sourceRoot":"","sources":["../../src/constants/business-content.ts"],"names":[],"mappings":"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","sourcesContent":["// Content-surface business-rule constants — commissions, auditions, the social\n// feed, and messaging.\nimport {\n MAX_WORK_PROJECT_TITLE_LENGTH,\n MAX_WORK_PROJECT_DESCRIPTION_LENGTH,\n MAX_CHAPTER_CONTENT_LENGTH,\n MAX_WORK_REALM_TITLE_LENGTH,\n MAX_WORK_REALM_DESCRIPTION_LENGTH,\n} from \"./business-work-project.js\";\nimport { ACTIVE_LIMITS } from './app-mode.js';\n\n/** The maximum character length for a SquareStreetz post created on behalf of a workProject. */\nexport const MAX_SQUARE_STREETZ_DESCRIPTION_LENGTH = 150;\n\n// --- Commission Board & Proposals ---\n\n/** Maximum number of open commissions a workProject can have. Mode-varied. */\nexport const MAX_COMMISSION_LISTINGS = ACTIVE_LIMITS.workProject.maxCommissionListings;\n\n/** Maximum number of proposal artisans saved to a commission. */\nexport const MAX_SAVED_PROPOSAL_ARTISANS = 5;\n\n/** Maximum length for a commission title. */\nexport const MAX_COMMISSION_TITLE_LENGTH = MAX_WORK_PROJECT_TITLE_LENGTH;\n\n/** Maximum length for a commission description / cover letter. */\nexport const MAX_COMMISSION_DESCRIPTION_LENGTH = 400;\n\n// --- Moderation text-clear + published hall-content text fields ---\n\n/**\n * Neutral placeholder written into a single cleared text field by the moderation\n * text-clear remedy. Canonical wording — the backend `runModerationClearText`\n * core writes exactly this string; a wording change is a single edit here.\n */\nexport const MODERATION_CLEAR_PLACEHOLDER =\n 'Removed by moderation — awaiting an update by the steward.';\n\n/**\n * Default REASON strings recorded on a moderation action when the admin supplies no\n * user-facing reason. Distinct from MODERATION_CLEAR_PLACEHOLDER (which is written INTO\n * cleared content fields) — these are the recorded justification text. Canonical wording;\n * consumers (resolveAdminTask's forceRetitle / chat-delete actions) never inline them.\n */\nexport const MODERATION_DEFAULT_REMOVAL_REASON = 'Removed by moderation.';\nexport const MODERATION_DEFAULT_RETITLE_REASON = 'Title/description removed by moderation.';\n\n/**\n * CANONICAL clearable text-field map for the per-field moderation TEXT-CLEAR remedy.\n * Cross-boundary single owner: the admin field-picker offers this set per surface and\n * the backend clear runner validates + normalizes caller-supplied fields against it.\n * Keys are surfaces; values are the exact document field names (NOT display labels)\n * recorded verbatim in `moderationClearedFields`. Covers every clearable surface —\n * workProject/workRealm shell metadata, hall parent details (tale/tune/television),\n * and hall sub-items (chapter/track/episode).\n */\nexport const MODERATION_CLEARABLE_TEXT_FIELDS = {\n // workProject + workRealm shell metadata\n workProject: ['workingTitle', 'workingDescription'],\n workRealm: ['workingTitle', 'workingDescription'],\n // hall content parent details\n tale: ['title', 'description'],\n tune: ['title', 'description'],\n television: ['title', 'description'],\n // hall content sub-items\n chapter: ['title', 'content'],\n tuneTrack: ['title', 'description'],\n televisionEpisode: ['title', 'description'],\n} as const satisfies Record<string, readonly string[]>;\n\n/** A surface whose text fields the moderation clear remedy can neutralize. */\nexport type ModerationClearableSurface = keyof typeof MODERATION_CLEARABLE_TEXT_FIELDS;\n\n/**\n * The DISTINCT clearable text-field NAMES across the whole hall content family (tale/tune/\n * television detail → title/description; chapter → title/content; track/episode →\n * title/description). DERIVED from the canonical MODERATION_CLEARABLE_TEXT_FIELDS map — the\n * union of every hall surface's fields — so the `clearHallContentText` callable's field-enum\n * (`HallClearFieldSchema`) never restates the `title`/`description`/`content` literals. Index\n * access on the map's readonly tuples preserves the literal types, so this stays a typed\n * `readonly ['title','description','content']` a `z.enum(...)` can consume directly.\n */\nexport const HALL_CLEARABLE_TEXT_FIELD_NAMES = [\n MODERATION_CLEARABLE_TEXT_FIELDS.tale[0], // title\n MODERATION_CLEARABLE_TEXT_FIELDS.tale[1], // description\n MODERATION_CLEARABLE_TEXT_FIELDS.chapter[1], // content\n] as const;\n\n/**\n * The raw doc field names each published hall-content surface exposes as changeable TEXT.\n * Cross-boundary: the member \"Update details\" field picker offers this set per surface and\n * the change-request submit runner validates against it. Detail surfaces (tale/tune/\n * television) live on the hall parent doc; sub-item surfaces on the published chapter/\n * track/episode doc. This is the HALL-SURFACE SUBSET of the canonical\n * MODERATION_CLEARABLE_TEXT_FIELDS above (it excludes the `workProject` shell) — every\n * tuple is projected from that one owner, so the two can never drift.\n */\nexport const HALL_CONTENT_TEXT_FIELDS = {\n tale: MODERATION_CLEARABLE_TEXT_FIELDS.tale,\n tune: MODERATION_CLEARABLE_TEXT_FIELDS.tune,\n television: MODERATION_CLEARABLE_TEXT_FIELDS.television,\n chapter: MODERATION_CLEARABLE_TEXT_FIELDS.chapter,\n tuneTrack: MODERATION_CLEARABLE_TEXT_FIELDS.tuneTrack,\n televisionEpisode: MODERATION_CLEARABLE_TEXT_FIELDS.televisionEpisode,\n // Realm grain (R1, 2026-07-12): targets the `workRealms/{id}` doc directly.\n workRealm: MODERATION_CLEARABLE_TEXT_FIELDS.workRealm,\n} as const satisfies Record<string, readonly string[]>;\n\n/** Per-field max lengths for proposed hall-content text. DERIVED from the owning\n * constants — never independent numbers — so the change-request pipeline can never\n * drift from the authoring limits again (the pre-2026-07-13 copy carried its own\n * 200/5000/100000 set while authoring enforced 150/300/2500). */\nexport const HALL_CONTENT_TEXT_FIELD_MAX = {\n title: MAX_WORK_PROJECT_TITLE_LENGTH,\n description: MAX_WORK_PROJECT_DESCRIPTION_LENGTH,\n content: MAX_CHAPTER_CONTENT_LENGTH,\n workingTitle: MAX_WORK_REALM_TITLE_LENGTH,\n workingDescription: MAX_WORK_REALM_DESCRIPTION_LENGTH,\n} as const satisfies Record<string, number>;\n\n/** Admin decision reason on a published change request (required on a deny; shown to\n * the member). One owner for the review callable schema AND the admin work-view input. */\nexport const MAX_HALL_CHANGE_REQUEST_REASON_LENGTH = 2000;\n\n// --- Real-people / parody disclaimer (R3, 2026-07-12) ---\n\n/**\n * The ONE standard platform disclaimer rendered on every published work whose\n * author attested it depicts real people (parody / satire / commentary). Two\n * layers, always shown together (DJ, 2026-07-12): the themed playbill HEADER\n * on top, the plain legal MESSAGE underneath. There is no free-text disclaimer\n * anywhere — these constants are the only wording, so a wording change is a\n * single edit here (display surfaces and any backend consumer read these; the\n * text is never persisted on docs). The MESSAGE deliberately never ADMITS the\n * work depicts real people — it hedges (\"even those based on real people\",\n * the standard film-boilerplate move) so the disclaimer never hands over the\n * depiction element of a claim. Legal wording pending counsel confirmation\n * (tracked in docs/ttt-prod-legal/).\n */\nexport const REAL_PEOPLE_DISCLAIMER_HEADER =\n 'A Notice from the Management: the faces may be familiar, but the players are pure ' +\n 'invention — parody and satire, in the grand old tradition of the stage.';\n\nexport const REAL_PEOPLE_DISCLAIMER_MESSAGE =\n 'All characters, statements, and events in this work, even those based on real people, ' +\n 'are entirely fictional and are presented as parody, satire, or commentary. Any voices, ' +\n 'likenesses, or portrayals of real people are impersonated or fictionalized, and nothing ' +\n 'in this work should be understood as a statement of fact about, or as speech by, any ' +\n 'real person. This work is not created by, affiliated with, sponsored by, or endorsed by ' +\n 'any real person portrayed or referenced in it.';\n\n// --- Hall library per-user viewing-state doc (hall-viewing-experience Area 2, ruled 2026-07-04) ---\n\n/**\n * Caps for the per-user Hall viewing-state doc (`HallLibraryPreferencesSchema`,\n * `userProfiles/{uid}/privateData/hallLibraryPreferences`). Every list on that doc is\n * capped for launch — no unbounded per-user lists. `hiddenWorkIds`/`inkedWorkIds` are\n * oldest-pruned (or the write is rejected with a friendly message once full);\n * `inProgress` is LRU-pruned by `updatedAt`; `recentlyViewed` is capped, newest-kept.\n * Enforcement lives in the backend core (`runX`) that owns this doc — this is the\n * shared source of truth for the cap values themselves.\n */\nexport const HALL_LIBRARY_PREFS_CAPS = {\n hiddenWorkIds: 200,\n inkedWorkIds: 200,\n inProgress: 50,\n recentlyViewed: 20,\n} as const satisfies Record<string, number>;\n\n// --- Auditions ---\n\n/** Maximum length for an audition title. */\nexport const MAX_AUDITION_TITLE_LENGTH = 150;\n\n/** Curated-audition option-video batch bounds (the fixed 2..8 option count carried\n * from the Create click through targetInfo/upload-variables to the create core's\n * re-check). ONE declaration — every `.min()/.max()` derives from these. */\nexport const MIN_CURATED_AUDITION_OPTIONS = 2;\nexport const MAX_CURATED_AUDITION_OPTIONS = 8;\n\n/** Maximum length for an audition description. */\nexport const MAX_AUDITION_DESCRIPTION_LENGTH = 1000;\n\n/**\n * Maximum sponsored-audition payout amount in whole USD accepted at the upload\n * trust boundary. Mirrors MAX_PLEDGE_PAYMENT_AMOUNT_CENTS ($500,000) expressed\n * in dollars — a finite ceiling that rejects absurd/garbage amounts before any\n * downstream processing.\n */\nexport const MAX_SPONSORED_AUDITION_AMOUNT_USD = 500_000;\n\n// --- SquareStreetz (Social Feed) ---\n\n/** Maximum length for a SquareStreetz post. */\nexport const MAX_POST_LENGTH = 500;\n\n/** Maximum number of mentions allowed in a single SquareStreetz post. */\nexport const MAX_MENTIONS = 3;\n\n/** Maximum characters of a mention's display name shown before truncation. */\nexport const MAX_MENTION_DISPLAY_LENGTH = 30;\n\n// --- Messages & Invites ---\n\n/** Maximum length for a guild-invite message. */\nexport const MAX_GUILD_INVITE_MESSAGE_LENGTH = 500;\n\n/** Maximum length for a pledgePayment message. */\nexport const MAX_PLEDGE_PAYMENT_MESSAGE_LENGTH = 500;\n\n/** Maximum length for a chat reply-to preview snippet stored on an attachment. */\nexport const MAX_CHAT_REPLY_PREVIEW_LENGTH = 280;\n"]}
|
|
1
|
+
{"version":3,"file":"business-content.js","sourceRoot":"","sources":["../../src/constants/business-content.ts"],"names":[],"mappings":"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","sourcesContent":["// Content-surface business-rule constants — commissions, auditions, the social\n// feed, and messaging.\nimport {\n MAX_WORK_PROJECT_TITLE_LENGTH,\n MAX_WORK_PROJECT_DESCRIPTION_LENGTH,\n MAX_CHAPTER_CONTENT_LENGTH,\n MAX_WORK_REALM_TITLE_LENGTH,\n MAX_WORK_REALM_DESCRIPTION_LENGTH,\n} from \"./business-work-project.js\";\nimport { ACTIVE_LIMITS } from './app-mode.js';\n\n/** The maximum character length for a SquareStreetz post created on behalf of a workProject. */\nexport const MAX_SQUARE_STREETZ_DESCRIPTION_LENGTH = 150;\n\n// --- Commission Board & Proposals ---\n\n/** Maximum number of open commissions a workProject can have. Mode-varied. */\nexport const MAX_COMMISSION_LISTINGS = ACTIVE_LIMITS.workProject.maxCommissionListings;\n\n/** Maximum number of proposal artisans saved to a commission. */\nexport const MAX_SAVED_PROPOSAL_ARTISANS = 5;\n\n/** Maximum length for a commission title. */\nexport const MAX_COMMISSION_TITLE_LENGTH = MAX_WORK_PROJECT_TITLE_LENGTH;\n\n/** Maximum length for a commission description / cover letter. */\nexport const MAX_COMMISSION_DESCRIPTION_LENGTH = 400;\n\n// --- Moderation text-clear + published hall-content text fields ---\n\n/**\n * Neutral placeholder written into a single cleared text field by the moderation\n * text-clear remedy. Canonical wording — the backend `runModerationClearText`\n * core writes exactly this string; a wording change is a single edit here.\n */\nexport const MODERATION_CLEAR_PLACEHOLDER =\n 'Removed by moderation — awaiting an update by the steward.';\n\n/**\n * Default REASON strings recorded on a moderation action when the admin supplies no\n * user-facing reason. Distinct from MODERATION_CLEAR_PLACEHOLDER (which is written INTO\n * cleared content fields) — these are the recorded justification text. Canonical wording;\n * consumers (resolveAdminTask's forceRetitle / chat-delete actions) never inline them.\n */\nexport const MODERATION_DEFAULT_REMOVAL_REASON = 'Removed by moderation.';\nexport const MODERATION_DEFAULT_RETITLE_REASON = 'Title/description removed by moderation.';\n\n/**\n * CANONICAL clearable text-field map for the per-field moderation TEXT-CLEAR remedy.\n * Cross-boundary single owner: the admin field-picker offers this set per surface and\n * the backend clear runner validates + normalizes caller-supplied fields against it.\n * Keys are surfaces; values are the exact document field names (NOT display labels)\n * recorded verbatim in `moderationClearedFields`. Covers every clearable surface —\n * workProject/workRealm shell metadata, hall parent details (tale/tune/television),\n * and hall sub-items (chapter/track/episode).\n */\nexport const MODERATION_CLEARABLE_TEXT_FIELDS = {\n // workProject + workRealm shell metadata\n workProject: ['workingTitle', 'workingDescription'],\n workRealm: ['workingTitle', 'workingDescription'],\n // hall content parent details\n tale: ['title', 'description'],\n tune: ['title', 'description'],\n television: ['title', 'description'],\n // hall content sub-items\n chapter: ['title', 'content'],\n tuneTrack: ['title', 'description'],\n televisionEpisode: ['title', 'description'],\n} as const satisfies Record<string, readonly string[]>;\n\n/** A surface whose text fields the moderation clear remedy can neutralize. */\nexport type ModerationClearableSurface = keyof typeof MODERATION_CLEARABLE_TEXT_FIELDS;\n\n/**\n * The DISTINCT clearable text-field NAMES across the whole hall content family (tale/tune/\n * television detail → title/description; chapter → title/content; track/episode →\n * title/description). DERIVED from the canonical MODERATION_CLEARABLE_TEXT_FIELDS map — the\n * union of every hall surface's fields — so the `clearHallContentText` callable's field-enum\n * (`HallClearFieldSchema`) never restates the `title`/`description`/`content` literals. Index\n * access on the map's readonly tuples preserves the literal types, so this stays a typed\n * `readonly ['title','description','content']` a `z.enum(...)` can consume directly.\n */\nexport const HALL_CLEARABLE_TEXT_FIELD_NAMES = [\n MODERATION_CLEARABLE_TEXT_FIELDS.tale[0], // title\n MODERATION_CLEARABLE_TEXT_FIELDS.tale[1], // description\n MODERATION_CLEARABLE_TEXT_FIELDS.chapter[1], // content\n] as const;\n\n/**\n * The raw doc field names each published hall-content surface exposes as changeable TEXT.\n * Cross-boundary: the member \"Update details\" field picker offers this set per surface and\n * the change-request submit runner validates against it. Detail surfaces (tale/tune/\n * television) live on the hall parent doc; sub-item surfaces on the published chapter/\n * track/episode doc. This is the HALL-SURFACE SUBSET of the canonical\n * MODERATION_CLEARABLE_TEXT_FIELDS above (it excludes the `workProject` shell) — every\n * tuple is projected from that one owner, so the two can never drift.\n */\nexport const HALL_CONTENT_TEXT_FIELDS = {\n tale: MODERATION_CLEARABLE_TEXT_FIELDS.tale,\n tune: MODERATION_CLEARABLE_TEXT_FIELDS.tune,\n television: MODERATION_CLEARABLE_TEXT_FIELDS.television,\n chapter: MODERATION_CLEARABLE_TEXT_FIELDS.chapter,\n tuneTrack: MODERATION_CLEARABLE_TEXT_FIELDS.tuneTrack,\n televisionEpisode: MODERATION_CLEARABLE_TEXT_FIELDS.televisionEpisode,\n // Realm grain (R1, 2026-07-12): targets the `workRealms/{id}` doc directly.\n workRealm: MODERATION_CLEARABLE_TEXT_FIELDS.workRealm,\n} as const satisfies Record<string, readonly string[]>;\n\n/** Per-field max lengths for proposed hall-content text. DERIVED from the owning\n * constants — never independent numbers — so the change-request pipeline can never\n * drift from the authoring limits again (the pre-2026-07-13 copy carried its own\n * 200/5000/100000 set while authoring enforced 150/300/2500). */\nexport const HALL_CONTENT_TEXT_FIELD_MAX = {\n title: MAX_WORK_PROJECT_TITLE_LENGTH,\n description: MAX_WORK_PROJECT_DESCRIPTION_LENGTH,\n content: MAX_CHAPTER_CONTENT_LENGTH,\n workingTitle: MAX_WORK_REALM_TITLE_LENGTH,\n workingDescription: MAX_WORK_REALM_DESCRIPTION_LENGTH,\n} as const satisfies Record<string, number>;\n\n/** Admin decision reason on a published change request (required on a deny; shown to\n * the member). One owner for the review callable schema AND the admin work-view input. */\nexport const MAX_HALL_CHANGE_REQUEST_REASON_LENGTH = 2000;\n\n// --- Real-people / parody disclaimer (R3, 2026-07-12) ---\n\n/**\n * The ONE standard platform disclaimer rendered on every published work whose\n * author attested it depicts real people (parody / satire / commentary). Two\n * layers, always shown together (DJ, 2026-07-12): the themed playbill HEADER\n * on top, the plain legal MESSAGE underneath. There is no free-text disclaimer\n * anywhere — these constants are the only wording, so a wording change is a\n * single edit here (display surfaces and any backend consumer read these; the\n * text is never persisted on docs). The MESSAGE deliberately never ADMITS the\n * work depicts real people — it hedges (\"even those based on real people\",\n * the standard film-boilerplate move) so the disclaimer never hands over the\n * depiction element of a claim. Legal wording pending counsel confirmation\n * (tracked in docs/ttt-prod-legal/).\n */\nexport const REAL_PEOPLE_DISCLAIMER_HEADER =\n 'A Notice from the Management: the faces may be familiar, but the players are pure ' +\n 'invention — parody and satire, in the grand old tradition of the stage.';\n\nexport const REAL_PEOPLE_DISCLAIMER_MESSAGE =\n 'All characters, statements, and events in this work, even those based on real people, ' +\n 'are entirely fictional and are presented as parody, satire, or commentary. Any voices, ' +\n 'likenesses, or portrayals of real people are impersonated or fictionalized, and nothing ' +\n 'in this work should be understood as a statement of fact about, or as speech by, any ' +\n 'real person. This work is not created by, affiliated with, sponsored by, or endorsed by ' +\n 'any real person portrayed or referenced in it.';\n\n// --- Hall library per-user viewing-state doc (hall-viewing-experience Area 2, ruled 2026-07-04) ---\n\n/**\n * Caps for the per-user Hall viewing-state doc (`HallLibraryPreferencesSchema`,\n * `userProfiles/{uid}/privateData/hallLibraryPreferences`). Every list on that doc is\n * capped for launch — no unbounded per-user lists. `hiddenWorkIds`/`inkedWorkIds` are\n * oldest-pruned (or the write is rejected with a friendly message once full);\n * `inProgress` is LRU-pruned by `updatedAt`; `recentlyViewed` is capped, newest-kept.\n * Enforcement lives in the backend core (`runX`) that owns this doc — this is the\n * shared source of truth for the cap values themselves.\n */\nexport const HALL_LIBRARY_PREFS_CAPS = {\n hiddenWorkIds: 200,\n inkedWorkIds: 200,\n inProgress: 50,\n recentlyViewed: 20,\n} as const satisfies Record<string, number>;\n\n// --- Auditions ---\n\n/** Maximum length for an audition title. */\nexport const MAX_AUDITION_TITLE_LENGTH = 150;\n\n/** Curated-audition option-video batch bounds (the fixed 2..8 option count carried\n * from the Create click through targetInfo/upload-variables to the create core's\n * re-check). ONE declaration — every `.min()/.max()` derives from these. */\nexport const MIN_CURATED_AUDITION_OPTIONS = 2;\nexport const MAX_CURATED_AUDITION_OPTIONS = 8;\n\n/** Maximum length for an audition description. */\nexport const MAX_AUDITION_DESCRIPTION_LENGTH = 1000;\n\n/**\n * Maximum sponsored-audition payout amount in whole USD accepted at the upload\n * trust boundary. Mirrors MAX_PLEDGE_PAYMENT_AMOUNT_CENTS ($500,000) expressed\n * in dollars — a finite ceiling that rejects absurd/garbage amounts before any\n * downstream processing.\n */\nexport const MAX_SPONSORED_AUDITION_AMOUNT_USD = 500_000;\n\n// --- SquareStreetz (Social Feed) ---\n\n/** Maximum length for a SquareStreetz post. */\nexport const MAX_POST_LENGTH = 500;\n\n/** Maximum number of mentions allowed in a single SquareStreetz post. */\nexport const MAX_MENTIONS = 3;\n\n/** Maximum characters of a mention's display name shown before truncation. */\nexport const MAX_MENTION_DISPLAY_LENGTH = 30;\n\n// --- Messages & Invites ---\n\n/** Maximum length for a guild-invite message. */\nexport const MAX_GUILD_INVITE_MESSAGE_LENGTH = 500;\n\n/** Maximum length for a pledgePayment message. */\nexport const MAX_PLEDGE_PAYMENT_MESSAGE_LENGTH = 500;\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Published active Conversation Files allowed in ONE conversation.
|
|
2
|
+
* Mode-varied: charter 10 / full 20 (DJ ruling 2026-07-25). */
|
|
3
|
+
export declare const MAX_CONVERSATION_FILES: number;
|
|
4
|
+
/** Published STORED-OUTPUT bytes allowed in ONE conversation.
|
|
5
|
+
* Mode-varied: charter 500 MiB / full 1 GiB (DJ ruling 2026-07-25). */
|
|
6
|
+
export declare const MAX_CONVERSATION_FILE_STORAGE_BYTES: number;
|
|
7
|
+
//# sourceMappingURL=conversation-files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-files.d.ts","sourceRoot":"","sources":["../../src/constants/conversation-files.ts"],"names":[],"mappings":"AASA;gEACgE;AAChE,eAAO,MAAM,sBAAsB,QAAkD,CAAC;AAEtF;wEACwE;AACxE,eAAO,MAAM,mCAAmC,QACY,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Conversation Files limits — the derived enforcement values for the flat,
|
|
2
|
+
// Firestore-owned file list on a guild-invite conversation or an admin-support
|
|
3
|
+
// dispatch thread. The mode-varied source of truth is `ACTIVE_LIMITS.conversation`
|
|
4
|
+
// (constants/app-mode.ts); every enforcement point (startUpload's quota
|
|
5
|
+
// reservation, the publication transfer, Firestore rules mirroring, and the
|
|
6
|
+
// Conversation Files panel's usage line) DERIVES from these — never a literal.
|
|
7
|
+
import { ACTIVE_LIMITS } from './app-mode.js';
|
|
8
|
+
/** Published active Conversation Files allowed in ONE conversation.
|
|
9
|
+
* Mode-varied: charter 10 / full 20 (DJ ruling 2026-07-25). */
|
|
10
|
+
export const MAX_CONVERSATION_FILES = ACTIVE_LIMITS.conversation.maxConversationFiles;
|
|
11
|
+
/** Published STORED-OUTPUT bytes allowed in ONE conversation.
|
|
12
|
+
* Mode-varied: charter 500 MiB / full 1 GiB (DJ ruling 2026-07-25). */
|
|
13
|
+
export const MAX_CONVERSATION_FILE_STORAGE_BYTES = ACTIVE_LIMITS.conversation.maxConversationFileStorageBytes;
|
|
14
|
+
//# sourceMappingURL=conversation-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-files.js","sourceRoot":"","sources":["../../src/constants/conversation-files.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,+EAA+E;AAC/E,mFAAmF;AACnF,wEAAwE;AACxE,4EAA4E;AAC5E,+EAA+E;AAE/E,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C;gEACgE;AAChE,MAAM,CAAC,MAAM,sBAAsB,GAAG,aAAa,CAAC,YAAY,CAAC,oBAAoB,CAAC;AAEtF;wEACwE;AACxE,MAAM,CAAC,MAAM,mCAAmC,GAC9C,aAAa,CAAC,YAAY,CAAC,+BAA+B,CAAC","sourcesContent":["// Conversation Files limits — the derived enforcement values for the flat,\n// Firestore-owned file list on a guild-invite conversation or an admin-support\n// dispatch thread. The mode-varied source of truth is `ACTIVE_LIMITS.conversation`\n// (constants/app-mode.ts); every enforcement point (startUpload's quota\n// reservation, the publication transfer, Firestore rules mirroring, and the\n// Conversation Files panel's usage line) DERIVES from these — never a literal.\n\nimport { ACTIVE_LIMITS } from './app-mode.js';\n\n/** Published active Conversation Files allowed in ONE conversation.\n * Mode-varied: charter 10 / full 20 (DJ ruling 2026-07-25). */\nexport const MAX_CONVERSATION_FILES = ACTIVE_LIMITS.conversation.maxConversationFiles;\n\n/** Published STORED-OUTPUT bytes allowed in ONE conversation.\n * Mode-varied: charter 500 MiB / full 1 GiB (DJ ruling 2026-07-25). */\nexport const MAX_CONVERSATION_FILE_STORAGE_BYTES =\n ACTIVE_LIMITS.conversation.maxConversationFileStorageBytes;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC"}
|
package/dist/constants/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC","sourcesContent":["export * from './app-mode.js';\nexport * from './business.js';\nexport * from './chat.js';\nexport * from './moderation.js';\nexport * from './options.js';\nexport * from './admin-labels.js';\nexport * from './craft-skill-statements.js';\nexport * from './publish-attestations.js';\nexport * from './safety-confirmation-phrases.js';\nexport * from './safety-telemetry-patterns.js';\nexport * from './pagination.js';\nexport * from './release-flags.js';\nexport * from './retention.js';\nexport * from './scheduled-jobs.js';\nexport * from './media-processing.js';\nexport * from './storage-keys.js';\nexport * from './company-mascots.js';\nexport * from './center-stage-rooms.js';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,mBAAmB,CAAC;AAClC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,yBAAyB,CAAC","sourcesContent":["export * from './app-mode.js';\nexport * from './business.js';\nexport * from './chat.js';\nexport * from './conversation-files.js';\nexport * from './moderation.js';\nexport * from './options.js';\nexport * from './admin-labels.js';\nexport * from './craft-skill-statements.js';\nexport * from './publish-attestations.js';\nexport * from './safety-confirmation-phrases.js';\nexport * from './safety-telemetry-patterns.js';\nexport * from './pagination.js';\nexport * from './release-flags.js';\nexport * from './retention.js';\nexport * from './scheduled-jobs.js';\nexport * from './media-processing.js';\nexport * from './storage-keys.js';\nexport * from './company-mascots.js';\nexport * from './center-stage-rooms.js';\n"]}
|
|
@@ -49,7 +49,6 @@ export declare const ChatSyncEventSchema: z.ZodObject<{
|
|
|
49
49
|
config: "config";
|
|
50
50
|
channelAuth: "channelAuth";
|
|
51
51
|
accountAccess: "accountAccess";
|
|
52
|
-
attachmentFlip: "attachmentFlip";
|
|
53
52
|
serverMessage: "serverMessage";
|
|
54
53
|
}>;
|
|
55
54
|
version: z.ZodNumber;
|
|
@@ -108,7 +107,6 @@ export declare const ChatMessageOutboxSchema: z.ZodObject<{
|
|
|
108
107
|
kind: z.ZodEnum<{
|
|
109
108
|
userMsg: "userMsg";
|
|
110
109
|
systemMsg: "systemMsg";
|
|
111
|
-
attachmentPlaceholder: "attachmentPlaceholder";
|
|
112
110
|
}>;
|
|
113
111
|
threadRef: z.ZodString;
|
|
114
112
|
payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
@@ -147,7 +145,6 @@ export declare const ChatAdminActionCommandSchema: z.ZodObject<{
|
|
|
147
145
|
caseId: z.ZodString;
|
|
148
146
|
reason: z.ZodString;
|
|
149
147
|
expectedMessageRevision: z.ZodNumber;
|
|
150
|
-
attachmentAssetIds: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
151
148
|
payloadHash: z.ZodString;
|
|
152
149
|
state: z.ZodEnum<{
|
|
153
150
|
failed: "failed";
|
|
@@ -161,7 +158,6 @@ export declare const ChatAdminActionCommandSchema: z.ZodObject<{
|
|
|
161
158
|
lastError: z.ZodNullable<z.ZodString>;
|
|
162
159
|
result: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
163
160
|
doRevisionId: z.ZodNullable<z.ZodString>;
|
|
164
|
-
attachmentBlocked: z.ZodDefault<z.ZodBoolean>;
|
|
165
161
|
terminalFailureGeneration: z.ZodNumber;
|
|
166
162
|
createdAt: z.ZodNumber;
|
|
167
163
|
appliedAt: z.ZodNullable<z.ZodNumber>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-sync.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/chat-sync.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;iBAW1C,CAAC;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AAIxF,eAAO,MAAM,uBAAuB;;;;;;;;;;;;iBAUlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,eAAO,MAAM,4BAA4B;;;;;;;;iBAKvC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAGlF,eAAO,MAAM,mBAAmB
|
|
1
|
+
{"version":3,"file":"chat-sync.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/chat-sync.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,eAAO,MAAM,+BAA+B;;;;;;;;;;;;;;;;;iBAW1C,CAAC;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AAIxF,eAAO,MAAM,uBAAuB;;;;;;;;;;;;iBAUlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,eAAO,MAAM,4BAA4B;;;;;;;;iBAKvC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAGlF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;iBAiB9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAGhE,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmBlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAGxE,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;iBAclC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAKxE,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0BvC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAgBlF,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAsB5C,CAAC;AACH,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAC;AAK5F,eAAO,MAAM,2CAA2C;;;;;;;;;;;;;;iBAQtD,CAAC;AACH,MAAM,MAAM,qCAAqC,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2CAA2C,CAAC,CAAC"}
|
|
@@ -46,7 +46,7 @@ export const ChatScopeDegradedCauseSchema = z.object({
|
|
|
46
46
|
export const ChatSyncEventSchema = z.object({
|
|
47
47
|
eventId: z.string(),
|
|
48
48
|
targetDo: z.string(),
|
|
49
|
-
kind: z.enum(['channelAuth', 'accountAccess', 'config', '
|
|
49
|
+
kind: z.enum(['channelAuth', 'accountAccess', 'config', 'serverMessage']),
|
|
50
50
|
version: z.number(),
|
|
51
51
|
payload: z.record(z.string(), z.unknown()).nullable(),
|
|
52
52
|
tombstone: z.boolean().optional(),
|
|
@@ -85,7 +85,7 @@ export const ChatSyncFanoutJobSchema = z.object({
|
|
|
85
85
|
// ── chatMessageOutbox/{commandId} ───────────────────────────────────────────
|
|
86
86
|
export const ChatMessageOutboxSchema = z.object({
|
|
87
87
|
commandId: z.string(),
|
|
88
|
-
kind: z.enum(['userMsg', 'systemMsg'
|
|
88
|
+
kind: z.enum(['userMsg', 'systemMsg']),
|
|
89
89
|
threadRef: z.string(),
|
|
90
90
|
payload: z.record(z.string(), z.unknown()),
|
|
91
91
|
payloadVersion: z.number(),
|
|
@@ -112,11 +112,6 @@ export const ChatAdminActionCommandSchema = z.object({
|
|
|
112
112
|
caseId: z.string(),
|
|
113
113
|
reason: z.string(),
|
|
114
114
|
expectedMessageRevision: z.number(),
|
|
115
|
-
// Ready-attachment media asset id(s) on the moderated message (block FIRST, then
|
|
116
|
-
// DO tombstone — the attachment-redaction saga, round-10 blocker 9). Empty for a
|
|
117
|
-
// text-only message. DERIVED SERVER-SIDE inside the moderation saga from the DO/message
|
|
118
|
-
// context — NEVER client-supplied (the case-bound context read does not expose them).
|
|
119
|
-
attachmentAssetIds: z.array(z.string()).default([]),
|
|
120
115
|
payloadHash: z.string(),
|
|
121
116
|
state: z.enum(['queued', 'delivering', 'applied', 'failed', 'deadLetter']),
|
|
122
117
|
attemptCount: z.number(),
|
|
@@ -124,8 +119,6 @@ export const ChatAdminActionCommandSchema = z.object({
|
|
|
124
119
|
lastError: z.string().nullable(),
|
|
125
120
|
result: z.record(z.string(), z.unknown()).nullable(),
|
|
126
121
|
doRevisionId: z.string().nullable(),
|
|
127
|
-
// True once the redaction saga has blocked the attachment asset(s) for this command.
|
|
128
|
-
attachmentBlocked: z.boolean().default(false),
|
|
129
122
|
terminalFailureGeneration: z.number(),
|
|
130
123
|
createdAt: z.number(),
|
|
131
124
|
appliedAt: z.number().nullable(),
|