@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.
Files changed (70) hide show
  1. package/dist/constants/business-work-project.d.ts +17 -0
  2. package/dist/constants/business-work-project.d.ts.map +1 -1
  3. package/dist/constants/business-work-project.js +17 -0
  4. package/dist/constants/business-work-project.js.map +1 -1
  5. package/dist/constants/pagination.d.ts +13 -0
  6. package/dist/constants/pagination.d.ts.map +1 -1
  7. package/dist/constants/pagination.js +13 -0
  8. package/dist/constants/pagination.js.map +1 -1
  9. package/dist/constants/storage-keys.d.ts +7 -0
  10. package/dist/constants/storage-keys.d.ts.map +1 -1
  11. package/dist/constants/storage-keys.js +21 -0
  12. package/dist/constants/storage-keys.js.map +1 -1
  13. package/dist/doc-schemas/media-activation-jobs.d.ts +2 -0
  14. package/dist/doc-schemas/media-activation-jobs.d.ts.map +1 -1
  15. package/dist/doc-schemas/media-activation-jobs.js +21 -0
  16. package/dist/doc-schemas/media-activation-jobs.js.map +1 -1
  17. package/dist/doc-schemas/media-assets.d.ts +21 -0
  18. package/dist/doc-schemas/media-assets.d.ts.map +1 -1
  19. package/dist/doc-schemas/media-assets.js +108 -10
  20. package/dist/doc-schemas/media-assets.js.map +1 -1
  21. package/dist/doc-schemas/registry.d.ts +18 -0
  22. package/dist/doc-schemas/registry.d.ts.map +1 -1
  23. package/dist/doc-schemas/registry.js +4 -1
  24. package/dist/doc-schemas/registry.js.map +1 -1
  25. package/dist/doc-schemas/user.d.ts.map +1 -1
  26. package/dist/doc-schemas/user.js +2 -1
  27. package/dist/doc-schemas/user.js.map +1 -1
  28. package/dist/doc-schemas/work-project.d.ts +13 -0
  29. package/dist/doc-schemas/work-project.d.ts.map +1 -1
  30. package/dist/doc-schemas/work-project.js +36 -0
  31. package/dist/doc-schemas/work-project.js.map +1 -1
  32. package/dist/notifications/index.d.ts.map +1 -1
  33. package/dist/notifications/index.js +41 -0
  34. package/dist/notifications/index.js.map +1 -1
  35. package/dist/paths/collection-refs.d.ts +1 -0
  36. package/dist/paths/collection-refs.d.ts.map +1 -1
  37. package/dist/paths/collection-refs.js +5 -1
  38. package/dist/paths/collection-refs.js.map +1 -1
  39. package/dist/paths/collections.d.ts +7 -0
  40. package/dist/paths/collections.d.ts.map +1 -1
  41. package/dist/paths/collections.js +10 -0
  42. package/dist/paths/collections.js.map +1 -1
  43. package/dist/paths/path-builders.d.ts +1 -0
  44. package/dist/paths/path-builders.d.ts.map +1 -1
  45. package/dist/paths/path-builders.js +4 -1
  46. package/dist/paths/path-builders.js.map +1 -1
  47. package/dist/permissions/work-project-permissions-data.d.ts +1 -1
  48. package/dist/permissions/work-project-permissions-data.d.ts.map +1 -1
  49. package/dist/permissions/work-project-permissions-data.js +5 -3
  50. package/dist/permissions/work-project-permissions-data.js.map +1 -1
  51. package/dist/schemas/atoms.d.ts +17 -0
  52. package/dist/schemas/atoms.d.ts.map +1 -1
  53. package/dist/schemas/atoms.js +17 -0
  54. package/dist/schemas/atoms.js.map +1 -1
  55. package/dist/schemas/notification.d.ts +23 -1
  56. package/dist/schemas/notification.d.ts.map +1 -1
  57. package/dist/schemas/notification.js +41 -2
  58. package/dist/schemas/notification.js.map +1 -1
  59. package/dist/schemas/users.d.ts +22 -0
  60. package/dist/schemas/users.d.ts.map +1 -1
  61. package/dist/schemas/users.js +53 -2
  62. package/dist/schemas/users.js.map +1 -1
  63. package/dist/schemas/work-project-management.d.ts +151 -1
  64. package/dist/schemas/work-project-management.d.ts.map +1 -1
  65. package/dist/schemas/work-project-management.js +173 -17
  66. package/dist/schemas/work-project-management.js.map +1 -1
  67. package/dist/types/audit.d.ts +1 -1
  68. package/dist/types/audit.d.ts.map +1 -1
  69. package/dist/types/audit.js.map +1 -1
  70. 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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAkC1B,CAAC;AACZ,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
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":"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"}
1
+ {"version":3,"file":"media-assets.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/media-assets.ts"],"names":[],"mappings":"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"}
@@ -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
- 'realmFile', // reserved seam — realm shared files are post-launch
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
- // none — not shared to the realm (default)
136
- // nonCanon — shared to the realm's pool, non-canon
137
- // canon shared and marked canon (realm steward/owner toggles canon nonCanon)
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 RealmFileCanonStatusSchema = z.enum(['none', 'nonCanon', 'canon']);
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. A file's standing in its realm's shared pool; set at
266
- // creation to 'none' and moved by the realm shared-files callables. Attribution
267
- // fields (who set canon, when) are added by that feature when it ships.
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