@ttt-productions/ttt-core 0.79.18 → 0.79.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants/business-work-project.d.ts +17 -0
- package/dist/constants/business-work-project.d.ts.map +1 -1
- package/dist/constants/business-work-project.js +17 -0
- package/dist/constants/business-work-project.js.map +1 -1
- package/dist/constants/pagination.d.ts +13 -0
- package/dist/constants/pagination.d.ts.map +1 -1
- package/dist/constants/pagination.js +13 -0
- package/dist/constants/pagination.js.map +1 -1
- package/dist/constants/storage-keys.d.ts +7 -0
- package/dist/constants/storage-keys.d.ts.map +1 -1
- package/dist/constants/storage-keys.js +21 -0
- package/dist/constants/storage-keys.js.map +1 -1
- package/dist/doc-schemas/media-activation-jobs.d.ts +2 -0
- package/dist/doc-schemas/media-activation-jobs.d.ts.map +1 -1
- package/dist/doc-schemas/media-activation-jobs.js +21 -0
- package/dist/doc-schemas/media-activation-jobs.js.map +1 -1
- package/dist/doc-schemas/media-assets.d.ts +21 -0
- package/dist/doc-schemas/media-assets.d.ts.map +1 -1
- package/dist/doc-schemas/media-assets.js +108 -10
- package/dist/doc-schemas/media-assets.js.map +1 -1
- package/dist/doc-schemas/registry.d.ts +18 -0
- package/dist/doc-schemas/registry.d.ts.map +1 -1
- package/dist/doc-schemas/registry.js +4 -1
- package/dist/doc-schemas/registry.js.map +1 -1
- package/dist/doc-schemas/user.d.ts.map +1 -1
- package/dist/doc-schemas/user.js +2 -1
- package/dist/doc-schemas/user.js.map +1 -1
- package/dist/doc-schemas/work-project.d.ts +13 -0
- package/dist/doc-schemas/work-project.d.ts.map +1 -1
- package/dist/doc-schemas/work-project.js +36 -0
- package/dist/doc-schemas/work-project.js.map +1 -1
- package/dist/notifications/index.d.ts.map +1 -1
- package/dist/notifications/index.js +41 -0
- package/dist/notifications/index.js.map +1 -1
- package/dist/paths/collection-refs.d.ts +1 -0
- package/dist/paths/collection-refs.d.ts.map +1 -1
- package/dist/paths/collection-refs.js +5 -1
- package/dist/paths/collection-refs.js.map +1 -1
- package/dist/paths/collections.d.ts +7 -0
- package/dist/paths/collections.d.ts.map +1 -1
- package/dist/paths/collections.js +10 -0
- package/dist/paths/collections.js.map +1 -1
- package/dist/paths/path-builders.d.ts +1 -0
- package/dist/paths/path-builders.d.ts.map +1 -1
- package/dist/paths/path-builders.js +4 -1
- package/dist/paths/path-builders.js.map +1 -1
- package/dist/permissions/work-project-permissions-data.d.ts +1 -1
- package/dist/permissions/work-project-permissions-data.d.ts.map +1 -1
- package/dist/permissions/work-project-permissions-data.js +5 -3
- package/dist/permissions/work-project-permissions-data.js.map +1 -1
- package/dist/schemas/atoms.d.ts +17 -0
- package/dist/schemas/atoms.d.ts.map +1 -1
- package/dist/schemas/atoms.js +17 -0
- package/dist/schemas/atoms.js.map +1 -1
- package/dist/schemas/notification.d.ts +23 -1
- package/dist/schemas/notification.d.ts.map +1 -1
- package/dist/schemas/notification.js +41 -2
- package/dist/schemas/notification.js.map +1 -1
- package/dist/schemas/users.d.ts +22 -0
- package/dist/schemas/users.d.ts.map +1 -1
- package/dist/schemas/users.js +53 -2
- package/dist/schemas/users.js.map +1 -1
- package/dist/schemas/work-project-management.d.ts +151 -1
- package/dist/schemas/work-project-management.d.ts.map +1 -1
- package/dist/schemas/work-project-management.js +173 -17
- package/dist/schemas/work-project-management.js.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 +1 -1
|
@@ -22,6 +22,23 @@ export declare const MAX_FILE_FOLDERS: number;
|
|
|
22
22
|
export declare const MAX_WORK_FILES: number;
|
|
23
23
|
/** Maximum total file-storage bytes per workProject. Mode-varied. */
|
|
24
24
|
export declare const MAX_WORK_FILE_STORAGE_BYTES: number;
|
|
25
|
+
/**
|
|
26
|
+
* Maximum number of shared-file folders a Realm steward may create
|
|
27
|
+
* (`workRealms/{workRealmId}/realmFileFolders`).
|
|
28
|
+
*
|
|
29
|
+
* Bounded on purpose: the folder collection is read WHOLE by the gallery projection, by the
|
|
30
|
+
* folder-cap check, and by the case-insensitive name-uniqueness check, so an unbounded
|
|
31
|
+
* collection would turn each of those into an unbounded read. 30 is generous for organizing
|
|
32
|
+
* one Realm's shared pool (Realm folders have no access lists — they are purely
|
|
33
|
+
* organizational) while keeping every one of those reads a single bounded page.
|
|
34
|
+
*
|
|
35
|
+
* NOT mode-varied: unlike the Work-side caps this is an organizational bound on steward
|
|
36
|
+
* housekeeping, not a charter-vs-full consumption allowance.
|
|
37
|
+
*
|
|
38
|
+
* Realm folder NAMES reuse MAX_FILE_FOLDER_NAME_LENGTH above — one folder-name rule
|
|
39
|
+
* platform-wide; there is deliberately no second realm-specific length.
|
|
40
|
+
*/
|
|
41
|
+
export declare const MAX_REALM_FILE_FOLDERS = 30;
|
|
25
42
|
/** Allowed characters in titles: letters, numbers, spaces. */
|
|
26
43
|
export declare const TITLE_PATTERN: RegExp;
|
|
27
44
|
/** Maximum number of auditions a single workProject can have open at once. Mode-varied. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"business-work-project.d.ts","sourceRoot":"","sources":["../../src/constants/business-work-project.ts"],"names":[],"mappings":"AAGA,oEAAoE;AACpE,eAAO,MAAM,6BAA6B,OAAO,CAAC;AAElD,yEAAyE;AACzE,eAAO,MAAM,cAAc,QAAyC,CAAC;AAErE;;;GAGG;AACH,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAI9C,8CAA8C;AAC9C,eAAO,MAAM,6BAA6B,MAAM,CAAC;AAEjD;uFACuF;AACvF,eAAO,MAAM,mCAAmC,OAAO,CAAC;AAOxD,eAAO,MAAM,2BAA2B,MAAgC,CAAC;AACzE,eAAO,MAAM,iCAAiC,OAAsC,CAAC;AAErF,0DAA0D;AAC1D,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAE/C,mEAAmE;AACnE,eAAO,MAAM,gBAAgB,QAA2C,CAAC;AAEzE,2EAA2E;AAC3E,eAAO,MAAM,cAAc,QAAyC,CAAC;AAErE,qEAAqE;AACrE,eAAO,MAAM,2BAA2B,QAAoD,CAAC;AAE7F,8DAA8D;AAC9D,eAAO,MAAM,aAAa,QAAoB,CAAC;AAE/C,2FAA2F;AAC3F,eAAO,MAAM,0BAA0B,QAAoD,CAAC;AAK5F,eAAO,MAAM,qBAAqB,MAAgC,CAAC;AACnE,eAAO,MAAM,2BAA2B,OAAsC,CAAC;AAE/E,eAAO,MAAM,qBAAqB,MAAgC,CAAC;AACnE,eAAO,MAAM,2BAA2B,OAAsC,CAAC;AAE/E,eAAO,MAAM,2BAA2B,MAAgC,CAAC;AACzE,eAAO,MAAM,iCAAiC,OAAsC,CAAC;AAErF,+DAA+D;AAC/D,eAAO,MAAM,YAAY,QAAwC,CAAC;AAElE,0CAA0C;AAC1C,eAAO,MAAM,wBAAwB,MAAgC,CAAC;AAEtE;wFACwF;AACxF,eAAO,MAAM,0BAA0B,QAAoD,CAAC;AAE5F,qFAAqF;AACrF,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAE1C,0EAA0E;AAC1E,eAAO,MAAM,eAAe,QAA0C,CAAC;AAEvE,wCAAwC;AACxC,eAAO,MAAM,2BAA2B,MAAgC,CAAC;AAEzE,8CAA8C;AAC9C,eAAO,MAAM,iCAAiC,OAAsC,CAAC;AAErF,iFAAiF;AACjF,eAAO,MAAM,uBAAuB,QAAkD,CAAC;AAEvF,2CAA2C;AAC3C,eAAO,MAAM,mCAAmC,MAAgC,CAAC;AAEjF,iDAAiD;AACjD,eAAO,MAAM,yCAAyC,OAAsC,CAAC"}
|
|
1
|
+
{"version":3,"file":"business-work-project.d.ts","sourceRoot":"","sources":["../../src/constants/business-work-project.ts"],"names":[],"mappings":"AAGA,oEAAoE;AACpE,eAAO,MAAM,6BAA6B,OAAO,CAAC;AAElD,yEAAyE;AACzE,eAAO,MAAM,cAAc,QAAyC,CAAC;AAErE;;;GAGG;AACH,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAI9C,8CAA8C;AAC9C,eAAO,MAAM,6BAA6B,MAAM,CAAC;AAEjD;uFACuF;AACvF,eAAO,MAAM,mCAAmC,OAAO,CAAC;AAOxD,eAAO,MAAM,2BAA2B,MAAgC,CAAC;AACzE,eAAO,MAAM,iCAAiC,OAAsC,CAAC;AAErF,0DAA0D;AAC1D,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAE/C,mEAAmE;AACnE,eAAO,MAAM,gBAAgB,QAA2C,CAAC;AAEzE,2EAA2E;AAC3E,eAAO,MAAM,cAAc,QAAyC,CAAC;AAErE,qEAAqE;AACrE,eAAO,MAAM,2BAA2B,QAAoD,CAAC;AAE7F;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC,8DAA8D;AAC9D,eAAO,MAAM,aAAa,QAAoB,CAAC;AAE/C,2FAA2F;AAC3F,eAAO,MAAM,0BAA0B,QAAoD,CAAC;AAK5F,eAAO,MAAM,qBAAqB,MAAgC,CAAC;AACnE,eAAO,MAAM,2BAA2B,OAAsC,CAAC;AAE/E,eAAO,MAAM,qBAAqB,MAAgC,CAAC;AACnE,eAAO,MAAM,2BAA2B,OAAsC,CAAC;AAE/E,eAAO,MAAM,2BAA2B,MAAgC,CAAC;AACzE,eAAO,MAAM,iCAAiC,OAAsC,CAAC;AAErF,+DAA+D;AAC/D,eAAO,MAAM,YAAY,QAAwC,CAAC;AAElE,0CAA0C;AAC1C,eAAO,MAAM,wBAAwB,MAAgC,CAAC;AAEtE;wFACwF;AACxF,eAAO,MAAM,0BAA0B,QAAoD,CAAC;AAE5F,qFAAqF;AACrF,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAE1C,0EAA0E;AAC1E,eAAO,MAAM,eAAe,QAA0C,CAAC;AAEvE,wCAAwC;AACxC,eAAO,MAAM,2BAA2B,MAAgC,CAAC;AAEzE,8CAA8C;AAC9C,eAAO,MAAM,iCAAiC,OAAsC,CAAC;AAErF,iFAAiF;AACjF,eAAO,MAAM,uBAAuB,QAAkD,CAAC;AAEvF,2CAA2C;AAC3C,eAAO,MAAM,mCAAmC,MAAgC,CAAC;AAEjF,iDAAiD;AACjD,eAAO,MAAM,yCAAyC,OAAsC,CAAC"}
|
|
@@ -29,6 +29,23 @@ export const MAX_FILE_FOLDERS = ACTIVE_LIMITS.workProject.maxFileFolders;
|
|
|
29
29
|
export const MAX_WORK_FILES = ACTIVE_LIMITS.workProject.maxWorkFiles;
|
|
30
30
|
/** Maximum total file-storage bytes per workProject. Mode-varied. */
|
|
31
31
|
export const MAX_WORK_FILE_STORAGE_BYTES = ACTIVE_LIMITS.workProject.maxWorkFileStorageBytes;
|
|
32
|
+
/**
|
|
33
|
+
* Maximum number of shared-file folders a Realm steward may create
|
|
34
|
+
* (`workRealms/{workRealmId}/realmFileFolders`).
|
|
35
|
+
*
|
|
36
|
+
* Bounded on purpose: the folder collection is read WHOLE by the gallery projection, by the
|
|
37
|
+
* folder-cap check, and by the case-insensitive name-uniqueness check, so an unbounded
|
|
38
|
+
* collection would turn each of those into an unbounded read. 30 is generous for organizing
|
|
39
|
+
* one Realm's shared pool (Realm folders have no access lists — they are purely
|
|
40
|
+
* organizational) while keeping every one of those reads a single bounded page.
|
|
41
|
+
*
|
|
42
|
+
* NOT mode-varied: unlike the Work-side caps this is an organizational bound on steward
|
|
43
|
+
* housekeeping, not a charter-vs-full consumption allowance.
|
|
44
|
+
*
|
|
45
|
+
* Realm folder NAMES reuse MAX_FILE_FOLDER_NAME_LENGTH above — one folder-name rule
|
|
46
|
+
* platform-wide; there is deliberately no second realm-specific length.
|
|
47
|
+
*/
|
|
48
|
+
export const MAX_REALM_FILE_FOLDERS = 30;
|
|
32
49
|
/** Allowed characters in titles: letters, numbers, spaces. */
|
|
33
50
|
export const TITLE_PATTERN = /^[a-zA-Z0-9 ]+$/;
|
|
34
51
|
/** Maximum number of auditions a single workProject can have open at once. Mode-varied. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"business-work-project.js","sourceRoot":"","sources":["../../src/constants/business-work-project.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,oEAAoE;AACpE,MAAM,CAAC,MAAM,6BAA6B,GAAG,IAAI,CAAC;AAElD,yEAAyE;AACzE,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAC,WAAW,CAAC,YAAY,CAAC;AAErE;;;GAGG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,EAAE,CAAC;AAE9C,4CAA4C;AAE5C,8CAA8C;AAC9C,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAG,CAAC;AAEjD;uFACuF;AACvF,MAAM,CAAC,MAAM,mCAAmC,GAAG,IAAI,CAAC;AAExD,2CAA2C;AAC3C,wFAAwF;AACxF,yFAAyF;AACzF,kFAAkF;AAElF,MAAM,CAAC,MAAM,2BAA2B,GAAG,6BAA6B,CAAC;AACzE,MAAM,CAAC,MAAM,iCAAiC,GAAG,mCAAmC,CAAC;AAErF,0DAA0D;AAC1D,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAE/C,mEAAmE;AACnE,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAa,CAAC,WAAW,CAAC,cAAc,CAAC;AAEzE,2EAA2E;AAC3E,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAC,WAAW,CAAC,YAAY,CAAC;AAErE,qEAAqE;AACrE,MAAM,CAAC,MAAM,2BAA2B,GAAG,aAAa,CAAC,WAAW,CAAC,uBAAuB,CAAC;AAE7F,8DAA8D;AAC9D,MAAM,CAAC,MAAM,aAAa,GAAG,iBAAiB,CAAC;AAE/C,2FAA2F;AAC3F,MAAM,CAAC,MAAM,0BAA0B,GAAG,aAAa,CAAC,WAAW,CAAC,uBAAuB,CAAC;AAE5F,4DAA4D;AAC5D,qEAAqE;AAErE,MAAM,CAAC,MAAM,qBAAqB,GAAG,6BAA6B,CAAC;AACnE,MAAM,CAAC,MAAM,2BAA2B,GAAG,mCAAmC,CAAC;AAE/E,MAAM,CAAC,MAAM,qBAAqB,GAAG,6BAA6B,CAAC;AACnE,MAAM,CAAC,MAAM,2BAA2B,GAAG,mCAAmC,CAAC;AAE/E,MAAM,CAAC,MAAM,2BAA2B,GAAG,6BAA6B,CAAC;AACzE,MAAM,CAAC,MAAM,iCAAiC,GAAG,mCAAmC,CAAC;AAErF,+DAA+D;AAC/D,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAAC,WAAW,CAAC,WAAW,CAAC;AAElE,0CAA0C;AAC1C,MAAM,CAAC,MAAM,wBAAwB,GAAG,6BAA6B,CAAC;AAEtE;wFACwF;AACxF,MAAM,CAAC,MAAM,0BAA0B,GAAG,aAAa,CAAC,WAAW,CAAC,uBAAuB,CAAC;AAE5F,qFAAqF;AACrF,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAE1C,0EAA0E;AAC1E,MAAM,CAAC,MAAM,eAAe,GAAG,aAAa,CAAC,WAAW,CAAC,aAAa,CAAC;AAEvE,wCAAwC;AACxC,MAAM,CAAC,MAAM,2BAA2B,GAAG,6BAA6B,CAAC;AAEzE,8CAA8C;AAC9C,MAAM,CAAC,MAAM,iCAAiC,GAAG,mCAAmC,CAAC;AAErF,iFAAiF;AACjF,MAAM,CAAC,MAAM,uBAAuB,GAAG,aAAa,CAAC,WAAW,CAAC,qBAAqB,CAAC;AAEvF,2CAA2C;AAC3C,MAAM,CAAC,MAAM,mCAAmC,GAAG,6BAA6B,CAAC;AAEjF,iDAAiD;AACjD,MAAM,CAAC,MAAM,yCAAyC,GAAG,mCAAmC,CAAC","sourcesContent":["// WorkProject + subtype (Tales / Tunes / Television) business-rule constants.\nimport { ACTIVE_LIMITS } from './app-mode.js';\n\n/** The absolute maximum number of stakes a workProject can have. */\nexport const MAX_WORK_PROJECT_STAKE_SHARES = 1000;\n\n/** Maximum number of active guildmates per work project. Mode-varied. */\nexport const MAX_GUILD_SIZE = ACTIVE_LIMITS.workProject.maxGuildSize;\n\n/**\n * Stake shares minted to the realm's founding-Work holder when a Work is\n * created into an EXISTING public realm. Counts toward MAX_WORK_PROJECT_STAKE_SHARES.\n */\nexport const EXISTING_REALM_STAKE_SHARES = 75;\n\n// --- WorkProject Titles & Descriptions ---\n\n/** Maximum length for a workProject title. */\nexport const MAX_WORK_PROJECT_TITLE_LENGTH = 150;\n\n/** Maximum length for a workProject description (DJ ruling 2026-07-13: 1000 — room for\n * a real paragraph; browse cards render a truncated excerpt with click-to-expand). */\nexport const MAX_WORK_PROJECT_DESCRIPTION_LENGTH = 1000;\n\n// --- Work Realm titles & descriptions ---\n// Aliases of the workProject pair — realms share the platform title/description limits.\n// NOTE: a realm working title doubles as the `reservedRealmNames/{UPPER(title)}` doc ID,\n// so realmWorkingTitleSchema layers doc-ID character rules on top of this length.\n\nexport const MAX_WORK_REALM_TITLE_LENGTH = MAX_WORK_PROJECT_TITLE_LENGTH;\nexport const MAX_WORK_REALM_DESCRIPTION_LENGTH = MAX_WORK_PROJECT_DESCRIPTION_LENGTH;\n\n/** Maximum length for a work-project file-folder name. */\nexport const MAX_FILE_FOLDER_NAME_LENGTH = 100;\n\n/** Maximum number of file folders per workProject. Mode-varied. */\nexport const MAX_FILE_FOLDERS = ACTIVE_LIMITS.workProject.maxFileFolders;\n\n/** Maximum number of files across a workProject's folders. Mode-varied. */\nexport const MAX_WORK_FILES = ACTIVE_LIMITS.workProject.maxWorkFiles;\n\n/** Maximum total file-storage bytes per workProject. Mode-varied. */\nexport const MAX_WORK_FILE_STORAGE_BYTES = ACTIVE_LIMITS.workProject.maxWorkFileStorageBytes;\n\n/** Allowed characters in titles: letters, numbers, spaces. */\nexport const TITLE_PATTERN = /^[a-zA-Z0-9 ]+$/;\n\n/** Maximum number of auditions a single workProject can have open at once. Mode-varied. */\nexport const MAX_WORK_PROJECT_AUDITIONS = ACTIVE_LIMITS.workProject.maxWorkProjectAuditions;\n\n// --- WorkProject Subtypes (Tales / Tunes / Television) ---\n// Length aliases — kept as named exports so call sites read clearly.\n\nexport const MAX_TALE_TITLE_LENGTH = MAX_WORK_PROJECT_TITLE_LENGTH;\nexport const MAX_TALE_DESCRIPTION_LENGTH = MAX_WORK_PROJECT_DESCRIPTION_LENGTH;\n\nexport const MAX_TUNE_TITLE_LENGTH = MAX_WORK_PROJECT_TITLE_LENGTH;\nexport const MAX_TUNE_DESCRIPTION_LENGTH = MAX_WORK_PROJECT_DESCRIPTION_LENGTH;\n\nexport const MAX_TELEVISION_TITLE_LENGTH = MAX_WORK_PROJECT_TITLE_LENGTH;\nexport const MAX_TELEVISION_DESCRIPTION_LENGTH = MAX_WORK_PROJECT_DESCRIPTION_LENGTH;\n\n/** Maximum number of chapters a Tale can have. Mode-varied. */\nexport const MAX_CHAPTERS = ACTIVE_LIMITS.workProject.maxChapters;\n\n/** Maximum length for a chapter title. */\nexport const MAX_CHAPTER_TITLE_LENGTH = MAX_WORK_PROJECT_TITLE_LENGTH;\n\n/** Maximum length for chapter body content. Mode-varied (charter 30k / full 100k) —\n * the ONE mode-varied text limit (DJ 2026-07-13); the flip raises it automatically. */\nexport const MAX_CHAPTER_CONTENT_LENGTH = ACTIVE_LIMITS.workProject.maxChapterContentLength;\n\n/** Chapter-body EXCERPT length for preview rows (hall reading view chapter list). */\nexport const CHAPTER_EXCERPT_LENGTH = 180;\n\n/** Maximum number of tracks a Tunes workProject can have. Mode-varied. */\nexport const MAX_TUNE_TRACKS = ACTIVE_LIMITS.workProject.maxTuneTracks;\n\n/** Maximum length for a track title. */\nexport const MAX_TUNE_TRACK_TITLE_LENGTH = MAX_WORK_PROJECT_TITLE_LENGTH;\n\n/** Maximum length for a track description. */\nexport const MAX_TUNE_TRACK_DESCRIPTION_LENGTH = MAX_WORK_PROJECT_DESCRIPTION_LENGTH;\n\n/** Maximum number of episodes a Television workProject can have. Mode-varied. */\nexport const MAX_TELEVISION_EPISODES = ACTIVE_LIMITS.workProject.maxTelevisionEpisodes;\n\n/** Maximum length for an episode title. */\nexport const MAX_TELEVISION_EPISODE_TITLE_LENGTH = MAX_WORK_PROJECT_TITLE_LENGTH;\n\n/** Maximum length for an episode description. */\nexport const MAX_TELEVISION_EPISODE_DESCRIPTION_LENGTH = MAX_WORK_PROJECT_DESCRIPTION_LENGTH;\n"]}
|
|
1
|
+
{"version":3,"file":"business-work-project.js","sourceRoot":"","sources":["../../src/constants/business-work-project.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,oEAAoE;AACpE,MAAM,CAAC,MAAM,6BAA6B,GAAG,IAAI,CAAC;AAElD,yEAAyE;AACzE,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAC,WAAW,CAAC,YAAY,CAAC;AAErE;;;GAGG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,EAAE,CAAC;AAE9C,4CAA4C;AAE5C,8CAA8C;AAC9C,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAG,CAAC;AAEjD;uFACuF;AACvF,MAAM,CAAC,MAAM,mCAAmC,GAAG,IAAI,CAAC;AAExD,2CAA2C;AAC3C,wFAAwF;AACxF,yFAAyF;AACzF,kFAAkF;AAElF,MAAM,CAAC,MAAM,2BAA2B,GAAG,6BAA6B,CAAC;AACzE,MAAM,CAAC,MAAM,iCAAiC,GAAG,mCAAmC,CAAC;AAErF,0DAA0D;AAC1D,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,CAAC;AAE/C,mEAAmE;AACnE,MAAM,CAAC,MAAM,gBAAgB,GAAG,aAAa,CAAC,WAAW,CAAC,cAAc,CAAC;AAEzE,2EAA2E;AAC3E,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAC,WAAW,CAAC,YAAY,CAAC;AAErE,qEAAqE;AACrE,MAAM,CAAC,MAAM,2BAA2B,GAAG,aAAa,CAAC,WAAW,CAAC,uBAAuB,CAAC;AAE7F;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAEzC,8DAA8D;AAC9D,MAAM,CAAC,MAAM,aAAa,GAAG,iBAAiB,CAAC;AAE/C,2FAA2F;AAC3F,MAAM,CAAC,MAAM,0BAA0B,GAAG,aAAa,CAAC,WAAW,CAAC,uBAAuB,CAAC;AAE5F,4DAA4D;AAC5D,qEAAqE;AAErE,MAAM,CAAC,MAAM,qBAAqB,GAAG,6BAA6B,CAAC;AACnE,MAAM,CAAC,MAAM,2BAA2B,GAAG,mCAAmC,CAAC;AAE/E,MAAM,CAAC,MAAM,qBAAqB,GAAG,6BAA6B,CAAC;AACnE,MAAM,CAAC,MAAM,2BAA2B,GAAG,mCAAmC,CAAC;AAE/E,MAAM,CAAC,MAAM,2BAA2B,GAAG,6BAA6B,CAAC;AACzE,MAAM,CAAC,MAAM,iCAAiC,GAAG,mCAAmC,CAAC;AAErF,+DAA+D;AAC/D,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAAC,WAAW,CAAC,WAAW,CAAC;AAElE,0CAA0C;AAC1C,MAAM,CAAC,MAAM,wBAAwB,GAAG,6BAA6B,CAAC;AAEtE;wFACwF;AACxF,MAAM,CAAC,MAAM,0BAA0B,GAAG,aAAa,CAAC,WAAW,CAAC,uBAAuB,CAAC;AAE5F,qFAAqF;AACrF,MAAM,CAAC,MAAM,sBAAsB,GAAG,GAAG,CAAC;AAE1C,0EAA0E;AAC1E,MAAM,CAAC,MAAM,eAAe,GAAG,aAAa,CAAC,WAAW,CAAC,aAAa,CAAC;AAEvE,wCAAwC;AACxC,MAAM,CAAC,MAAM,2BAA2B,GAAG,6BAA6B,CAAC;AAEzE,8CAA8C;AAC9C,MAAM,CAAC,MAAM,iCAAiC,GAAG,mCAAmC,CAAC;AAErF,iFAAiF;AACjF,MAAM,CAAC,MAAM,uBAAuB,GAAG,aAAa,CAAC,WAAW,CAAC,qBAAqB,CAAC;AAEvF,2CAA2C;AAC3C,MAAM,CAAC,MAAM,mCAAmC,GAAG,6BAA6B,CAAC;AAEjF,iDAAiD;AACjD,MAAM,CAAC,MAAM,yCAAyC,GAAG,mCAAmC,CAAC","sourcesContent":["// WorkProject + subtype (Tales / Tunes / Television) business-rule constants.\nimport { ACTIVE_LIMITS } from './app-mode.js';\n\n/** The absolute maximum number of stakes a workProject can have. */\nexport const MAX_WORK_PROJECT_STAKE_SHARES = 1000;\n\n/** Maximum number of active guildmates per work project. Mode-varied. */\nexport const MAX_GUILD_SIZE = ACTIVE_LIMITS.workProject.maxGuildSize;\n\n/**\n * Stake shares minted to the realm's founding-Work holder when a Work is\n * created into an EXISTING public realm. Counts toward MAX_WORK_PROJECT_STAKE_SHARES.\n */\nexport const EXISTING_REALM_STAKE_SHARES = 75;\n\n// --- WorkProject Titles & Descriptions ---\n\n/** Maximum length for a workProject title. */\nexport const MAX_WORK_PROJECT_TITLE_LENGTH = 150;\n\n/** Maximum length for a workProject description (DJ ruling 2026-07-13: 1000 — room for\n * a real paragraph; browse cards render a truncated excerpt with click-to-expand). */\nexport const MAX_WORK_PROJECT_DESCRIPTION_LENGTH = 1000;\n\n// --- Work Realm titles & descriptions ---\n// Aliases of the workProject pair — realms share the platform title/description limits.\n// NOTE: a realm working title doubles as the `reservedRealmNames/{UPPER(title)}` doc ID,\n// so realmWorkingTitleSchema layers doc-ID character rules on top of this length.\n\nexport const MAX_WORK_REALM_TITLE_LENGTH = MAX_WORK_PROJECT_TITLE_LENGTH;\nexport const MAX_WORK_REALM_DESCRIPTION_LENGTH = MAX_WORK_PROJECT_DESCRIPTION_LENGTH;\n\n/** Maximum length for a work-project file-folder name. */\nexport const MAX_FILE_FOLDER_NAME_LENGTH = 100;\n\n/** Maximum number of file folders per workProject. Mode-varied. */\nexport const MAX_FILE_FOLDERS = ACTIVE_LIMITS.workProject.maxFileFolders;\n\n/** Maximum number of files across a workProject's folders. Mode-varied. */\nexport const MAX_WORK_FILES = ACTIVE_LIMITS.workProject.maxWorkFiles;\n\n/** Maximum total file-storage bytes per workProject. Mode-varied. */\nexport const MAX_WORK_FILE_STORAGE_BYTES = ACTIVE_LIMITS.workProject.maxWorkFileStorageBytes;\n\n/**\n * Maximum number of shared-file folders a Realm steward may create\n * (`workRealms/{workRealmId}/realmFileFolders`).\n *\n * Bounded on purpose: the folder collection is read WHOLE by the gallery projection, by the\n * folder-cap check, and by the case-insensitive name-uniqueness check, so an unbounded\n * collection would turn each of those into an unbounded read. 30 is generous for organizing\n * one Realm's shared pool (Realm folders have no access lists — they are purely\n * organizational) while keeping every one of those reads a single bounded page.\n *\n * NOT mode-varied: unlike the Work-side caps this is an organizational bound on steward\n * housekeeping, not a charter-vs-full consumption allowance.\n *\n * Realm folder NAMES reuse MAX_FILE_FOLDER_NAME_LENGTH above — one folder-name rule\n * platform-wide; there is deliberately no second realm-specific length.\n */\nexport const MAX_REALM_FILE_FOLDERS = 30;\n\n/** Allowed characters in titles: letters, numbers, spaces. */\nexport const TITLE_PATTERN = /^[a-zA-Z0-9 ]+$/;\n\n/** Maximum number of auditions a single workProject can have open at once. Mode-varied. */\nexport const MAX_WORK_PROJECT_AUDITIONS = ACTIVE_LIMITS.workProject.maxWorkProjectAuditions;\n\n// --- WorkProject Subtypes (Tales / Tunes / Television) ---\n// Length aliases — kept as named exports so call sites read clearly.\n\nexport const MAX_TALE_TITLE_LENGTH = MAX_WORK_PROJECT_TITLE_LENGTH;\nexport const MAX_TALE_DESCRIPTION_LENGTH = MAX_WORK_PROJECT_DESCRIPTION_LENGTH;\n\nexport const MAX_TUNE_TITLE_LENGTH = MAX_WORK_PROJECT_TITLE_LENGTH;\nexport const MAX_TUNE_DESCRIPTION_LENGTH = MAX_WORK_PROJECT_DESCRIPTION_LENGTH;\n\nexport const MAX_TELEVISION_TITLE_LENGTH = MAX_WORK_PROJECT_TITLE_LENGTH;\nexport const MAX_TELEVISION_DESCRIPTION_LENGTH = MAX_WORK_PROJECT_DESCRIPTION_LENGTH;\n\n/** Maximum number of chapters a Tale can have. Mode-varied. */\nexport const MAX_CHAPTERS = ACTIVE_LIMITS.workProject.maxChapters;\n\n/** Maximum length for a chapter title. */\nexport const MAX_CHAPTER_TITLE_LENGTH = MAX_WORK_PROJECT_TITLE_LENGTH;\n\n/** Maximum length for chapter body content. Mode-varied (charter 30k / full 100k) —\n * the ONE mode-varied text limit (DJ 2026-07-13); the flip raises it automatically. */\nexport const MAX_CHAPTER_CONTENT_LENGTH = ACTIVE_LIMITS.workProject.maxChapterContentLength;\n\n/** Chapter-body EXCERPT length for preview rows (hall reading view chapter list). */\nexport const CHAPTER_EXCERPT_LENGTH = 180;\n\n/** Maximum number of tracks a Tunes workProject can have. Mode-varied. */\nexport const MAX_TUNE_TRACKS = ACTIVE_LIMITS.workProject.maxTuneTracks;\n\n/** Maximum length for a track title. */\nexport const MAX_TUNE_TRACK_TITLE_LENGTH = MAX_WORK_PROJECT_TITLE_LENGTH;\n\n/** Maximum length for a track description. */\nexport const MAX_TUNE_TRACK_DESCRIPTION_LENGTH = MAX_WORK_PROJECT_DESCRIPTION_LENGTH;\n\n/** Maximum number of episodes a Television workProject can have. Mode-varied. */\nexport const MAX_TELEVISION_EPISODES = ACTIVE_LIMITS.workProject.maxTelevisionEpisodes;\n\n/** Maximum length for an episode title. */\nexport const MAX_TELEVISION_EPISODE_TITLE_LENGTH = MAX_WORK_PROJECT_TITLE_LENGTH;\n\n/** Maximum length for an episode description. */\nexport const MAX_TELEVISION_EPISODE_DESCRIPTION_LENGTH = MAX_WORK_PROJECT_DESCRIPTION_LENGTH;\n"]}
|
|
@@ -25,6 +25,19 @@ export declare const POSTS_PER_PAGE = 20;
|
|
|
25
25
|
export declare const VIOLATIONS_PER_PAGE = 5;
|
|
26
26
|
/** Page size for the craft-skills list hook. */
|
|
27
27
|
export declare const CRAFT_SKILL_MEDIA_PER_PAGE = 12;
|
|
28
|
+
/**
|
|
29
|
+
* Hard page limit for the Realm shared-files gallery projection (`getRealmSharedFiles`).
|
|
30
|
+
* The query was previously unbounded; this is the named cap the input schema derives its
|
|
31
|
+
* `limit` bound from and the server clamps to, so one Realm's pool can never be read (or
|
|
32
|
+
* requested) in a single unbounded page. Matches the card-grid rhythm of the gallery.
|
|
33
|
+
*/
|
|
34
|
+
export declare const REALM_SHARED_FILES_PAGE_LIMIT = 24;
|
|
35
|
+
/**
|
|
36
|
+
* Hard page limit for the steward/admin realm-file promotion queue
|
|
37
|
+
* (`getRealmFilePromotionQueue`). Smaller than the gallery page: the queue is a decision
|
|
38
|
+
* surface a steward works through, not a browse grid.
|
|
39
|
+
*/
|
|
40
|
+
export declare const REALM_FILE_PROMOTION_QUEUE_PAGE_LIMIT = 20;
|
|
28
41
|
/** Maximum number of recent posts the trending-feed scheduled commission processes per run. Mode-varied. */
|
|
29
42
|
export declare const TRENDING_FEED_PROCESS_LIMIT: number;
|
|
30
43
|
/** HallLibrary page-level UX values (page size, recency window, search debounce, per-item tag cap). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../src/constants/pagination.ts"],"names":[],"mappings":"AAGA,0DAA0D;AAC1D,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,sCAAsC,IAAI,CAAC;AACxD,eAAO,MAAM,+BAA+B,IAAI,CAAC;AACjD,eAAO,MAAM,8BAA8B,IAAI,CAAC;AAChD,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAC/C,eAAO,MAAM,kCAAkC,IAAI,CAAC;AACpD,eAAO,MAAM,uCAAuC,IAAI,CAAC;AACzD,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAC5C,eAAO,MAAM,kCAAkC,IAAI,CAAC;AACpD,eAAO,MAAM,gCAAgC,IAAI,CAAC;AAClD,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAChD,eAAO,MAAM,qCAAqC,KAAK,CAAC;AAIxD,mDAAmD;AACnD,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAE3C,yDAAyD;AACzD,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC,wDAAwD;AACxD,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,0CAA0C;AAC1C,eAAO,MAAM,cAAc,KAAK,CAAC;AAEjC,qDAAqD;AACrD,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC,gDAAgD;AAChD,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAE7C,4GAA4G;AAC5G,eAAO,MAAM,2BAA2B,QAAiD,CAAC;AAI1F,uGAAuG;AACvG,eAAO,MAAM,2BAA2B;;;;;CAK9B,CAAC"}
|
|
1
|
+
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../src/constants/pagination.ts"],"names":[],"mappings":"AAGA,0DAA0D;AAC1D,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,sCAAsC,IAAI,CAAC;AACxD,eAAO,MAAM,+BAA+B,IAAI,CAAC;AACjD,eAAO,MAAM,8BAA8B,IAAI,CAAC;AAChD,eAAO,MAAM,4BAA4B,KAAK,CAAC;AAC/C,eAAO,MAAM,kCAAkC,IAAI,CAAC;AACpD,eAAO,MAAM,uCAAuC,IAAI,CAAC;AACzD,eAAO,MAAM,uBAAuB,IAAI,CAAC;AACzC,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAC5C,eAAO,MAAM,kCAAkC,IAAI,CAAC;AACpD,eAAO,MAAM,gCAAgC,IAAI,CAAC;AAClD,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAChD,eAAO,MAAM,qCAAqC,KAAK,CAAC;AAIxD,mDAAmD;AACnD,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAE3C,yDAAyD;AACzD,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC,wDAAwD;AACxD,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC,0CAA0C;AAC1C,eAAO,MAAM,cAAc,KAAK,CAAC;AAEjC,qDAAqD;AACrD,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC,gDAAgD;AAChD,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAE7C;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAEhD;;;;GAIG;AACH,eAAO,MAAM,qCAAqC,KAAK,CAAC;AAExD,4GAA4G;AAC5G,eAAO,MAAM,2BAA2B,QAAiD,CAAC;AAI1F,uGAAuG;AACvG,eAAO,MAAM,2BAA2B;;;;;CAK9B,CAAC"}
|
|
@@ -28,6 +28,19 @@ export const POSTS_PER_PAGE = 20;
|
|
|
28
28
|
export const VIOLATIONS_PER_PAGE = 5;
|
|
29
29
|
/** Page size for the craft-skills list hook. */
|
|
30
30
|
export const CRAFT_SKILL_MEDIA_PER_PAGE = 12;
|
|
31
|
+
/**
|
|
32
|
+
* Hard page limit for the Realm shared-files gallery projection (`getRealmSharedFiles`).
|
|
33
|
+
* The query was previously unbounded; this is the named cap the input schema derives its
|
|
34
|
+
* `limit` bound from and the server clamps to, so one Realm's pool can never be read (or
|
|
35
|
+
* requested) in a single unbounded page. Matches the card-grid rhythm of the gallery.
|
|
36
|
+
*/
|
|
37
|
+
export const REALM_SHARED_FILES_PAGE_LIMIT = 24;
|
|
38
|
+
/**
|
|
39
|
+
* Hard page limit for the steward/admin realm-file promotion queue
|
|
40
|
+
* (`getRealmFilePromotionQueue`). Smaller than the gallery page: the queue is a decision
|
|
41
|
+
* surface a steward works through, not a browse grid.
|
|
42
|
+
*/
|
|
43
|
+
export const REALM_FILE_PROMOTION_QUEUE_PAGE_LIMIT = 20;
|
|
31
44
|
/** Maximum number of recent posts the trending-feed scheduled commission processes per run. Mode-varied. */
|
|
32
45
|
export const TRENDING_FEED_PROCESS_LIMIT = ACTIVE_LIMITS.batches.trendingFeedProcessLimit;
|
|
33
46
|
// --- HallLibrary UX constants ---
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../src/constants/pagination.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,0DAA0D;AAC1D,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAExC,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AACzC,MAAM,CAAC,MAAM,sCAAsC,GAAG,CAAC,CAAC;AACxD,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,CAAC;AACjD,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC;AAChD,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,CAAC;AAC/C,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,CAAC;AACpD,MAAM,CAAC,MAAM,uCAAuC,GAAG,CAAC,CAAC;AACzD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AACzC,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC;AAC5C,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,CAAC;AACpD,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,CAAC;AAClD,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,CAAC;AAChD,MAAM,CAAC,MAAM,qCAAqC,GAAG,EAAE,CAAC;AAExD,mCAAmC;AAEnC,mDAAmD;AACnD,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAE3C,yDAAyD;AACzD,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAEnC,wDAAwD;AACxD,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAEpC,0CAA0C;AAC1C,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AAEjC,qDAAqD;AACrD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAErC,gDAAgD;AAChD,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAE7C,4GAA4G;AAC5G,MAAM,CAAC,MAAM,2BAA2B,GAAG,aAAa,CAAC,OAAO,CAAC,wBAAwB,CAAC;AAE1F,mCAAmC;AAEnC,uGAAuG;AACvG,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,cAAc,EAAE,EAAE;IAClB,gBAAgB,EAAE,EAAE;IACpB,iBAAiB,EAAE,EAAE;IACrB,kBAAkB,EAAE,GAAG;CACf,CAAC","sourcesContent":["// Pagination page sizes and hallLibrary UX constants.\nimport { ACTIVE_LIMITS } from './app-mode.js';\n\n/** Default pagination size when no other size applies. */\nexport const ITEMS_PER_PAGE_GENERAL = 5;\n\nexport const ITEMS_PER_PAGE_MESSAGES = 5;\nexport const ITEMS_PER_PAGE_ADMIN_DISPATCH_MESSAGES = 6;\nexport const ITEMS_PER_PAGE_COMMISSION_BOARD = 5;\nexport const ITEMS_PER_PAGE_GUILDMATE_USERS = 3;\nexport const ITEMS_PER_PAGE_GUILD_INVITES = 10;\nexport const ITEMS_PER_PAGE_OWNED_WORK_PROJECTS = 3;\nexport const ITEMS_PER_PAGE_ASSOCIATED_WORK_PROJECTS = 3;\nexport const ITEMS_PER_PAGE_CHAPTERS = 5;\nexport const ITEMS_PER_PAGE_TUNE_TRACKS = 3;\nexport const ITEMS_PER_PAGE_TELEVISION_EPISODES = 3;\nexport const ITEMS_PER_PAGE_PROPOSAL_ARTISANS = 5;\nexport const ITEMS_PER_PAGE_FOLLOWED_USERS = 10;\nexport const ITEMS_PER_PAGE_ADMIN_DISPATCH_THREADS = 10;\n\n// --- Hook-specific page sizes ---\n\n/** Page size for the pledge-payments list hook. */\nexport const PLEDGE_PAYMENTS_PER_PAGE = 20;\n\n/** Page size for the pending-media archive list hook. */\nexport const ARCHIVE_PER_PAGE = 10;\n\n/** Page size for the workProject-channels list hook. */\nexport const CHANNELS_PER_PAGE = 10;\n\n/** Page size for the social feed hook. */\nexport const POSTS_PER_PAGE = 20;\n\n/** Page size for the content-violation list hook. */\nexport const VIOLATIONS_PER_PAGE = 5;\n\n/** Page size for the craft-skills list hook. */\nexport const CRAFT_SKILL_MEDIA_PER_PAGE = 12;\n\n/** Maximum number of recent posts the trending-feed scheduled commission processes per run. Mode-varied. */\nexport const TRENDING_FEED_PROCESS_LIMIT = ACTIVE_LIMITS.batches.trendingFeedProcessLimit;\n\n// --- HallLibrary UX constants ---\n\n/** HallLibrary page-level UX values (page size, recency window, search debounce, per-item tag cap). */\nexport const HALL_LIBRARY_PAGE_CONSTANTS = {\n ITEMS_PER_PAGE: 20,\n MAX_RECENT_VIEWS: 50,\n MAX_TAGS_PER_ITEM: 10,\n SEARCH_DEBOUNCE_MS: 300,\n} as const;\n\n"]}
|
|
1
|
+
{"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../src/constants/pagination.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,0DAA0D;AAC1D,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAExC,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AACzC,MAAM,CAAC,MAAM,sCAAsC,GAAG,CAAC,CAAC;AACxD,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,CAAC;AACjD,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC;AAChD,MAAM,CAAC,MAAM,4BAA4B,GAAG,EAAE,CAAC;AAC/C,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,CAAC;AACpD,MAAM,CAAC,MAAM,uCAAuC,GAAG,CAAC,CAAC;AACzD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AACzC,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC;AAC5C,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,CAAC;AACpD,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,CAAC;AAClD,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,CAAC;AAChD,MAAM,CAAC,MAAM,qCAAqC,GAAG,EAAE,CAAC;AAExD,mCAAmC;AAEnC,mDAAmD;AACnD,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAE3C,yDAAyD;AACzD,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAEnC,wDAAwD;AACxD,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAEpC,0CAA0C;AAC1C,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AAEjC,qDAAqD;AACrD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAErC,gDAAgD;AAChD,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,EAAE,CAAC;AAEhD;;;;GAIG;AACH,MAAM,CAAC,MAAM,qCAAqC,GAAG,EAAE,CAAC;AAExD,4GAA4G;AAC5G,MAAM,CAAC,MAAM,2BAA2B,GAAG,aAAa,CAAC,OAAO,CAAC,wBAAwB,CAAC;AAE1F,mCAAmC;AAEnC,uGAAuG;AACvG,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,cAAc,EAAE,EAAE;IAClB,gBAAgB,EAAE,EAAE;IACpB,iBAAiB,EAAE,EAAE;IACrB,kBAAkB,EAAE,GAAG;CACf,CAAC","sourcesContent":["// Pagination page sizes and hallLibrary UX constants.\nimport { ACTIVE_LIMITS } from './app-mode.js';\n\n/** Default pagination size when no other size applies. */\nexport const ITEMS_PER_PAGE_GENERAL = 5;\n\nexport const ITEMS_PER_PAGE_MESSAGES = 5;\nexport const ITEMS_PER_PAGE_ADMIN_DISPATCH_MESSAGES = 6;\nexport const ITEMS_PER_PAGE_COMMISSION_BOARD = 5;\nexport const ITEMS_PER_PAGE_GUILDMATE_USERS = 3;\nexport const ITEMS_PER_PAGE_GUILD_INVITES = 10;\nexport const ITEMS_PER_PAGE_OWNED_WORK_PROJECTS = 3;\nexport const ITEMS_PER_PAGE_ASSOCIATED_WORK_PROJECTS = 3;\nexport const ITEMS_PER_PAGE_CHAPTERS = 5;\nexport const ITEMS_PER_PAGE_TUNE_TRACKS = 3;\nexport const ITEMS_PER_PAGE_TELEVISION_EPISODES = 3;\nexport const ITEMS_PER_PAGE_PROPOSAL_ARTISANS = 5;\nexport const ITEMS_PER_PAGE_FOLLOWED_USERS = 10;\nexport const ITEMS_PER_PAGE_ADMIN_DISPATCH_THREADS = 10;\n\n// --- Hook-specific page sizes ---\n\n/** Page size for the pledge-payments list hook. */\nexport const PLEDGE_PAYMENTS_PER_PAGE = 20;\n\n/** Page size for the pending-media archive list hook. */\nexport const ARCHIVE_PER_PAGE = 10;\n\n/** Page size for the workProject-channels list hook. */\nexport const CHANNELS_PER_PAGE = 10;\n\n/** Page size for the social feed hook. */\nexport const POSTS_PER_PAGE = 20;\n\n/** Page size for the content-violation list hook. */\nexport const VIOLATIONS_PER_PAGE = 5;\n\n/** Page size for the craft-skills list hook. */\nexport const CRAFT_SKILL_MEDIA_PER_PAGE = 12;\n\n/**\n * Hard page limit for the Realm shared-files gallery projection (`getRealmSharedFiles`).\n * The query was previously unbounded; this is the named cap the input schema derives its\n * `limit` bound from and the server clamps to, so one Realm's pool can never be read (or\n * requested) in a single unbounded page. Matches the card-grid rhythm of the gallery.\n */\nexport const REALM_SHARED_FILES_PAGE_LIMIT = 24;\n\n/**\n * Hard page limit for the steward/admin realm-file promotion queue\n * (`getRealmFilePromotionQueue`). Smaller than the gallery page: the queue is a decision\n * surface a steward works through, not a browse grid.\n */\nexport const REALM_FILE_PROMOTION_QUEUE_PAGE_LIMIT = 20;\n\n/** Maximum number of recent posts the trending-feed scheduled commission processes per run. Mode-varied. */\nexport const TRENDING_FEED_PROCESS_LIMIT = ACTIVE_LIMITS.batches.trendingFeedProcessLimit;\n\n// --- HallLibrary UX constants ---\n\n/** HallLibrary page-level UX values (page size, recency window, search debounce, per-item tag cap). */\nexport const HALL_LIBRARY_PAGE_CONSTANTS = {\n ITEMS_PER_PAGE: 20,\n MAX_RECENT_VIEWS: 50,\n MAX_TAGS_PER_ITEM: 10,\n SEARCH_DEBOUNCE_MS: 300,\n} as const;\n\n"]}
|
|
@@ -30,4 +30,11 @@ export declare const TEXT_SIZE_STORAGE_KEY = "ttt-text-size";
|
|
|
30
30
|
/** Same-tab window event dispatched when TEXT_SIZE_STORAGE_KEY changes (localStorage
|
|
31
31
|
* 'storage' events do not fire in the writing tab), mirroring REDUCED_MOTION_CHANGE_EVENT. */
|
|
32
32
|
export declare const TEXT_SIZE_CHANGE_EVENT = "ttt-text-size-change";
|
|
33
|
+
/** localStorage key holding the caller's single unconfirmed site-tour choice. Scoped by the
|
|
34
|
+
* AUTHENTICATED uid — never a browser-global key. */
|
|
35
|
+
export declare function siteTourPendingStorageKey(uid: string): string;
|
|
36
|
+
/** Same-tab window event dispatched when a `siteTourPendingStorageKey(uid)` entry is written or
|
|
37
|
+
* removed (localStorage 'storage' events do not fire in the writing tab), mirroring
|
|
38
|
+
* TEXT_SIZE_CHANGE_EVENT. Cross-tab propagation still rides the native 'storage' event. */
|
|
39
|
+
export declare const SITE_TOUR_PENDING_CHANGE_EVENT = "ttt-site-tour-pending-change";
|
|
33
40
|
//# sourceMappingURL=storage-keys.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-keys.d.ts","sourceRoot":"","sources":["../../src/constants/storage-keys.ts"],"names":[],"mappings":"AAEA,4FAA4F;AAC5F,eAAO,MAAM,iBAAiB,iBAAiB,CAAC;AAEhD,2FAA2F;AAC3F,eAAO,MAAM,cAAc,oBAAoB,CAAC;AAEhD,uFAAuF;AACvF,eAAO,MAAM,uBAAuB,iCAAiC,CAAC;AAMtE,qFAAqF;AACrF,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAE7D,qFAAqF;AACrF,eAAO,MAAM,yBAAyB,oBAAoB,CAAC;AAE3D;uCACuC;AACvC,eAAO,MAAM,6BAA6B,wBAAwB,CAAC;AAEnE;sEACsE;AACtE,eAAO,MAAM,0BAA0B,yBAAyB,CAAC;AAEjE,2EAA2E;AAC3E,eAAO,MAAM,sBAAsB,iCAAiC,CAAC;AAErE;0CAC0C;AAC1C,eAAO,MAAM,wBAAwB,yBAAyB,CAAC;AAS/D;8EAC8E;AAC9E,eAAO,MAAM,0BAA0B,uBAAuB,CAAC;AAE/D;0FAC0F;AAC1F,eAAO,MAAM,2BAA2B,8BAA8B,CAAC;AAQvE,yFAAyF;AACzF,eAAO,MAAM,qBAAqB,kBAAkB,CAAC;AAErD;+FAC+F;AAC/F,eAAO,MAAM,sBAAsB,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"storage-keys.d.ts","sourceRoot":"","sources":["../../src/constants/storage-keys.ts"],"names":[],"mappings":"AAEA,4FAA4F;AAC5F,eAAO,MAAM,iBAAiB,iBAAiB,CAAC;AAEhD,2FAA2F;AAC3F,eAAO,MAAM,cAAc,oBAAoB,CAAC;AAEhD,uFAAuF;AACvF,eAAO,MAAM,uBAAuB,iCAAiC,CAAC;AAMtE,qFAAqF;AACrF,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAE7D,qFAAqF;AACrF,eAAO,MAAM,yBAAyB,oBAAoB,CAAC;AAE3D;uCACuC;AACvC,eAAO,MAAM,6BAA6B,wBAAwB,CAAC;AAEnE;sEACsE;AACtE,eAAO,MAAM,0BAA0B,yBAAyB,CAAC;AAEjE,2EAA2E;AAC3E,eAAO,MAAM,sBAAsB,iCAAiC,CAAC;AAErE;0CAC0C;AAC1C,eAAO,MAAM,wBAAwB,yBAAyB,CAAC;AAS/D;8EAC8E;AAC9E,eAAO,MAAM,0BAA0B,uBAAuB,CAAC;AAE/D;0FAC0F;AAC1F,eAAO,MAAM,2BAA2B,8BAA8B,CAAC;AAQvE,yFAAyF;AACzF,eAAO,MAAM,qBAAqB,kBAAkB,CAAC;AAErD;+FAC+F;AAC/F,eAAO,MAAM,sBAAsB,yBAAyB,CAAC;AAe7D;sDACsD;AACtD,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;4FAE4F;AAC5F,eAAO,MAAM,8BAA8B,iCAAiC,CAAC"}
|
|
@@ -45,4 +45,25 @@ export const TEXT_SIZE_STORAGE_KEY = 'ttt-text-size';
|
|
|
45
45
|
/** Same-tab window event dispatched when TEXT_SIZE_STORAGE_KEY changes (localStorage
|
|
46
46
|
* 'storage' events do not fire in the writing tab), mirroring REDUCED_MOTION_CHANGE_EVENT. */
|
|
47
47
|
export const TEXT_SIZE_CHANGE_EVENT = 'ttt-text-size-change';
|
|
48
|
+
// --- First-visit site-tour pending preference (the ONE sanctioned optimistic-hide slot) ---
|
|
49
|
+
// Unlike the House controls above, site-tour state is ACCOUNT-DURABLE: `privateData/{uid}.siteTour`
|
|
50
|
+
// stays the sole authority and the `updateSiteTourPreference` callable stays its sole writer. This
|
|
51
|
+
// key holds a SINGLE uid-scoped entry recording a choice the member has already made but whose
|
|
52
|
+
// server write has not been confirmed yet, so the overlay can close instantly and the write can be
|
|
53
|
+
// replayed on the next boot. It is a one-entry durable retry SLOT, never a cache, mirror, or second
|
|
54
|
+
// source of eligibility — a member with no pending entry is evaluated purely from the server state.
|
|
55
|
+
//
|
|
56
|
+
// UID-SCOPED BY CONSTRUCTION: a browser-global key would let user A's choice suppress (or replay
|
|
57
|
+
// into) the tour for user B after a sign-out/sign-in on the same device. The stored entry ALSO
|
|
58
|
+
// carries its own `uid` (SiteTourPendingPreferenceSchema, schemas/users.ts) and must match the key
|
|
59
|
+
// owner before it may affect eligibility or be replayed.
|
|
60
|
+
/** localStorage key holding the caller's single unconfirmed site-tour choice. Scoped by the
|
|
61
|
+
* AUTHENTICATED uid — never a browser-global key. */
|
|
62
|
+
export function siteTourPendingStorageKey(uid) {
|
|
63
|
+
return `ttt-site-tour-pending:${uid}`;
|
|
64
|
+
}
|
|
65
|
+
/** Same-tab window event dispatched when a `siteTourPendingStorageKey(uid)` entry is written or
|
|
66
|
+
* removed (localStorage 'storage' events do not fire in the writing tab), mirroring
|
|
67
|
+
* TEXT_SIZE_CHANGE_EVENT. Cross-tab propagation still rides the native 'storage' event. */
|
|
68
|
+
export const SITE_TOUR_PENDING_CHANGE_EVENT = 'ttt-site-tour-pending-change';
|
|
48
69
|
//# sourceMappingURL=storage-keys.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-keys.js","sourceRoot":"","sources":["../../src/constants/storage-keys.ts"],"names":[],"mappings":"AAAA,iEAAiE;AAEjE,4FAA4F;AAC5F,MAAM,CAAC,MAAM,iBAAiB,GAAG,cAAc,CAAC;AAEhD,2FAA2F;AAC3F,MAAM,CAAC,MAAM,cAAc,GAAG,iBAAiB,CAAC;AAEhD,uFAAuF;AACvF,MAAM,CAAC,MAAM,uBAAuB,GAAG,8BAA8B,CAAC;AAEtE,uEAAuE;AACvE,4EAA4E;AAC5E,0DAA0D;AAE1D,qFAAqF;AACrF,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAuB,CAAC;AAE7D,qFAAqF;AACrF,MAAM,CAAC,MAAM,yBAAyB,GAAG,iBAAiB,CAAC;AAE3D;uCACuC;AACvC,MAAM,CAAC,MAAM,6BAA6B,GAAG,qBAAqB,CAAC;AAEnE;sEACsE;AACtE,MAAM,CAAC,MAAM,0BAA0B,GAAG,sBAAsB,CAAC;AAEjE,2EAA2E;AAC3E,MAAM,CAAC,MAAM,sBAAsB,GAAG,8BAA8B,CAAC;AAErE;0CAC0C;AAC1C,MAAM,CAAC,MAAM,wBAAwB,GAAG,sBAAsB,CAAC;AAE/D,6DAA6D;AAC7D,yFAAyF;AACzF,0FAA0F;AAC1F,wFAAwF;AACxF,2FAA2F;AAC3F,8DAA8D;AAE9D;8EAC8E;AAC9E,MAAM,CAAC,MAAM,0BAA0B,GAAG,oBAAoB,CAAC;AAE/D;0FAC0F;AAC1F,MAAM,CAAC,MAAM,2BAA2B,GAAG,2BAA2B,CAAC;AAEvE,kDAAkD;AAClD,mFAAmF;AACnF,+FAA+F;AAC/F,+FAA+F;AAC/F,uEAAuE;AAEvE,yFAAyF;AACzF,MAAM,CAAC,MAAM,qBAAqB,GAAG,eAAe,CAAC;AAErD;+FAC+F;AAC/F,MAAM,CAAC,MAAM,sBAAsB,GAAG,sBAAsB,CAAC","sourcesContent":["// Well-known keys used in browser sessionStorage / localStorage.\n\n/** sessionStorage key holding the path the user wanted before being redirected to login. */\nexport const REDIRECT_PATH_KEY = 'redirectPath';\n\n/** localStorage key holding the last-seen app version (used by version-gate component). */\nexport const LS_VERSION_KEY = 'ttt-app-version';\n\n/** sessionStorage key marking that a version-mismatch reload was already attempted. */\nexport const SS_RELOAD_ATTEMPTED_KEY = 'ttt-version-reload-attempted';\n\n// --- Company / Green Room dock companion (device-local v1 stores) ---\n// Values are byte-stable for backward compatibility — the historical 'bill'\n// naming predates the Company rename and MUST NOT change.\n\n/** localStorage key holding the user's chosen dock companion id ('bill' | 'kit'). */\nexport const COMPANION_STORAGE_KEY = 'ttt-company-companion';\n\n/** localStorage key: 'true' when the user has hidden the dock companion entirely. */\nexport const MASCOT_HIDDEN_STORAGE_KEY = 'ttt-bill-hidden';\n\n/** localStorage key holding the last-shown dock-bubble line index (avoids an\n * immediate repeat across visits). */\nexport const MASCOT_LINE_INDEX_STORAGE_KEY = 'ttt-bill-line-index';\n\n/** Same-tab window event dispatched when MASCOT_HIDDEN_STORAGE_KEY changes\n * (localStorage 'storage' events do not fire in the writing tab). */\nexport const MASCOT_HIDDEN_CHANGE_EVENT = 'ttt-bill-pref-change';\n\n/** Same-tab window event dispatched when COMPANION_STORAGE_KEY changes. */\nexport const COMPANION_CHANGE_EVENT = 'ttt-company-companion-change';\n\n/** Same-tab window event dispatched when the transient dock-puppet pose changes\n * (in-memory store; never persisted). */\nexport const MASCOT_POSE_CHANGE_EVENT = 'ttt-bill-pose-change';\n\n// --- Manual reduced-motion House control (device-local) ---\n// Independent of the companion visibility store above: reducing motion does not hide the\n// companion, and hiding the companion does not change motion. Effective reduced motion is\n// (the device's prefers-reduced-motion request) OR (this manual preference); the device\n// request always wins. Device-local BY DESIGN — never mirrored to Firestore or the private\n// user document (unlike the account-durable site-tour state).\n\n/** localStorage key: 'true' when the member has manually enabled TTT's app-wide\n * reduced-motion preference (the \"Motion: Full / Reduced\" House control). */\nexport const REDUCED_MOTION_STORAGE_KEY = 'ttt-reduced-motion';\n\n/** Same-tab window event dispatched when REDUCED_MOTION_STORAGE_KEY changes (localStorage\n * 'storage' events do not fire in the writing tab), mirroring COMPANION_CHANGE_EVENT. */\nexport const REDUCED_MOTION_CHANGE_EVENT = 'ttt-reduced-motion-change';\n\n// --- Large-text House control (device-local) ---\n// The root font-size scale behind the House \"Text size\" control. Same device-local\n// useSyncExternalStore shape as the reduced-motion control above — never mirrored to Firestore\n// or the private user document. The <html> CSS hook it applies stays app-side next to the rule\n// that defines it (as the reduced-motion store's root attribute does).\n\n/** localStorage key holding the member's text-size preference ('standard' | 'large'). */\nexport const TEXT_SIZE_STORAGE_KEY = 'ttt-text-size';\n\n/** Same-tab window event dispatched when TEXT_SIZE_STORAGE_KEY changes (localStorage\n * 'storage' events do not fire in the writing tab), mirroring REDUCED_MOTION_CHANGE_EVENT. */\nexport const TEXT_SIZE_CHANGE_EVENT = 'ttt-text-size-change';\n"]}
|
|
1
|
+
{"version":3,"file":"storage-keys.js","sourceRoot":"","sources":["../../src/constants/storage-keys.ts"],"names":[],"mappings":"AAAA,iEAAiE;AAEjE,4FAA4F;AAC5F,MAAM,CAAC,MAAM,iBAAiB,GAAG,cAAc,CAAC;AAEhD,2FAA2F;AAC3F,MAAM,CAAC,MAAM,cAAc,GAAG,iBAAiB,CAAC;AAEhD,uFAAuF;AACvF,MAAM,CAAC,MAAM,uBAAuB,GAAG,8BAA8B,CAAC;AAEtE,uEAAuE;AACvE,4EAA4E;AAC5E,0DAA0D;AAE1D,qFAAqF;AACrF,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAuB,CAAC;AAE7D,qFAAqF;AACrF,MAAM,CAAC,MAAM,yBAAyB,GAAG,iBAAiB,CAAC;AAE3D;uCACuC;AACvC,MAAM,CAAC,MAAM,6BAA6B,GAAG,qBAAqB,CAAC;AAEnE;sEACsE;AACtE,MAAM,CAAC,MAAM,0BAA0B,GAAG,sBAAsB,CAAC;AAEjE,2EAA2E;AAC3E,MAAM,CAAC,MAAM,sBAAsB,GAAG,8BAA8B,CAAC;AAErE;0CAC0C;AAC1C,MAAM,CAAC,MAAM,wBAAwB,GAAG,sBAAsB,CAAC;AAE/D,6DAA6D;AAC7D,yFAAyF;AACzF,0FAA0F;AAC1F,wFAAwF;AACxF,2FAA2F;AAC3F,8DAA8D;AAE9D;8EAC8E;AAC9E,MAAM,CAAC,MAAM,0BAA0B,GAAG,oBAAoB,CAAC;AAE/D;0FAC0F;AAC1F,MAAM,CAAC,MAAM,2BAA2B,GAAG,2BAA2B,CAAC;AAEvE,kDAAkD;AAClD,mFAAmF;AACnF,+FAA+F;AAC/F,+FAA+F;AAC/F,uEAAuE;AAEvE,yFAAyF;AACzF,MAAM,CAAC,MAAM,qBAAqB,GAAG,eAAe,CAAC;AAErD;+FAC+F;AAC/F,MAAM,CAAC,MAAM,sBAAsB,GAAG,sBAAsB,CAAC;AAE7D,6FAA6F;AAC7F,oGAAoG;AACpG,mGAAmG;AACnG,+FAA+F;AAC/F,mGAAmG;AACnG,oGAAoG;AACpG,oGAAoG;AACpG,EAAE;AACF,iGAAiG;AACjG,+FAA+F;AAC/F,mGAAmG;AACnG,yDAAyD;AAEzD;sDACsD;AACtD,MAAM,UAAU,yBAAyB,CAAC,GAAW;IACnD,OAAO,yBAAyB,GAAG,EAAE,CAAC;AACxC,CAAC;AAED;;4FAE4F;AAC5F,MAAM,CAAC,MAAM,8BAA8B,GAAG,8BAA8B,CAAC","sourcesContent":["// Well-known keys used in browser sessionStorage / localStorage.\n\n/** sessionStorage key holding the path the user wanted before being redirected to login. */\nexport const REDIRECT_PATH_KEY = 'redirectPath';\n\n/** localStorage key holding the last-seen app version (used by version-gate component). */\nexport const LS_VERSION_KEY = 'ttt-app-version';\n\n/** sessionStorage key marking that a version-mismatch reload was already attempted. */\nexport const SS_RELOAD_ATTEMPTED_KEY = 'ttt-version-reload-attempted';\n\n// --- Company / Green Room dock companion (device-local v1 stores) ---\n// Values are byte-stable for backward compatibility — the historical 'bill'\n// naming predates the Company rename and MUST NOT change.\n\n/** localStorage key holding the user's chosen dock companion id ('bill' | 'kit'). */\nexport const COMPANION_STORAGE_KEY = 'ttt-company-companion';\n\n/** localStorage key: 'true' when the user has hidden the dock companion entirely. */\nexport const MASCOT_HIDDEN_STORAGE_KEY = 'ttt-bill-hidden';\n\n/** localStorage key holding the last-shown dock-bubble line index (avoids an\n * immediate repeat across visits). */\nexport const MASCOT_LINE_INDEX_STORAGE_KEY = 'ttt-bill-line-index';\n\n/** Same-tab window event dispatched when MASCOT_HIDDEN_STORAGE_KEY changes\n * (localStorage 'storage' events do not fire in the writing tab). */\nexport const MASCOT_HIDDEN_CHANGE_EVENT = 'ttt-bill-pref-change';\n\n/** Same-tab window event dispatched when COMPANION_STORAGE_KEY changes. */\nexport const COMPANION_CHANGE_EVENT = 'ttt-company-companion-change';\n\n/** Same-tab window event dispatched when the transient dock-puppet pose changes\n * (in-memory store; never persisted). */\nexport const MASCOT_POSE_CHANGE_EVENT = 'ttt-bill-pose-change';\n\n// --- Manual reduced-motion House control (device-local) ---\n// Independent of the companion visibility store above: reducing motion does not hide the\n// companion, and hiding the companion does not change motion. Effective reduced motion is\n// (the device's prefers-reduced-motion request) OR (this manual preference); the device\n// request always wins. Device-local BY DESIGN — never mirrored to Firestore or the private\n// user document (unlike the account-durable site-tour state).\n\n/** localStorage key: 'true' when the member has manually enabled TTT's app-wide\n * reduced-motion preference (the \"Motion: Full / Reduced\" House control). */\nexport const REDUCED_MOTION_STORAGE_KEY = 'ttt-reduced-motion';\n\n/** Same-tab window event dispatched when REDUCED_MOTION_STORAGE_KEY changes (localStorage\n * 'storage' events do not fire in the writing tab), mirroring COMPANION_CHANGE_EVENT. */\nexport const REDUCED_MOTION_CHANGE_EVENT = 'ttt-reduced-motion-change';\n\n// --- Large-text House control (device-local) ---\n// The root font-size scale behind the House \"Text size\" control. Same device-local\n// useSyncExternalStore shape as the reduced-motion control above — never mirrored to Firestore\n// or the private user document. The <html> CSS hook it applies stays app-side next to the rule\n// that defines it (as the reduced-motion store's root attribute does).\n\n/** localStorage key holding the member's text-size preference ('standard' | 'large'). */\nexport const TEXT_SIZE_STORAGE_KEY = 'ttt-text-size';\n\n/** Same-tab window event dispatched when TEXT_SIZE_STORAGE_KEY changes (localStorage\n * 'storage' events do not fire in the writing tab), mirroring REDUCED_MOTION_CHANGE_EVENT. */\nexport const TEXT_SIZE_CHANGE_EVENT = 'ttt-text-size-change';\n\n// --- First-visit site-tour pending preference (the ONE sanctioned optimistic-hide slot) ---\n// Unlike the House controls above, site-tour state is ACCOUNT-DURABLE: `privateData/{uid}.siteTour`\n// stays the sole authority and the `updateSiteTourPreference` callable stays its sole writer. This\n// key holds a SINGLE uid-scoped entry recording a choice the member has already made but whose\n// server write has not been confirmed yet, so the overlay can close instantly and the write can be\n// replayed on the next boot. It is a one-entry durable retry SLOT, never a cache, mirror, or second\n// source of eligibility — a member with no pending entry is evaluated purely from the server state.\n//\n// UID-SCOPED BY CONSTRUCTION: a browser-global key would let user A's choice suppress (or replay\n// into) the tour for user B after a sign-out/sign-in on the same device. The stored entry ALSO\n// carries its own `uid` (SiteTourPendingPreferenceSchema, schemas/users.ts) and must match the key\n// owner before it may affect eligibility or be replayed.\n\n/** localStorage key holding the caller's single unconfirmed site-tour choice. Scoped by the\n * AUTHENTICATED uid — never a browser-global key. */\nexport function siteTourPendingStorageKey(uid: string): string {\n return `ttt-site-tour-pending:${uid}`;\n}\n\n/** Same-tab window event dispatched when a `siteTourPendingStorageKey(uid)` entry is written or\n * removed (localStorage 'storage' events do not fire in the writing tab), mirroring\n * TEXT_SIZE_CHANGE_EVENT. Cross-tab propagation still rides the native 'storage' event. */\nexport const SITE_TOUR_PENDING_CHANGE_EVENT = 'ttt-site-tour-pending-change';\n"]}
|
|
@@ -122,6 +122,8 @@ export declare const MediaActivationJobSchema: z.ZodObject<{
|
|
|
122
122
|
details: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
123
123
|
at: z.ZodOptional<z.ZodNumber>;
|
|
124
124
|
}, z.core.$strict>>;
|
|
125
|
+
parentKey: z.ZodOptional<z.ZodString>;
|
|
126
|
+
parentWaitStartedAt: z.ZodOptional<z.ZodCustom<import("./firestore-primitives.js").FirestoreTimestampLike, import("./firestore-primitives.js").FirestoreTimestampLike>>;
|
|
125
127
|
createdAt: z.ZodCustom<import("./firestore-primitives.js").FirestoreTimestampLike, import("./firestore-primitives.js").FirestoreTimestampLike>;
|
|
126
128
|
authorityAppliedAt: z.ZodOptional<z.ZodCustom<import("./firestore-primitives.js").FirestoreTimestampLike, import("./firestore-primitives.js").FirestoreTimestampLike>>;
|
|
127
129
|
completedAt: z.ZodOptional<z.ZodCustom<import("./firestore-primitives.js").FirestoreTimestampLike, import("./firestore-primitives.js").FirestoreTimestampLike>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-activation-jobs.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/media-activation-jobs.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,eAAO,MAAM,8BAA8B;;;;;EAKzC,CAAC;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AAEtF,eAAO,MAAM,wBAAwB
|
|
1
|
+
{"version":3,"file":"media-activation-jobs.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/media-activation-jobs.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,eAAO,MAAM,8BAA8B;;;;;EAKzC,CAAC;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AAEtF,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAwD1B,CAAC;AACZ,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
|
|
@@ -42,6 +42,27 @@ export const MediaActivationJobSchema = z
|
|
|
42
42
|
attemptCount: z.number().int().nonnegative(),
|
|
43
43
|
nextAttemptAt: FirestoreTimestampSchema,
|
|
44
44
|
lastError: StructuredErrorSchema.optional(),
|
|
45
|
+
// ===== Parent-publication dependency (the curated-audition absent-parent lane) =====
|
|
46
|
+
// Some publications legitimately arrive before the parent document they attach to
|
|
47
|
+
// exists. The canonical case is an auditionMedia CURATED-lane ENTRY job: the creator
|
|
48
|
+
// uploads the prompt and its option videos in one batch, and the audition document is
|
|
49
|
+
// written by the PROMPT's publish — so an option's publish can run first. That is an
|
|
50
|
+
// expected race, not a fault, and it must not burn the job's normal retry budget.
|
|
51
|
+
//
|
|
52
|
+
// `parentKey` is the id of the publication that must exist first — for the curated
|
|
53
|
+
// audition lane, the `auditionId`. It is set at job-build time ONLY for jobs minted on
|
|
54
|
+
// an absent-parent identity lane; a prompt job never carries it, and neither does an
|
|
55
|
+
// ordinary open-mode entry (its upload surface requires the audition page to already
|
|
56
|
+
// exist, so a missing parent there IS a real failure). The runner may treat a
|
|
57
|
+
// parent-absent publication as a park (rather than a failure) only when this durable key
|
|
58
|
+
// is present, and the prompt's publish uses it to wake its parked siblings.
|
|
59
|
+
//
|
|
60
|
+
// `parentWaitStartedAt` stamps the FIRST parent-absent occurrence and never moves
|
|
61
|
+
// forward, so the bounded wait window is measured from one durable start.
|
|
62
|
+
//
|
|
63
|
+
// BOTH are optional: rows written before this field pair existed still parse unchanged.
|
|
64
|
+
parentKey: z.string().min(1).optional(),
|
|
65
|
+
parentWaitStartedAt: FirestoreTimestampSchema.optional(),
|
|
45
66
|
createdAt: FirestoreTimestampSchema,
|
|
46
67
|
authorityAppliedAt: FirestoreTimestampSchema.optional(),
|
|
47
68
|
completedAt: FirestoreTimestampSchema.optional(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-activation-jobs.js","sourceRoot":"","sources":["../../src/doc-schemas/media-activation-jobs.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,iFAAiF;AACjF,uEAAuE;AACvE,wEAAwE;AACxE,qDAAqD;AACrD,EAAE;AACF,oFAAoF;AACpF,kFAAkF;AAClF,kBAAkB;AAClB,EAAE;AACF,mFAAmF;AACnF,kEAAkE;AAElE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EACL,0BAA0B,EAC1B,iCAAiC,GAClC,MAAM,mBAAmB,CAAC;AAE3B,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC,IAAI,CAAC;IACnD,SAAS,EAAE,8EAA8E;IACzF,kBAAkB,EAAE,gEAAgE;IACpF,UAAU,EAAE,gCAAgC;IAC5C,YAAY,EAAE,iFAAiF;CAChG,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC;KACtC,MAAM,CAAC;IACN,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAE1C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACjC,UAAU,EAAE,gBAAgB;IAE5B,2EAA2E;IAC3E,wDAAwD;IACxD,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IAChD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,gBAAgB,EAAE,iCAAiC;IAEnD,2EAA2E;IAC3E,wDAAwD;IACxD,6DAA6D;IAC7D,eAAe,EAAE,0BAA0B;IAC3C,eAAe,EAAE,CAAC,CAAC,OAAO,EAAE;IAE5B,MAAM,EAAE,8BAA8B;IACtC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IAC5C,aAAa,EAAE,wBAAwB;IACvC,SAAS,EAAE,qBAAqB,CAAC,QAAQ,EAAE;IAE3C,SAAS,EAAE,wBAAwB;IACnC,kBAAkB,EAAE,wBAAwB,CAAC,QAAQ,EAAE;IACvD,WAAW,EAAE,wBAAwB,CAAC,QAAQ,EAAE;IAChD,cAAc,EAAE,wBAAwB,CAAC,QAAQ,EAAE;IACnD,4EAA4E;IAC5E,0DAA0D;IAC1D,QAAQ,EAAE,wBAAwB,CAAC,QAAQ,EAAE;CAC9C,CAAC;KACD,MAAM,EAAE,CAAC","sourcesContent":["// mediaActivationJobs/{jobId} — the durable job that drives the three-stage\n// finalize (prepare → activate → publish) and its crash recovery. Created in the\n// SAME private prepare transaction as mediaAssets/{assetId}; attempted\n// immediately and re-driven by a scheduled recovery worker. Server-only\n// (`allow read, write: if false`); NO client access.\n//\n// See ttt-prod docs/design/media-assets-and-protected-serving.md — the design owner\n// for this job, the three-stage finalize, the typed publication adapters, and the\n// reconcile pass.\n//\n// jobId = hash('media-activation', assetId, authorityVersion) (edge-protocol-core\n// canonical hash family; collision-safe per the frozen ID rules).\n\nimport { z } from 'zod';\nimport { StructuredErrorSchema } from '@ttt-productions/edge-protocol-core';\nimport { FileOriginSchema } from '../media/file-origin.js';\nimport { FirestoreTimestampSchema } from './firestore-primitives.js';\nimport {\n MediaPublicationKindSchema,\n MediaServingAuthorityRecordSchema,\n} from './media-assets.js';\n\nexport const MediaActivationJobStatusSchema = z.enum([\n 'pending', // call the signed activation endpoint, verify the ack, CAS → authorityApplied\n 'authorityApplied', // call the typed publication adapter, on success CAS → complete\n 'complete', // owner published; TTL eligible\n 'deadLetter', // retries exhausted — retained for operator replay; user sees publication-failed\n]);\nexport type MediaActivationJobStatus = z.infer<typeof MediaActivationJobStatusSchema>;\n\nexport const MediaActivationJobSchema = z\n .object({\n jobId: z.string().min(1),\n schemaVersion: z.number().int().positive(),\n\n assetId: z.string().min(1),\n pendingMediaId: z.string().min(1),\n fileOrigin: FileOriginSchema,\n\n // The exact serving record this job activates — the DO must ack this exact\n // version + payloadHash before publication may proceed.\n authorityVersion: z.number().int().nonnegative(),\n payloadHash: z.string().min(1),\n authorityPayload: MediaServingAuthorityRecordSchema,\n\n // Typed publication adapter. `publicationArgs` is forward-validated by the\n // per-kind adapter registry — NEVER arbitrary Firestore\n // writes; the job carries typed data, not serialized writes.\n publicationKind: MediaPublicationKindSchema,\n publicationArgs: z.unknown(),\n\n status: MediaActivationJobStatusSchema,\n attemptCount: z.number().int().nonnegative(),\n nextAttemptAt: FirestoreTimestampSchema,\n lastError: StructuredErrorSchema.optional(),\n\n createdAt: FirestoreTimestampSchema,\n authorityAppliedAt: FirestoreTimestampSchema.optional(),\n completedAt: FirestoreTimestampSchema.optional(),\n deadLetteredAt: FirestoreTimestampSchema.optional(),\n // TTL set ONLY at `complete`; NEVER on pending/authorityApplied/deadLetter.\n // Replay clears terminal/TTL fields (frozen matrix rule).\n expireAt: FirestoreTimestampSchema.optional(),\n })\n .strict();\nexport type MediaActivationJob = z.infer<typeof MediaActivationJobSchema>;\n"]}
|
|
1
|
+
{"version":3,"file":"media-activation-jobs.js","sourceRoot":"","sources":["../../src/doc-schemas/media-activation-jobs.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,iFAAiF;AACjF,uEAAuE;AACvE,wEAAwE;AACxE,qDAAqD;AACrD,EAAE;AACF,oFAAoF;AACpF,kFAAkF;AAClF,kBAAkB;AAClB,EAAE;AACF,mFAAmF;AACnF,kEAAkE;AAElE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EACL,0BAA0B,EAC1B,iCAAiC,GAClC,MAAM,mBAAmB,CAAC;AAE3B,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC,IAAI,CAAC;IACnD,SAAS,EAAE,8EAA8E;IACzF,kBAAkB,EAAE,gEAAgE;IACpF,UAAU,EAAE,gCAAgC;IAC5C,YAAY,EAAE,iFAAiF;CAChG,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC;KACtC,MAAM,CAAC;IACN,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAE1C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACjC,UAAU,EAAE,gBAAgB;IAE5B,2EAA2E;IAC3E,wDAAwD;IACxD,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IAChD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,gBAAgB,EAAE,iCAAiC;IAEnD,2EAA2E;IAC3E,wDAAwD;IACxD,6DAA6D;IAC7D,eAAe,EAAE,0BAA0B;IAC3C,eAAe,EAAE,CAAC,CAAC,OAAO,EAAE;IAE5B,MAAM,EAAE,8BAA8B;IACtC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;IAC5C,aAAa,EAAE,wBAAwB;IACvC,SAAS,EAAE,qBAAqB,CAAC,QAAQ,EAAE;IAE3C,sFAAsF;IACtF,kFAAkF;IAClF,qFAAqF;IACrF,sFAAsF;IACtF,qFAAqF;IACrF,kFAAkF;IAClF,EAAE;IACF,mFAAmF;IACnF,uFAAuF;IACvF,qFAAqF;IACrF,qFAAqF;IACrF,8EAA8E;IAC9E,yFAAyF;IACzF,4EAA4E;IAC5E,EAAE;IACF,kFAAkF;IAClF,0EAA0E;IAC1E,EAAE;IACF,wFAAwF;IACxF,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACvC,mBAAmB,EAAE,wBAAwB,CAAC,QAAQ,EAAE;IAExD,SAAS,EAAE,wBAAwB;IACnC,kBAAkB,EAAE,wBAAwB,CAAC,QAAQ,EAAE;IACvD,WAAW,EAAE,wBAAwB,CAAC,QAAQ,EAAE;IAChD,cAAc,EAAE,wBAAwB,CAAC,QAAQ,EAAE;IACnD,4EAA4E;IAC5E,0DAA0D;IAC1D,QAAQ,EAAE,wBAAwB,CAAC,QAAQ,EAAE;CAC9C,CAAC;KACD,MAAM,EAAE,CAAC","sourcesContent":["// mediaActivationJobs/{jobId} — the durable job that drives the three-stage\n// finalize (prepare → activate → publish) and its crash recovery. Created in the\n// SAME private prepare transaction as mediaAssets/{assetId}; attempted\n// immediately and re-driven by a scheduled recovery worker. Server-only\n// (`allow read, write: if false`); NO client access.\n//\n// See ttt-prod docs/design/media-assets-and-protected-serving.md — the design owner\n// for this job, the three-stage finalize, the typed publication adapters, and the\n// reconcile pass.\n//\n// jobId = hash('media-activation', assetId, authorityVersion) (edge-protocol-core\n// canonical hash family; collision-safe per the frozen ID rules).\n\nimport { z } from 'zod';\nimport { StructuredErrorSchema } from '@ttt-productions/edge-protocol-core';\nimport { FileOriginSchema } from '../media/file-origin.js';\nimport { FirestoreTimestampSchema } from './firestore-primitives.js';\nimport {\n MediaPublicationKindSchema,\n MediaServingAuthorityRecordSchema,\n} from './media-assets.js';\n\nexport const MediaActivationJobStatusSchema = z.enum([\n 'pending', // call the signed activation endpoint, verify the ack, CAS → authorityApplied\n 'authorityApplied', // call the typed publication adapter, on success CAS → complete\n 'complete', // owner published; TTL eligible\n 'deadLetter', // retries exhausted — retained for operator replay; user sees publication-failed\n]);\nexport type MediaActivationJobStatus = z.infer<typeof MediaActivationJobStatusSchema>;\n\nexport const MediaActivationJobSchema = z\n .object({\n jobId: z.string().min(1),\n schemaVersion: z.number().int().positive(),\n\n assetId: z.string().min(1),\n pendingMediaId: z.string().min(1),\n fileOrigin: FileOriginSchema,\n\n // The exact serving record this job activates — the DO must ack this exact\n // version + payloadHash before publication may proceed.\n authorityVersion: z.number().int().nonnegative(),\n payloadHash: z.string().min(1),\n authorityPayload: MediaServingAuthorityRecordSchema,\n\n // Typed publication adapter. `publicationArgs` is forward-validated by the\n // per-kind adapter registry — NEVER arbitrary Firestore\n // writes; the job carries typed data, not serialized writes.\n publicationKind: MediaPublicationKindSchema,\n publicationArgs: z.unknown(),\n\n status: MediaActivationJobStatusSchema,\n attemptCount: z.number().int().nonnegative(),\n nextAttemptAt: FirestoreTimestampSchema,\n lastError: StructuredErrorSchema.optional(),\n\n // ===== Parent-publication dependency (the curated-audition absent-parent lane) =====\n // Some publications legitimately arrive before the parent document they attach to\n // exists. The canonical case is an auditionMedia CURATED-lane ENTRY job: the creator\n // uploads the prompt and its option videos in one batch, and the audition document is\n // written by the PROMPT's publish — so an option's publish can run first. That is an\n // expected race, not a fault, and it must not burn the job's normal retry budget.\n //\n // `parentKey` is the id of the publication that must exist first — for the curated\n // audition lane, the `auditionId`. It is set at job-build time ONLY for jobs minted on\n // an absent-parent identity lane; a prompt job never carries it, and neither does an\n // ordinary open-mode entry (its upload surface requires the audition page to already\n // exist, so a missing parent there IS a real failure). The runner may treat a\n // parent-absent publication as a park (rather than a failure) only when this durable key\n // is present, and the prompt's publish uses it to wake its parked siblings.\n //\n // `parentWaitStartedAt` stamps the FIRST parent-absent occurrence and never moves\n // forward, so the bounded wait window is measured from one durable start.\n //\n // BOTH are optional: rows written before this field pair existed still parse unchanged.\n parentKey: z.string().min(1).optional(),\n parentWaitStartedAt: FirestoreTimestampSchema.optional(),\n\n createdAt: FirestoreTimestampSchema,\n authorityAppliedAt: FirestoreTimestampSchema.optional(),\n completedAt: FirestoreTimestampSchema.optional(),\n deadLetteredAt: FirestoreTimestampSchema.optional(),\n // TTL set ONLY at `complete`; NEVER on pending/authorityApplied/deadLetter.\n // Replay clears terminal/TTL fields (frozen matrix rule).\n expireAt: FirestoreTimestampSchema.optional(),\n })\n .strict();\nexport type MediaActivationJob = z.infer<typeof MediaActivationJobSchema>;\n"]}
|
|
@@ -159,12 +159,28 @@ export declare const MediaRetentionPolicySchema: z.ZodEnum<{
|
|
|
159
159
|
legalHold: "legalHold";
|
|
160
160
|
}>;
|
|
161
161
|
export type MediaRetentionPolicy = z.infer<typeof MediaRetentionPolicySchema>;
|
|
162
|
+
export declare const REALM_FILE_CANON_STATUS_VALUES: readonly ["none", "pendingApproval", "nonCanon", "canon"];
|
|
162
163
|
export declare const RealmFileCanonStatusSchema: z.ZodEnum<{
|
|
163
164
|
none: "none";
|
|
165
|
+
pendingApproval: "pendingApproval";
|
|
164
166
|
nonCanon: "nonCanon";
|
|
165
167
|
canon: "canon";
|
|
166
168
|
}>;
|
|
167
169
|
export type RealmFileCanonStatus = z.infer<typeof RealmFileCanonStatusSchema>;
|
|
170
|
+
/** The two APPROVED (steward-accepted, realm-served) standings. The member gallery query
|
|
171
|
+
* and its projection accept exactly these — never the full status union, so a pending or
|
|
172
|
+
* unshared row can never be typed into an approved-files response. Derived from the one
|
|
173
|
+
* union above; consumers import this instead of re-quoting the members (ARCH-102). */
|
|
174
|
+
export declare const REALM_FILE_APPROVED_STATUS_VALUES: readonly ["nonCanon", "canon"];
|
|
175
|
+
export declare const RealmFileApprovedStatusSchema: z.ZodEnum<{
|
|
176
|
+
nonCanon: "nonCanon";
|
|
177
|
+
canon: "canon";
|
|
178
|
+
}>;
|
|
179
|
+
export type RealmFileApprovedStatus = z.infer<typeof RealmFileApprovedStatusSchema>;
|
|
180
|
+
/** The single AWAITING-DECISION standing. The steward promotion-queue projection accepts
|
|
181
|
+
* only this, so an approved or unshared row can never be typed into the queue. */
|
|
182
|
+
export declare const RealmFilePendingApprovalStatusSchema: z.ZodLiteral<"pendingApproval">;
|
|
183
|
+
export type RealmFilePendingApprovalStatus = z.infer<typeof RealmFilePendingApprovalStatusSchema>;
|
|
168
184
|
/** Whether the canonical serving record has been applied to the DO authority. */
|
|
169
185
|
export declare const MediaAuthoritySyncStateSchema: z.ZodEnum<{
|
|
170
186
|
pending: "pending";
|
|
@@ -444,9 +460,14 @@ export declare const MediaAssetSchema: z.ZodObject<{
|
|
|
444
460
|
}, z.core.$strict>>;
|
|
445
461
|
realmFileCanonStatus: z.ZodEnum<{
|
|
446
462
|
none: "none";
|
|
463
|
+
pendingApproval: "pendingApproval";
|
|
447
464
|
nonCanon: "nonCanon";
|
|
448
465
|
canon: "canon";
|
|
449
466
|
}>;
|
|
467
|
+
realmFileFolderId: z.ZodOptional<z.ZodString>;
|
|
468
|
+
realmFileShareRequestId: z.ZodOptional<z.ZodString>;
|
|
469
|
+
realmFileShareRequestedByUid: z.ZodOptional<z.ZodString>;
|
|
470
|
+
realmFileShareRequestedAt: z.ZodOptional<z.ZodNumber>;
|
|
450
471
|
authorityVersion: z.ZodOptional<z.ZodNumber>;
|
|
451
472
|
authorityPayloadHash: z.ZodOptional<z.ZodString>;
|
|
452
473
|
authoritySyncState: z.ZodOptional<z.ZodEnum<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-assets.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/media-assets.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,6DAA6D;AAC7D,eAAO,MAAM,qBAAqB;;;;;EAAsD,CAAC;AACzF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;4DAC4D;AAC5D,eAAO,MAAM,wBAAwB;;;;;EAA2D,CAAC;AACjG,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E;;uCAEuC;AACvC,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"media-assets.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/media-assets.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,6DAA6D;AAC7D,eAAO,MAAM,qBAAqB;;;;;EAAsD,CAAC;AACzF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;4DAC4D;AAC5D,eAAO,MAAM,wBAAwB;;;;;EAA2D,CAAC;AACjG,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E;;uCAEuC;AACvC,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;EAsBpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAM5E;;uFAEuF;AACvF,eAAO,MAAM,sBAAsB;;;;EAAsC,CAAC;AAC1E,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,8CAA+C,CAAC;AAC/E,eAAO,MAAM,qBAAqB;;;;;EAA6B,CAAC;AAChE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;;;iCAKiC;AACjC,eAAO,MAAM,qBAAqB;;;;;;;;EAQhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;;;;;;;GASG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA0B5B,CAAC;AACZ,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E,eAAO,MAAM,uBAAuB;;;;;;;kBAyBzB,CAAC;AACZ,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,eAAO,MAAM,0BAA0B;;;;EAIrC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAc9E,eAAO,MAAM,8BAA8B,2DAKjC,CAAC;AACX,eAAO,MAAM,0BAA0B;;;;;EAAyC,CAAC;AACjF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E;;;uFAGuF;AACvF,eAAO,MAAM,iCAAiC,gCAAiC,CAAC;AAChF,eAAO,MAAM,6BAA6B;;;EAA4C,CAAC;AACvF,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAEpF;mFACmF;AACnF,eAAO,MAAM,oCAAoC,iCAA+B,CAAC;AACjF,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oCAAoC,CAAC,CAAC;AAMlG,iFAAiF;AACjF,eAAO,MAAM,6BAA6B;;;;EAA+C,CAAC;AAC1F,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAEpF;iFACiF;AACjF,eAAO,MAAM,gCAAgC;;;;EAAkD,CAAC;AAChG,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAC;AAE1F;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;4BAkBlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE;;;;GAIG;AACH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;EAoBrC,CAAC;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E;;;;;;GAMG;AACH,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAiBnC,CAAC;AACZ,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAC;AAE5F,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAsI3B,CAAC;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC"}
|
|
@@ -30,7 +30,12 @@ export const MediaAssetOwnerTypeSchema = z.enum([
|
|
|
30
30
|
// admin-support). Replaces the removed `guildChatAttachment` owner type — chat
|
|
31
31
|
// messages no longer own media.
|
|
32
32
|
'conversationFile',
|
|
33
|
-
|
|
33
|
+
// Realm shared files are the deliberate MUTATE-IN-PLACE exception: a promoted work file
|
|
34
|
+
// keeps its ONE `workFile`-owned asset doc and flips tier in place, so no asset is ever
|
|
35
|
+
// owned by `realmFile` today. The owner type stays declared for a future realm-owned
|
|
36
|
+
// media surface; it is NOT the seam realm sharing rides (that is `realmFileCanonStatus`
|
|
37
|
+
// + `realmId` + `realmFileFolderId` on the work file's own asset).
|
|
38
|
+
'realmFile',
|
|
34
39
|
'safetyEvidence', // inert system sentinel — synthetic NCII-evidence assets (never an account surface)
|
|
35
40
|
]);
|
|
36
41
|
// ===== Media origin lineage (Appendix A0) =====
|
|
@@ -131,13 +136,34 @@ export const MediaRetentionPolicySchema = z.enum([
|
|
|
131
136
|
'preserveForTrustAndSafety',
|
|
132
137
|
'legalHold',
|
|
133
138
|
]);
|
|
134
|
-
// Realm shared-files: a work file's standing in its realm's shared pool.
|
|
135
|
-
//
|
|
136
|
-
//
|
|
137
|
-
//
|
|
139
|
+
// Realm shared-files: a work file's standing in its realm's shared pool. ONE seam — the
|
|
140
|
+
// approval gate is a value in this union, never a parallel status field.
|
|
141
|
+
// none — not shared to the realm (default)
|
|
142
|
+
// pendingApproval — a Work file admin has REQUESTED promotion; the Realm steward has not
|
|
143
|
+
// decided yet. The file is NOT served to the Realm (tier stays `scoped`)
|
|
144
|
+
// and is invisible to the member gallery, whose query selects only
|
|
145
|
+
// nonCanon|canon — so pending rows are excluded structurally, not by a
|
|
146
|
+
// filter someone can forget.
|
|
147
|
+
// nonCanon — approved into the realm's pool (in a steward-chosen folder), non-canon
|
|
148
|
+
// canon — approved and marked canon (realm steward toggles canon ↔ nonCanon)
|
|
138
149
|
// Moderation/takedown is NOT a value here — a hidden file is hidden via the shared
|
|
139
150
|
// media path (`servingStatus: 'hidden'`), so the gallery filters on servingStatus.
|
|
140
|
-
export const
|
|
151
|
+
export const REALM_FILE_CANON_STATUS_VALUES = [
|
|
152
|
+
'none',
|
|
153
|
+
'pendingApproval',
|
|
154
|
+
'nonCanon',
|
|
155
|
+
'canon',
|
|
156
|
+
];
|
|
157
|
+
export const RealmFileCanonStatusSchema = z.enum(REALM_FILE_CANON_STATUS_VALUES);
|
|
158
|
+
/** The two APPROVED (steward-accepted, realm-served) standings. The member gallery query
|
|
159
|
+
* and its projection accept exactly these — never the full status union, so a pending or
|
|
160
|
+
* unshared row can never be typed into an approved-files response. Derived from the one
|
|
161
|
+
* union above; consumers import this instead of re-quoting the members (ARCH-102). */
|
|
162
|
+
export const REALM_FILE_APPROVED_STATUS_VALUES = ['nonCanon', 'canon'];
|
|
163
|
+
export const RealmFileApprovedStatusSchema = z.enum(REALM_FILE_APPROVED_STATUS_VALUES);
|
|
164
|
+
/** The single AWAITING-DECISION standing. The steward promotion-queue projection accepts
|
|
165
|
+
* only this, so an approved or unshared row can never be typed into the queue. */
|
|
166
|
+
export const RealmFilePendingApprovalStatusSchema = z.literal('pendingApproval');
|
|
141
167
|
// ===== Serving authority (Durable Object) + publication gating =====
|
|
142
168
|
// See ttt-prod docs/design/media-assets-and-protected-serving.md (the design owner
|
|
143
169
|
// for the Durable Object serving authority and publication gating).
|
|
@@ -262,10 +288,29 @@ export const MediaAssetSchema = z.object({
|
|
|
262
288
|
// before the lineage rollout still parse; set server-side at first accepted
|
|
263
289
|
// ingest, inherited unchanged by every copy/variant. Never client-supplied.
|
|
264
290
|
originLineage: MediaOriginLineageV1Schema.optional(),
|
|
265
|
-
// Realm shared-files seam
|
|
266
|
-
// creation to 'none' and moved
|
|
267
|
-
//
|
|
291
|
+
// ===== Realm shared-files seam (request → steward approval → foldered pool) =====
|
|
292
|
+
// A file's standing in its realm's shared pool; set at creation to 'none' and moved
|
|
293
|
+
// ONLY by the realm shared-files callables. The legal combinations of this field with
|
|
294
|
+
// `realmId`, `realmFileFolderId`, and the three request fields are ENFORCED by the
|
|
295
|
+
// refinement below — the fields are not independently optional.
|
|
268
296
|
realmFileCanonStatus: RealmFileCanonStatusSchema,
|
|
297
|
+
// The steward-chosen folder under `workRealms/{realmId}/realmFileFolders/{id}`. There is
|
|
298
|
+
// no default folder: approval IS the folder assignment, so every approved file is in a
|
|
299
|
+
// folder by construction. Cleared on decline, withdrawal, and admin un-share — but
|
|
300
|
+
// PRESERVED through moderation hide/restore (hide is reversible and changes serving state
|
|
301
|
+
// only; clearing it would restore an approved file with no folder and lose the steward's
|
|
302
|
+
// organization).
|
|
303
|
+
realmFileFolderId: z.string().min(1).optional(),
|
|
304
|
+
// Pending-request metadata, present ONLY while `realmFileCanonStatus === 'pendingApproval'`.
|
|
305
|
+
// `realmFileShareRequestId` is the CLIENT-GENERATED stable request id carried by the
|
|
306
|
+
// request input; approval, decline, and withdrawal all compare against it, so a stale tab
|
|
307
|
+
// can never decide a newer re-request. `realmFileShareRequestedByUid` is the recorded
|
|
308
|
+
// requester — the resolution notification is addressed from THIS field, never guessed from
|
|
309
|
+
// `createdByUid` (the uploader and the promoting file admin are frequently different
|
|
310
|
+
// people). `realmFileShareRequestedAt` is epoch ms (ARCH-105).
|
|
311
|
+
realmFileShareRequestId: z.string().min(1).optional(),
|
|
312
|
+
realmFileShareRequestedByUid: z.string().min(1).optional(),
|
|
313
|
+
realmFileShareRequestedAt: z.number().optional(),
|
|
269
314
|
// Serving authority + publication gating. Additive/optional so assets
|
|
270
315
|
// written before the authority build still parse: absent authorityVersion ⇒
|
|
271
316
|
// 0/never-applied, absent publicationState ⇒ 'unpublished'. Every
|
|
@@ -285,5 +330,58 @@ export const MediaAssetSchema = z.object({
|
|
|
285
330
|
authoritySyncNextAttemptAt: z.number().optional(),
|
|
286
331
|
createdAt: z.number(),
|
|
287
332
|
updatedAt: z.number(),
|
|
288
|
-
}).strict()
|
|
333
|
+
}).strict().superRefine((val, ctx) => {
|
|
334
|
+
// ===== Realm-file legal-combination invariant =====
|
|
335
|
+
// The realm-file field GROUP is one state machine, not five independently-optional
|
|
336
|
+
// fields. Declared HERE, on the canonical doc schema (ARCH-102), so every writer inherits
|
|
337
|
+
// it from one parse instead of each transition re-deciding — and so no reader ever has to
|
|
338
|
+
// defend against a half-written state (an approved file with no folder, a pending file
|
|
339
|
+
// already flipped into the realm, a decline that left request metadata behind).
|
|
340
|
+
//
|
|
341
|
+
// none → no realmId, no folder, no request fields
|
|
342
|
+
// pendingApproval → realmId + ALL THREE request fields; NO folder (approval assigns it)
|
|
343
|
+
// nonCanon|canon → realmId + folder; NO request fields (the request is resolved)
|
|
344
|
+
//
|
|
345
|
+
// DELIBERATELY NOT CONSTRAINED HERE: `accessTier`. Tier is origin-dependent across the
|
|
346
|
+
// whole asset universe (this one schema covers every media origin, not just work files),
|
|
347
|
+
// so binding tier to a realm-file status would misjudge assets that have nothing to do
|
|
348
|
+
// with realms. Tier correctness on these transitions (`scoped` while pending, `artisan`
|
|
349
|
+
// once approved) is enforced by the callable transactions and their tests.
|
|
350
|
+
// `servingStatus` stays orthogonal too — moderation hide/quarantine is independent of a
|
|
351
|
+
// file's realm standing.
|
|
352
|
+
const requestFields = [
|
|
353
|
+
['realmFileShareRequestId', val.realmFileShareRequestId],
|
|
354
|
+
['realmFileShareRequestedByUid', val.realmFileShareRequestedByUid],
|
|
355
|
+
['realmFileShareRequestedAt', val.realmFileShareRequestedAt],
|
|
356
|
+
];
|
|
357
|
+
const forbid = (path, value, message) => {
|
|
358
|
+
if (value !== undefined)
|
|
359
|
+
ctx.addIssue({ code: 'custom', path: [path], message });
|
|
360
|
+
};
|
|
361
|
+
const require_ = (path, value, message) => {
|
|
362
|
+
if (value === undefined)
|
|
363
|
+
ctx.addIssue({ code: 'custom', path: [path], message });
|
|
364
|
+
};
|
|
365
|
+
if (val.realmFileCanonStatus === 'none') {
|
|
366
|
+
forbid('realmId', val.realmId, 'realmId is only set on a realm-shared or pending asset (realmFileCanonStatus is "none")');
|
|
367
|
+
forbid('realmFileFolderId', val.realmFileFolderId, 'realmFileFolderId is only set on an APPROVED realm-shared asset (realmFileCanonStatus is "none")');
|
|
368
|
+
for (const [path, value] of requestFields) {
|
|
369
|
+
forbid(path, value, `${path} is only set while a promotion request is pending (realmFileCanonStatus is "none")`);
|
|
370
|
+
}
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
require_('realmId', val.realmId, `realmId is required whenever realmFileCanonStatus is "${val.realmFileCanonStatus}"`);
|
|
374
|
+
if (val.realmFileCanonStatus === 'pendingApproval') {
|
|
375
|
+
forbid('realmFileFolderId', val.realmFileFolderId, 'a pending request has no folder yet — the steward assigns the folder AT approval');
|
|
376
|
+
for (const [path, value] of requestFields) {
|
|
377
|
+
require_(path, value, `${path} is required while realmFileCanonStatus is "pendingApproval"`);
|
|
378
|
+
}
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
// 'nonCanon' | 'canon' — approved into the pool.
|
|
382
|
+
require_('realmFileFolderId', val.realmFileFolderId, `realmFileFolderId is required on an approved realm file (realmFileCanonStatus is "${val.realmFileCanonStatus}")`);
|
|
383
|
+
for (const [path, value] of requestFields) {
|
|
384
|
+
forbid(path, value, `${path} must be cleared once the request is resolved (realmFileCanonStatus is "${val.realmFileCanonStatus}")`);
|
|
385
|
+
}
|
|
386
|
+
});
|
|
289
387
|
//# sourceMappingURL=media-assets.js.map
|