@ttt-productions/ttt-core 0.79.20 → 0.79.21

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.
@@ -39,6 +39,22 @@ export declare const MAX_WORK_FILE_STORAGE_BYTES: number;
39
39
  * platform-wide; there is deliberately no second realm-specific length.
40
40
  */
41
41
  export declare const MAX_REALM_FILE_FOLDERS = 30;
42
+ /**
43
+ * Maximum length of a realm-file promotion `requestId`.
44
+ *
45
+ * This is the FIRST client-minted, client-CHOSEN id in the set that is durably PERSISTED:
46
+ * it lands on the `mediaAssets` doc, in the audit payload, in notification metadata, and in
47
+ * the notification aggregation key. Every one of those is an attacker-reachable write
48
+ * amplification if the id is unbounded, so the bound belongs on the atom, not on each
49
+ * call site.
50
+ *
51
+ * 64 is the smallest bound that comfortably fits what the client actually mints — a
52
+ * `crypto.randomUUID()` is 36 characters — while leaving room for a prefixed variant. It is
53
+ * deliberately TIGHTER than the 200-character opaque-id cap the admin chat-moderation
54
+ * requestIds use (`schemas/chat.ts`): those carry composite operator-supplied ids, whereas
55
+ * this one is always a generated UUID.
56
+ */
57
+ export declare const MAX_REALM_FILE_SHARE_REQUEST_ID_LENGTH = 64;
42
58
  /** Allowed characters in titles: letters, numbers, spaces. */
43
59
  export declare const TITLE_PATTERN: RegExp;
44
60
  /** 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;;;;;;;;;;;;;;;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"}
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;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,sCAAsC,KAAK,CAAC;AAEzD,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"}
@@ -46,6 +46,22 @@ export const MAX_WORK_FILE_STORAGE_BYTES = ACTIVE_LIMITS.workProject.maxWorkFile
46
46
  * platform-wide; there is deliberately no second realm-specific length.
47
47
  */
48
48
  export const MAX_REALM_FILE_FOLDERS = 30;
49
+ /**
50
+ * Maximum length of a realm-file promotion `requestId`.
51
+ *
52
+ * This is the FIRST client-minted, client-CHOSEN id in the set that is durably PERSISTED:
53
+ * it lands on the `mediaAssets` doc, in the audit payload, in notification metadata, and in
54
+ * the notification aggregation key. Every one of those is an attacker-reachable write
55
+ * amplification if the id is unbounded, so the bound belongs on the atom, not on each
56
+ * call site.
57
+ *
58
+ * 64 is the smallest bound that comfortably fits what the client actually mints — a
59
+ * `crypto.randomUUID()` is 36 characters — while leaving room for a prefixed variant. It is
60
+ * deliberately TIGHTER than the 200-character opaque-id cap the admin chat-moderation
61
+ * requestIds use (`schemas/chat.ts`): those carry composite operator-supplied ids, whereas
62
+ * this one is always a generated UUID.
63
+ */
64
+ export const MAX_REALM_FILE_SHARE_REQUEST_ID_LENGTH = 64;
49
65
  /** Allowed characters in titles: letters, numbers, spaces. */
50
66
  export const TITLE_PATTERN = /^[a-zA-Z0-9 ]+$/;
51
67
  /** 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;;;;;;;;;;;;;;;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"]}
1
+ {"version":3,"file":"business-work-project.js","sourceRoot":"","sources":["../../src/constants/business-work-project.ts"],"names":[],"mappings":"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","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/**\n * Maximum length of a realm-file promotion `requestId`.\n *\n * This is the FIRST client-minted, client-CHOSEN id in the set that is durably PERSISTED:\n * it lands on the `mediaAssets` doc, in the audit payload, in notification metadata, and in\n * the notification aggregation key. Every one of those is an attacker-reachable write\n * amplification if the id is unbounded, so the bound belongs on the atom, not on each\n * call site.\n *\n * 64 is the smallest bound that comfortably fits what the client actually mints — a\n * `crypto.randomUUID()` is 36 characters — while leaving room for a prefixed variant. It is\n * deliberately TIGHTER than the 200-character opaque-id cap the admin chat-moderation\n * requestIds use (`schemas/chat.ts`): those carry composite operator-supplied ids, whereas\n * this one is always a generated UUID.\n */\nexport const MAX_REALM_FILE_SHARE_REQUEST_ID_LENGTH = 64;\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"]}
@@ -177,10 +177,25 @@ export declare const RealmFileApprovedStatusSchema: z.ZodEnum<{
177
177
  canon: "canon";
178
178
  }>;
179
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. */
180
+ /** The single AWAITING-DECISION standing. Exported as a VALUE as well as a schema so a
181
+ * consumer can branch on it (`status === REALM_FILE_PENDING_APPROVAL_STATUS`) without
182
+ * re-quoting the member — the redeclaration guard pins this literal to this file. */
183
+ export declare const REALM_FILE_PENDING_APPROVAL_STATUS: "pendingApproval";
184
+ /** The steward promotion-queue projection accepts only this, so an approved or unshared row
185
+ * can never be typed into the queue. */
182
186
  export declare const RealmFilePendingApprovalStatusSchema: z.ZodLiteral<"pendingApproval">;
183
187
  export type RealmFilePendingApprovalStatus = z.infer<typeof RealmFilePendingApprovalStatusSchema>;
188
+ /** Every standing EXCEPT `none` — a file that has entered the request/approval lifecycle at
189
+ * all. Derived from the two subsets above, so adding a future standing to one of them
190
+ * reaches this set automatically. Used by the Work-side share-state projection, whose rows
191
+ * exist only for files that are actually requested or shared. */
192
+ export declare const REALM_FILE_ACTIVE_STATUS_VALUES: readonly ["pendingApproval", "nonCanon", "canon"];
193
+ export declare const RealmFileActiveStatusSchema: z.ZodEnum<{
194
+ pendingApproval: "pendingApproval";
195
+ nonCanon: "nonCanon";
196
+ canon: "canon";
197
+ }>;
198
+ export type RealmFileActiveStatus = z.infer<typeof RealmFileActiveStatusSchema>;
184
199
  /** Whether the canonical serving record has been applied to the DO authority. */
185
200
  export declare const MediaAuthoritySyncStateSchema: z.ZodEnum<{
186
201
  pending: "pending";
@@ -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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"}
@@ -161,9 +161,22 @@ export const RealmFileCanonStatusSchema = z.enum(REALM_FILE_CANON_STATUS_VALUES)
161
161
  * union above; consumers import this instead of re-quoting the members (ARCH-102). */
162
162
  export const REALM_FILE_APPROVED_STATUS_VALUES = ['nonCanon', 'canon'];
163
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');
164
+ /** The single AWAITING-DECISION standing. Exported as a VALUE as well as a schema so a
165
+ * consumer can branch on it (`status === REALM_FILE_PENDING_APPROVAL_STATUS`) without
166
+ * re-quoting the member — the redeclaration guard pins this literal to this file. */
167
+ export const REALM_FILE_PENDING_APPROVAL_STATUS = 'pendingApproval';
168
+ /** The steward promotion-queue projection accepts only this, so an approved or unshared row
169
+ * can never be typed into the queue. */
170
+ export const RealmFilePendingApprovalStatusSchema = z.literal(REALM_FILE_PENDING_APPROVAL_STATUS);
171
+ /** Every standing EXCEPT `none` — a file that has entered the request/approval lifecycle at
172
+ * all. Derived from the two subsets above, so adding a future standing to one of them
173
+ * reaches this set automatically. Used by the Work-side share-state projection, whose rows
174
+ * exist only for files that are actually requested or shared. */
175
+ export const REALM_FILE_ACTIVE_STATUS_VALUES = [
176
+ REALM_FILE_PENDING_APPROVAL_STATUS,
177
+ ...REALM_FILE_APPROVED_STATUS_VALUES,
178
+ ];
179
+ export const RealmFileActiveStatusSchema = z.enum(REALM_FILE_ACTIVE_STATUS_VALUES);
167
180
  // ===== Serving authority (Durable Object) + publication gating =====
168
181
  // See ttt-prod docs/design/media-assets-and-protected-serving.md (the design owner
169
182
  // for the Durable Object serving authority and publication gating).
@@ -1 +1 @@
1
- {"version":3,"file":"media-assets.js","sourceRoot":"","sources":["../../src/doc-schemas/media-assets.ts"],"names":[],"mappings":"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","sourcesContent":["// mediaAssets/{mediaAssetId} — the canonical media registry. One doc per\n// logical uploaded media item; all variants inside. Content docs reference\n// media ONLY by `*AssetId` fields — never URLs. Serving authority is the\n// gateway Worker (cookie/grant + KV blocklist); this doc is the server-side\n// truth the edge records derive from. NO client reads, NO client writes.\n// See ttt-prod docs/design/media-assets-and-protected-serving.md.\n\nimport { z } from 'zod';\nimport { StructuredErrorSchema } from '@ttt-productions/edge-protocol-core';\nimport { FileOriginSchema } from '../media/file-origin.js';\n\n/** Who may be served the bytes (the Worker's tier check). */\nexport const MediaAccessTierSchema = z.enum(['broad', 'scoped', 'artisan', 'adminOnly']);\nexport type MediaAccessTier = z.infer<typeof MediaAccessTierSchema>;\n\n/** Canonical serving state. The edge record derives from this; hide/restore/\n * quarantine flows write it together with the blocklist. */\nexport const MediaServingStatusSchema = z.enum(['servable', 'hidden', 'quarantined', 'deleted']);\nexport type MediaServingStatus = z.infer<typeof MediaServingStatusSchema>;\n\n/** The surface that owns this asset. One asset never serves two scopes —\n * publishing to the Hall (or future realm promotion) creates a NEW asset\n * owned by the destination surface. */\nexport const MediaAssetOwnerTypeSchema = z.enum([\n 'userProfile',\n 'craftSkill',\n 'squareStreetzPost',\n 'workProject',\n 'workContent', // tale chapter / tune track / television episode media (pre-publish)\n 'hallItem',\n 'commissionListing',\n 'commissionProposal',\n 'audition',\n 'auditionEntry',\n // A file in a conversation's flat Conversation Files list (guild-invite or\n // admin-support). Replaces the removed `guildChatAttachment` owner type — chat\n // messages no longer own media.\n 'conversationFile',\n // Realm shared files are the deliberate MUTATE-IN-PLACE exception: a promoted work file\n // keeps its ONE `workFile`-owned asset doc and flips tier in place, so no asset is ever\n // owned by `realmFile` today. The owner type stays declared for a future realm-owned\n // media surface; it is NOT the seam realm sharing rides (that is `realmFileCanonStatus`\n // + `realmId` + `realmFileFolderId` on the work file's own asset).\n 'realmFile',\n 'safetyEvidence', // inert system sentinel — synthetic NCII-evidence assets (never an account surface)\n]);\nexport type MediaAssetOwnerType = z.infer<typeof MediaAssetOwnerTypeSchema>;\n\n// ===== Media origin lineage (Appendix A0) =====\n// One canonical lineage used by media, CSAM, and safety. Embedded on every\n// media asset + every copy.\n\n/** The ONE canonical stored content media kind (what the pipeline produces and the\n * asset doc records). Distinct from the 4-value display/transport MediaTypeSchema\n * (doc-schemas/social.ts, adds 'other') and media-schemas' generic MediaKindSchema. */\nexport const ContentMediaKindSchema = z.enum(['image', 'video', 'audio']);\nexport type ContentMediaKind = z.infer<typeof ContentMediaKindSchema>;\n\n/**\n * The named-variant key set for `variantSha256s` — declared ONCE here; every declared\n * `image.variants[].key` in `TTT_MEDIA_SPECS` is compile-checked against this union\n * (the specs type their variant keys as `MediaVariantKey`), so an undeclared variant\n * name fails the BUILD — no sync test needed. Never an open `string`.\n */\nexport const MEDIA_VARIANT_KEYS = ['full', 'medium', 'small', 'main'] as const;\nexport const MediaVariantKeySchema = z.enum(MEDIA_VARIANT_KEYS);\nexport type MediaVariantKey = z.infer<typeof MediaVariantKeySchema>;\n\n/** Why this asset was created from its source (A0).\n *\n * `chat_derivative` was REMOVED with the chat-attachment architecture: chat is\n * text-only and owns no media, so no copy can be made \"for a chat message\". A\n * Conversation File is an ORIGINAL (`original`), never a chat derivative; nothing\n * ever set the retired value. */\nexport const MediaCopyReasonSchema = z.enum([\n 'original',\n 'variant',\n 'hall_publish',\n 'profile_derivative',\n 'moderation_copy',\n 'evidence_copy',\n 'other',\n]);\nexport type MediaCopyReason = z.infer<typeof MediaCopyReasonSchema>;\n\n/**\n * Canonical media origin lineage (Appendix A0). A copy INHERITS\n * rootIngestId/rootAssetId/originatingUploaderUid/originatingUploadEventId/\n * originalUploadCreatedAt/rootSha256/originalSha256 unchanged; it sets its own\n * sourceAssetId/variantSha256s/copyReason/copyActorUid/currentOwner*. Client\n * requests can NEVER set or override any lineage field. Automatic account\n * action targets ONLY `originatingUploaderUid`; incident-wide blocking\n * enumerates by `rootIngestId`. Missing/corrupt lineage → safetyLocked +\n * manual decision, never a guessed ban.\n */\nexport const MediaOriginLineageV1Schema = z.object({\n lineageVersion: z.literal(1),\n rootIngestId: z.string().min(1), // first-accepted ingest event id; stable across all copies\n rootAssetId: z.string().min(1), // first asset created from that ingest\n sourceAssetId: z.string().min(1).optional(), // immediate parent copied from (absent on the root)\n originatingUploaderUid: z.string().min(1), // set server-side at first accepted ingest; IMMUTABLE; inherited\n // May be '' for a legacy copy synthesized from a pre-rollout source with no known upload event.\n originatingUploadEventId: z.string(),\n originalUploadCreatedAt: z.number(),\n // '' until content hashing backfills the real sha256 (Phase 5 PhotoDNA / evidence capture).\n // NOT z.string().min(1): the media pipeline does not compute a content hash at finalize yet,\n // so a freshly-ingested asset legitimately carries an empty rootSha256 until it is hashed.\n rootSha256: z.string(),\n originalSha256: z.string().min(1).optional(),\n // PARTIAL map: one hash per PRODUCED variant (an asset produces only the variants its\n // origin declares — e.g. full/medium/small for a profile picture, 'main' for others —\n // never all four). Typed keys, never an open string. `z.partialRecord` (NOT `z.record`):\n // in Zod 4 `z.record(enum,…)` is EXHAUSTIVE (demands every enum key), which would reject\n // every real asset's partial variant set; `partialRecord` makes the keys optional.\n variantSha256s: z.partialRecord(MediaVariantKeySchema, z.string().min(1)),\n copyReason: MediaCopyReasonSchema,\n createdFromOwnerType: MediaAssetOwnerTypeSchema.optional(), // never a bare string\n createdFromOwnerId: z.string().min(1).optional(),\n copyActorUid: z.string().min(1).optional(), // who triggered the copy (distinct from the original uploader)\n currentOwnerType: MediaAssetOwnerTypeSchema, // mutable; the asset's present owner\n currentOwnerId: z.string().min(1),\n}).strict();\nexport type MediaOriginLineageV1 = z.infer<typeof MediaOriginLineageV1Schema>;\n\nexport const MediaAssetVariantSchema = z.object({\n contentType: z.string().min(1),\n sizeBytes: z.number().int().nonnegative(),\n width: z.number().int().positive().optional(),\n height: z.number().int().positive().optional(),\n durationSec: z.number().positive().optional(),\n /**\n * Server-owned filename the gateway puts in `Content-Disposition` for a\n * `?download=1` request. VARIANT-specific on purpose: the downloadable bytes are\n * a PROCESSED variant, so the extension must match THIS variant's actual\n * `contentType` — a transcoded JPEG/WebP/MP4 is never labelled with the original\n * upload's incompatible extension.\n *\n * Written ONLY by backend publishers, and ONLY for surfaces that intentionally\n * offer a Download action — Work Files (including the same asset shared to a\n * Realm), Conversation Files, and downloadable Hall media. Profiles, posts,\n * covers, and every other surface leave it ABSENT so no private original filename\n * is ever exposed; an absent value serves the safe bare `attachment` disposition.\n *\n * Always produced by `normalizeDownloadFilename` (media/download-filename.ts) —\n * that helper owns the sanitization rules and the UTF-8 byte cap, so no bound is\n * restated here. A client query parameter is NEVER the filename authority.\n * Filenames are user content: never log this value.\n */\n downloadFilename: z.string().min(1).optional(),\n}).strict();\nexport type MediaAssetVariant = z.infer<typeof MediaAssetVariantSchema>;\n\nexport const MediaRetentionPolicySchema = z.enum([\n 'standard', // staging original deleted ~24h after verified mirror\n 'preserveForTrustAndSafety',\n 'legalHold',\n]);\nexport type MediaRetentionPolicy = z.infer<typeof MediaRetentionPolicySchema>;\n\n// Realm shared-files: a work file's standing in its realm's shared pool. ONE seam — the\n// approval gate is a value in this union, never a parallel status field.\n// none — not shared to the realm (default)\n// pendingApproval — a Work file admin has REQUESTED promotion; the Realm steward has not\n// decided yet. The file is NOT served to the Realm (tier stays `scoped`)\n// and is invisible to the member gallery, whose query selects only\n// nonCanon|canon — so pending rows are excluded structurally, not by a\n// filter someone can forget.\n// nonCanon — approved into the realm's pool (in a steward-chosen folder), non-canon\n// canon — approved and marked canon (realm steward toggles canon ↔ nonCanon)\n// Moderation/takedown is NOT a value here — a hidden file is hidden via the shared\n// media path (`servingStatus: 'hidden'`), so the gallery filters on servingStatus.\nexport const REALM_FILE_CANON_STATUS_VALUES = [\n 'none',\n 'pendingApproval',\n 'nonCanon',\n 'canon',\n] as const;\nexport const RealmFileCanonStatusSchema = z.enum(REALM_FILE_CANON_STATUS_VALUES);\nexport type RealmFileCanonStatus = z.infer<typeof RealmFileCanonStatusSchema>;\n\n/** The two APPROVED (steward-accepted, realm-served) standings. The member gallery query\n * and its projection accept exactly these — never the full status union, so a pending or\n * unshared row can never be typed into an approved-files response. Derived from the one\n * union above; consumers import this instead of re-quoting the members (ARCH-102). */\nexport const REALM_FILE_APPROVED_STATUS_VALUES = ['nonCanon', 'canon'] as const;\nexport const RealmFileApprovedStatusSchema = z.enum(REALM_FILE_APPROVED_STATUS_VALUES);\nexport type RealmFileApprovedStatus = z.infer<typeof RealmFileApprovedStatusSchema>;\n\n/** The single AWAITING-DECISION standing. The steward promotion-queue projection accepts\n * only this, so an approved or unshared row can never be typed into the queue. */\nexport const RealmFilePendingApprovalStatusSchema = z.literal('pendingApproval');\nexport type RealmFilePendingApprovalStatus = z.infer<typeof RealmFilePendingApprovalStatusSchema>;\n\n// ===== Serving authority (Durable Object) + publication gating =====\n// See ttt-prod docs/design/media-assets-and-protected-serving.md (the design owner\n// for the Durable Object serving authority and publication gating).\n\n/** Whether the canonical serving record has been applied to the DO authority. */\nexport const MediaAuthoritySyncStateSchema = z.enum(['pending', 'applied', 'deadLetter']);\nexport type MediaAuthoritySyncState = z.infer<typeof MediaAuthoritySyncStateSchema>;\n\n/** Whether the asset is referenced by a visible owner doc. Orthogonal to the\n * upload's processing outcome (`pendingMedia.status`) and to `servingStatus`. */\nexport const MediaAssetPublicationStateSchema = z.enum(['unpublished', 'published', 'retired']);\nexport type MediaAssetPublicationState = z.infer<typeof MediaAssetPublicationStateSchema>;\n\n/**\n * Typed immutable serving scope for scoped-tier assets. The gateway Worker matches\n * a grant against the scope by `kind` — so a whole-Work `{w}` grant matches ONLY a\n * `workProject` scope, never a conversation scope, and a conversation grant is never\n * reachable by a Work asset.\n *\n * - `workProject` — pre-publish content media (hall covers / sub-item media during\n * authoring), scoped to project read membership. Carries the matchable\n * `workProjectId`. This is the typed home for work scope on the strongly-consistent\n * serving record so the DO-fallback path can authorize it (the DO persists scope\n * only as `scopeJson`, no separate column).\n * - `workFileFolder` — a work-project FILE living in a folder. The EXACT folder scope,\n * NOT the whole-Work `{w}` grant: a custom folder's bytes must be unreachable by a\n * guildmate outside that folder's view trade-professions, so the grant callable runs\n * the per-folder view check and the Worker EXACT-matches `{workProjectId,\n * workFileFolderId}` — a plain Work `{w}` grant NEVER matches a folder file, and a\n * folder grant NEVER matches a `workProject`-scoped content asset.\n * - `guildInvite` / `adminSupport` — the two Conversation Files scopes; an EXACT\n * conversation scope, matching the `ConversationFileRef` that owns the file. There is\n * NO guildChannel scope: guild chat channels have no Conversation Files (guildmates\n * share files through Work Files, which keeps its own workFileFolder scope).\n *\n * `null` scope = no scope match required beyond the access tier (e.g. broad).\n */\nexport const MediaServingScopeSchema = z.discriminatedUnion('kind', [\n z.object({\n kind: z.literal('workProject'),\n workProjectId: z.string().min(1),\n }).strict(),\n z.object({\n kind: z.literal('workFileFolder'),\n workProjectId: z.string().min(1),\n workFileFolderId: z.string().min(1),\n }).strict(),\n z.object({\n kind: z.literal('guildInvite'),\n guildInviteId: z.string().min(1),\n }).strict(),\n z.object({\n kind: z.literal('adminSupport'),\n adminDispatchId: z.string().min(1),\n }).strict(),\n]);\nexport type MediaServingScope = z.infer<typeof MediaServingScopeSchema>;\n\n/**\n * The typed owner adapter a publication goes through. The activation job\n * carries this kind; a server-side registry validates per-kind `publicationArgs`\n * and performs the idempotent owner write. Every kind is a Firestore-owner adapter.\n */\nexport const MediaPublicationKindSchema = z.enum([\n 'profilePicture',\n 'squarePostMedia',\n 'workAsset',\n 'hallCover',\n // Realm cover — Firestore-owner adapter writes `realmCoverAssetId` onto\n // workRealms/{workRealmId} (the 'realm-cover' upload origin).\n 'realmCover',\n 'workContentMedia', // sub-item media (tale chapter / tune track / television episode) — attaches the *AssetId field on the workContent doc; scoped to the work project\n 'auditionMedia',\n 'commissionListingMedia',\n 'commissionProposalMedia',\n 'craftSkillMedia',\n // Conversation File: the ONE adapter that creates a visible Conversation File owner\n // record ({conversationParent}/conversationFiles/{conversationFileId}) and transfers\n // the quota reservation to published counters in the same transaction. Replaces the\n // removed `chatAttachment` (Channel-DO flip) and `adminSupportAttachment` (message\n // placeholder flip) kinds. Carries the typed `guildInvite` / `adminSupport`\n // MediaServingScope of the owning conversation.\n 'conversationFile',\n]);\nexport type MediaPublicationKind = z.infer<typeof MediaPublicationKindSchema>;\n\n/**\n * The normalized serving record — the SAME contract used to generate both\n * the DO authority row and the KV cache payload (one function, so they can't\n * drift). The R2 object key stays deterministic (`mediaAssets/{assetId}/{key}`)\n * and is NOT persisted here. `payloadHash` is computed over the canonical\n * payload EXCLUDING the hash itself (see edge-protocol-core `hashPayload`).\n */\nexport const MediaServingAuthorityRecordSchema = z.object({\n schemaVersion: z.number().int().positive(),\n assetId: z.string().min(1),\n authorityVersion: z.number().int().nonnegative(),\n operationId: z.string().min(1),\n payloadHash: z.string().min(1),\n\n servingStatus: MediaServingStatusSchema,\n accessTier: MediaAccessTierSchema,\n\n ownerType: MediaAssetOwnerTypeSchema,\n ownerId: z.string().min(1),\n scope: MediaServingScopeSchema.nullable(),\n\n variants: z.record(z.string(), MediaAssetVariantSchema),\n\n updatedAtMs: z.number(),\n}).strict();\nexport type MediaServingAuthorityRecord = z.infer<typeof MediaServingAuthorityRecordSchema>;\n\nexport const MediaAssetSchema = z.object({\n mediaAssetId: z.string().min(1),\n mediaKind: ContentMediaKindSchema,\n fileOrigin: FileOriginSchema,\n\n // Ownership / scope. ownerId is the owning doc's id within ownerType's\n // surface; scope ids let the Worker/grant layer match scoped access.\n ownerType: MediaAssetOwnerTypeSchema,\n ownerId: z.string().min(1),\n workProjectId: z.string().optional(),\n realmId: z.string().optional(),\n createdByUid: z.string().min(1),\n\n // Access + serving (canonical; edge records derive from these).\n accessTier: MediaAccessTierSchema,\n servingStatus: MediaServingStatusSchema,\n\n // Variants by key. The object key in R2 (and the Storage emulator) is\n // deterministic — mediaAssets/{mediaAssetId}/{variantKey} — never stored.\n variants: z.record(z.string(), MediaAssetVariantSchema),\n\n // Lifecycle / trust-and-safety.\n moderationStatus: z.enum(['approved', 'quarantined']),\n retentionPolicy: MediaRetentionPolicySchema,\n legalHold: z.boolean(),\n originalDeletedAt: z.number().optional(),\n\n // T&S provenance lineage (Appendix A0). Additive/optional so assets written\n // before the lineage rollout still parse; set server-side at first accepted\n // ingest, inherited unchanged by every copy/variant. Never client-supplied.\n originLineage: MediaOriginLineageV1Schema.optional(),\n\n // ===== Realm shared-files seam (request → steward approval → foldered pool) =====\n // A file's standing in its realm's shared pool; set at creation to 'none' and moved\n // ONLY by the realm shared-files callables. The legal combinations of this field with\n // `realmId`, `realmFileFolderId`, and the three request fields are ENFORCED by the\n // refinement below — the fields are not independently optional.\n realmFileCanonStatus: RealmFileCanonStatusSchema,\n\n // The steward-chosen folder under `workRealms/{realmId}/realmFileFolders/{id}`. There is\n // no default folder: approval IS the folder assignment, so every approved file is in a\n // folder by construction. Cleared on decline, withdrawal, and admin un-share — but\n // PRESERVED through moderation hide/restore (hide is reversible and changes serving state\n // only; clearing it would restore an approved file with no folder and lose the steward's\n // organization).\n realmFileFolderId: z.string().min(1).optional(),\n\n // Pending-request metadata, present ONLY while `realmFileCanonStatus === 'pendingApproval'`.\n // `realmFileShareRequestId` is the CLIENT-GENERATED stable request id carried by the\n // request input; approval, decline, and withdrawal all compare against it, so a stale tab\n // can never decide a newer re-request. `realmFileShareRequestedByUid` is the recorded\n // requester — the resolution notification is addressed from THIS field, never guessed from\n // `createdByUid` (the uploader and the promoting file admin are frequently different\n // people). `realmFileShareRequestedAt` is epoch ms (ARCH-105).\n realmFileShareRequestId: z.string().min(1).optional(),\n realmFileShareRequestedByUid: z.string().min(1).optional(),\n realmFileShareRequestedAt: z.number().optional(),\n\n // Serving authority + publication gating. Additive/optional so assets\n // written before the authority build still parse: absent authorityVersion ⇒\n // 0/never-applied, absent publicationState ⇒ 'unpublished'. Every\n // serving-record mutation increments authorityVersion in an authoritative txn.\n authorityVersion: z.number().int().nonnegative().optional(),\n authorityPayloadHash: z.string().optional(),\n authoritySyncState: MediaAuthoritySyncStateSchema.optional(),\n publicationState: MediaAssetPublicationStateSchema.optional(),\n scope: MediaServingScopeSchema.optional(),\n authorityAppliedAt: z.number().optional(),\n publishedAt: z.number().optional(),\n lastAuthorityError: StructuredErrorSchema.optional(),\n // Authority-sync retry ledger (M1): the scheduled worker bumps attemptCount + sets a backoff\n // nextAttemptAt on a transient apply failure, and dead-letters (authoritySyncState='deadLetter')\n // past a threshold. Absent ⇒ 0 attempts / immediately due.\n authoritySyncAttemptCount: z.number().int().nonnegative().optional(),\n authoritySyncNextAttemptAt: z.number().optional(),\n\n createdAt: z.number(),\n updatedAt: z.number(),\n}).strict().superRefine((val, ctx) => {\n // ===== Realm-file legal-combination invariant =====\n // The realm-file field GROUP is one state machine, not five independently-optional\n // fields. Declared HERE, on the canonical doc schema (ARCH-102), so every writer inherits\n // it from one parse instead of each transition re-deciding — and so no reader ever has to\n // defend against a half-written state (an approved file with no folder, a pending file\n // already flipped into the realm, a decline that left request metadata behind).\n //\n // none → no realmId, no folder, no request fields\n // pendingApproval → realmId + ALL THREE request fields; NO folder (approval assigns it)\n // nonCanon|canon → realmId + folder; NO request fields (the request is resolved)\n //\n // DELIBERATELY NOT CONSTRAINED HERE: `accessTier`. Tier is origin-dependent across the\n // whole asset universe (this one schema covers every media origin, not just work files),\n // so binding tier to a realm-file status would misjudge assets that have nothing to do\n // with realms. Tier correctness on these transitions (`scoped` while pending, `artisan`\n // once approved) is enforced by the callable transactions and their tests.\n // `servingStatus` stays orthogonal too — moderation hide/quarantine is independent of a\n // file's realm standing.\n const requestFields = [\n ['realmFileShareRequestId', val.realmFileShareRequestId],\n ['realmFileShareRequestedByUid', val.realmFileShareRequestedByUid],\n ['realmFileShareRequestedAt', val.realmFileShareRequestedAt],\n ] as const;\n\n const forbid = (path: string, value: unknown, message: string) => {\n if (value !== undefined) ctx.addIssue({ code: 'custom', path: [path], message });\n };\n const require_ = (path: string, value: unknown, message: string) => {\n if (value === undefined) ctx.addIssue({ code: 'custom', path: [path], message });\n };\n\n if (val.realmFileCanonStatus === 'none') {\n forbid('realmId', val.realmId, 'realmId is only set on a realm-shared or pending asset (realmFileCanonStatus is \"none\")');\n forbid('realmFileFolderId', val.realmFileFolderId, 'realmFileFolderId is only set on an APPROVED realm-shared asset (realmFileCanonStatus is \"none\")');\n for (const [path, value] of requestFields) {\n forbid(path, value, `${path} is only set while a promotion request is pending (realmFileCanonStatus is \"none\")`);\n }\n return;\n }\n\n require_('realmId', val.realmId, `realmId is required whenever realmFileCanonStatus is \"${val.realmFileCanonStatus}\"`);\n\n if (val.realmFileCanonStatus === 'pendingApproval') {\n forbid('realmFileFolderId', val.realmFileFolderId, 'a pending request has no folder yet — the steward assigns the folder AT approval');\n for (const [path, value] of requestFields) {\n require_(path, value, `${path} is required while realmFileCanonStatus is \"pendingApproval\"`);\n }\n return;\n }\n\n // 'nonCanon' | 'canon' — approved into the pool.\n require_('realmFileFolderId', val.realmFileFolderId, `realmFileFolderId is required on an approved realm file (realmFileCanonStatus is \"${val.realmFileCanonStatus}\")`);\n for (const [path, value] of requestFields) {\n forbid(path, value, `${path} must be cleared once the request is resolved (realmFileCanonStatus is \"${val.realmFileCanonStatus}\")`);\n }\n});\nexport type MediaAsset = z.infer<typeof MediaAssetSchema>;\n"]}
1
+ {"version":3,"file":"media-assets.js","sourceRoot":"","sources":["../../src/doc-schemas/media-assets.ts"],"names":[],"mappings":"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","sourcesContent":["// mediaAssets/{mediaAssetId} — the canonical media registry. One doc per\n// logical uploaded media item; all variants inside. Content docs reference\n// media ONLY by `*AssetId` fields — never URLs. Serving authority is the\n// gateway Worker (cookie/grant + KV blocklist); this doc is the server-side\n// truth the edge records derive from. NO client reads, NO client writes.\n// See ttt-prod docs/design/media-assets-and-protected-serving.md.\n\nimport { z } from 'zod';\nimport { StructuredErrorSchema } from '@ttt-productions/edge-protocol-core';\nimport { FileOriginSchema } from '../media/file-origin.js';\n\n/** Who may be served the bytes (the Worker's tier check). */\nexport const MediaAccessTierSchema = z.enum(['broad', 'scoped', 'artisan', 'adminOnly']);\nexport type MediaAccessTier = z.infer<typeof MediaAccessTierSchema>;\n\n/** Canonical serving state. The edge record derives from this; hide/restore/\n * quarantine flows write it together with the blocklist. */\nexport const MediaServingStatusSchema = z.enum(['servable', 'hidden', 'quarantined', 'deleted']);\nexport type MediaServingStatus = z.infer<typeof MediaServingStatusSchema>;\n\n/** The surface that owns this asset. One asset never serves two scopes —\n * publishing to the Hall (or future realm promotion) creates a NEW asset\n * owned by the destination surface. */\nexport const MediaAssetOwnerTypeSchema = z.enum([\n 'userProfile',\n 'craftSkill',\n 'squareStreetzPost',\n 'workProject',\n 'workContent', // tale chapter / tune track / television episode media (pre-publish)\n 'hallItem',\n 'commissionListing',\n 'commissionProposal',\n 'audition',\n 'auditionEntry',\n // A file in a conversation's flat Conversation Files list (guild-invite or\n // admin-support). Replaces the removed `guildChatAttachment` owner type — chat\n // messages no longer own media.\n 'conversationFile',\n // Realm shared files are the deliberate MUTATE-IN-PLACE exception: a promoted work file\n // keeps its ONE `workFile`-owned asset doc and flips tier in place, so no asset is ever\n // owned by `realmFile` today. The owner type stays declared for a future realm-owned\n // media surface; it is NOT the seam realm sharing rides (that is `realmFileCanonStatus`\n // + `realmId` + `realmFileFolderId` on the work file's own asset).\n 'realmFile',\n 'safetyEvidence', // inert system sentinel — synthetic NCII-evidence assets (never an account surface)\n]);\nexport type MediaAssetOwnerType = z.infer<typeof MediaAssetOwnerTypeSchema>;\n\n// ===== Media origin lineage (Appendix A0) =====\n// One canonical lineage used by media, CSAM, and safety. Embedded on every\n// media asset + every copy.\n\n/** The ONE canonical stored content media kind (what the pipeline produces and the\n * asset doc records). Distinct from the 4-value display/transport MediaTypeSchema\n * (doc-schemas/social.ts, adds 'other') and media-schemas' generic MediaKindSchema. */\nexport const ContentMediaKindSchema = z.enum(['image', 'video', 'audio']);\nexport type ContentMediaKind = z.infer<typeof ContentMediaKindSchema>;\n\n/**\n * The named-variant key set for `variantSha256s` — declared ONCE here; every declared\n * `image.variants[].key` in `TTT_MEDIA_SPECS` is compile-checked against this union\n * (the specs type their variant keys as `MediaVariantKey`), so an undeclared variant\n * name fails the BUILD — no sync test needed. Never an open `string`.\n */\nexport const MEDIA_VARIANT_KEYS = ['full', 'medium', 'small', 'main'] as const;\nexport const MediaVariantKeySchema = z.enum(MEDIA_VARIANT_KEYS);\nexport type MediaVariantKey = z.infer<typeof MediaVariantKeySchema>;\n\n/** Why this asset was created from its source (A0).\n *\n * `chat_derivative` was REMOVED with the chat-attachment architecture: chat is\n * text-only and owns no media, so no copy can be made \"for a chat message\". A\n * Conversation File is an ORIGINAL (`original`), never a chat derivative; nothing\n * ever set the retired value. */\nexport const MediaCopyReasonSchema = z.enum([\n 'original',\n 'variant',\n 'hall_publish',\n 'profile_derivative',\n 'moderation_copy',\n 'evidence_copy',\n 'other',\n]);\nexport type MediaCopyReason = z.infer<typeof MediaCopyReasonSchema>;\n\n/**\n * Canonical media origin lineage (Appendix A0). A copy INHERITS\n * rootIngestId/rootAssetId/originatingUploaderUid/originatingUploadEventId/\n * originalUploadCreatedAt/rootSha256/originalSha256 unchanged; it sets its own\n * sourceAssetId/variantSha256s/copyReason/copyActorUid/currentOwner*. Client\n * requests can NEVER set or override any lineage field. Automatic account\n * action targets ONLY `originatingUploaderUid`; incident-wide blocking\n * enumerates by `rootIngestId`. Missing/corrupt lineage → safetyLocked +\n * manual decision, never a guessed ban.\n */\nexport const MediaOriginLineageV1Schema = z.object({\n lineageVersion: z.literal(1),\n rootIngestId: z.string().min(1), // first-accepted ingest event id; stable across all copies\n rootAssetId: z.string().min(1), // first asset created from that ingest\n sourceAssetId: z.string().min(1).optional(), // immediate parent copied from (absent on the root)\n originatingUploaderUid: z.string().min(1), // set server-side at first accepted ingest; IMMUTABLE; inherited\n // May be '' for a legacy copy synthesized from a pre-rollout source with no known upload event.\n originatingUploadEventId: z.string(),\n originalUploadCreatedAt: z.number(),\n // '' until content hashing backfills the real sha256 (Phase 5 PhotoDNA / evidence capture).\n // NOT z.string().min(1): the media pipeline does not compute a content hash at finalize yet,\n // so a freshly-ingested asset legitimately carries an empty rootSha256 until it is hashed.\n rootSha256: z.string(),\n originalSha256: z.string().min(1).optional(),\n // PARTIAL map: one hash per PRODUCED variant (an asset produces only the variants its\n // origin declares — e.g. full/medium/small for a profile picture, 'main' for others —\n // never all four). Typed keys, never an open string. `z.partialRecord` (NOT `z.record`):\n // in Zod 4 `z.record(enum,…)` is EXHAUSTIVE (demands every enum key), which would reject\n // every real asset's partial variant set; `partialRecord` makes the keys optional.\n variantSha256s: z.partialRecord(MediaVariantKeySchema, z.string().min(1)),\n copyReason: MediaCopyReasonSchema,\n createdFromOwnerType: MediaAssetOwnerTypeSchema.optional(), // never a bare string\n createdFromOwnerId: z.string().min(1).optional(),\n copyActorUid: z.string().min(1).optional(), // who triggered the copy (distinct from the original uploader)\n currentOwnerType: MediaAssetOwnerTypeSchema, // mutable; the asset's present owner\n currentOwnerId: z.string().min(1),\n}).strict();\nexport type MediaOriginLineageV1 = z.infer<typeof MediaOriginLineageV1Schema>;\n\nexport const MediaAssetVariantSchema = z.object({\n contentType: z.string().min(1),\n sizeBytes: z.number().int().nonnegative(),\n width: z.number().int().positive().optional(),\n height: z.number().int().positive().optional(),\n durationSec: z.number().positive().optional(),\n /**\n * Server-owned filename the gateway puts in `Content-Disposition` for a\n * `?download=1` request. VARIANT-specific on purpose: the downloadable bytes are\n * a PROCESSED variant, so the extension must match THIS variant's actual\n * `contentType` — a transcoded JPEG/WebP/MP4 is never labelled with the original\n * upload's incompatible extension.\n *\n * Written ONLY by backend publishers, and ONLY for surfaces that intentionally\n * offer a Download action — Work Files (including the same asset shared to a\n * Realm), Conversation Files, and downloadable Hall media. Profiles, posts,\n * covers, and every other surface leave it ABSENT so no private original filename\n * is ever exposed; an absent value serves the safe bare `attachment` disposition.\n *\n * Always produced by `normalizeDownloadFilename` (media/download-filename.ts) —\n * that helper owns the sanitization rules and the UTF-8 byte cap, so no bound is\n * restated here. A client query parameter is NEVER the filename authority.\n * Filenames are user content: never log this value.\n */\n downloadFilename: z.string().min(1).optional(),\n}).strict();\nexport type MediaAssetVariant = z.infer<typeof MediaAssetVariantSchema>;\n\nexport const MediaRetentionPolicySchema = z.enum([\n 'standard', // staging original deleted ~24h after verified mirror\n 'preserveForTrustAndSafety',\n 'legalHold',\n]);\nexport type MediaRetentionPolicy = z.infer<typeof MediaRetentionPolicySchema>;\n\n// Realm shared-files: a work file's standing in its realm's shared pool. ONE seam — the\n// approval gate is a value in this union, never a parallel status field.\n// none — not shared to the realm (default)\n// pendingApproval — a Work file admin has REQUESTED promotion; the Realm steward has not\n// decided yet. The file is NOT served to the Realm (tier stays `scoped`)\n// and is invisible to the member gallery, whose query selects only\n// nonCanon|canon — so pending rows are excluded structurally, not by a\n// filter someone can forget.\n// nonCanon — approved into the realm's pool (in a steward-chosen folder), non-canon\n// canon — approved and marked canon (realm steward toggles canon ↔ nonCanon)\n// Moderation/takedown is NOT a value here — a hidden file is hidden via the shared\n// media path (`servingStatus: 'hidden'`), so the gallery filters on servingStatus.\nexport const REALM_FILE_CANON_STATUS_VALUES = [\n 'none',\n 'pendingApproval',\n 'nonCanon',\n 'canon',\n] as const;\nexport const RealmFileCanonStatusSchema = z.enum(REALM_FILE_CANON_STATUS_VALUES);\nexport type RealmFileCanonStatus = z.infer<typeof RealmFileCanonStatusSchema>;\n\n/** The two APPROVED (steward-accepted, realm-served) standings. The member gallery query\n * and its projection accept exactly these — never the full status union, so a pending or\n * unshared row can never be typed into an approved-files response. Derived from the one\n * union above; consumers import this instead of re-quoting the members (ARCH-102). */\nexport const REALM_FILE_APPROVED_STATUS_VALUES = ['nonCanon', 'canon'] as const;\nexport const RealmFileApprovedStatusSchema = z.enum(REALM_FILE_APPROVED_STATUS_VALUES);\nexport type RealmFileApprovedStatus = z.infer<typeof RealmFileApprovedStatusSchema>;\n\n/** The single AWAITING-DECISION standing. Exported as a VALUE as well as a schema so a\n * consumer can branch on it (`status === REALM_FILE_PENDING_APPROVAL_STATUS`) without\n * re-quoting the member — the redeclaration guard pins this literal to this file. */\nexport const REALM_FILE_PENDING_APPROVAL_STATUS = 'pendingApproval' as const;\n/** The steward promotion-queue projection accepts only this, so an approved or unshared row\n * can never be typed into the queue. */\nexport const RealmFilePendingApprovalStatusSchema = z.literal(REALM_FILE_PENDING_APPROVAL_STATUS);\nexport type RealmFilePendingApprovalStatus = z.infer<typeof RealmFilePendingApprovalStatusSchema>;\n\n/** Every standing EXCEPT `none` — a file that has entered the request/approval lifecycle at\n * all. Derived from the two subsets above, so adding a future standing to one of them\n * reaches this set automatically. Used by the Work-side share-state projection, whose rows\n * exist only for files that are actually requested or shared. */\nexport const REALM_FILE_ACTIVE_STATUS_VALUES = [\n REALM_FILE_PENDING_APPROVAL_STATUS,\n ...REALM_FILE_APPROVED_STATUS_VALUES,\n] as const;\nexport const RealmFileActiveStatusSchema = z.enum(REALM_FILE_ACTIVE_STATUS_VALUES);\nexport type RealmFileActiveStatus = z.infer<typeof RealmFileActiveStatusSchema>;\n\n// ===== Serving authority (Durable Object) + publication gating =====\n// See ttt-prod docs/design/media-assets-and-protected-serving.md (the design owner\n// for the Durable Object serving authority and publication gating).\n\n/** Whether the canonical serving record has been applied to the DO authority. */\nexport const MediaAuthoritySyncStateSchema = z.enum(['pending', 'applied', 'deadLetter']);\nexport type MediaAuthoritySyncState = z.infer<typeof MediaAuthoritySyncStateSchema>;\n\n/** Whether the asset is referenced by a visible owner doc. Orthogonal to the\n * upload's processing outcome (`pendingMedia.status`) and to `servingStatus`. */\nexport const MediaAssetPublicationStateSchema = z.enum(['unpublished', 'published', 'retired']);\nexport type MediaAssetPublicationState = z.infer<typeof MediaAssetPublicationStateSchema>;\n\n/**\n * Typed immutable serving scope for scoped-tier assets. The gateway Worker matches\n * a grant against the scope by `kind` — so a whole-Work `{w}` grant matches ONLY a\n * `workProject` scope, never a conversation scope, and a conversation grant is never\n * reachable by a Work asset.\n *\n * - `workProject` — pre-publish content media (hall covers / sub-item media during\n * authoring), scoped to project read membership. Carries the matchable\n * `workProjectId`. This is the typed home for work scope on the strongly-consistent\n * serving record so the DO-fallback path can authorize it (the DO persists scope\n * only as `scopeJson`, no separate column).\n * - `workFileFolder` — a work-project FILE living in a folder. The EXACT folder scope,\n * NOT the whole-Work `{w}` grant: a custom folder's bytes must be unreachable by a\n * guildmate outside that folder's view trade-professions, so the grant callable runs\n * the per-folder view check and the Worker EXACT-matches `{workProjectId,\n * workFileFolderId}` — a plain Work `{w}` grant NEVER matches a folder file, and a\n * folder grant NEVER matches a `workProject`-scoped content asset.\n * - `guildInvite` / `adminSupport` — the two Conversation Files scopes; an EXACT\n * conversation scope, matching the `ConversationFileRef` that owns the file. There is\n * NO guildChannel scope: guild chat channels have no Conversation Files (guildmates\n * share files through Work Files, which keeps its own workFileFolder scope).\n *\n * `null` scope = no scope match required beyond the access tier (e.g. broad).\n */\nexport const MediaServingScopeSchema = z.discriminatedUnion('kind', [\n z.object({\n kind: z.literal('workProject'),\n workProjectId: z.string().min(1),\n }).strict(),\n z.object({\n kind: z.literal('workFileFolder'),\n workProjectId: z.string().min(1),\n workFileFolderId: z.string().min(1),\n }).strict(),\n z.object({\n kind: z.literal('guildInvite'),\n guildInviteId: z.string().min(1),\n }).strict(),\n z.object({\n kind: z.literal('adminSupport'),\n adminDispatchId: z.string().min(1),\n }).strict(),\n]);\nexport type MediaServingScope = z.infer<typeof MediaServingScopeSchema>;\n\n/**\n * The typed owner adapter a publication goes through. The activation job\n * carries this kind; a server-side registry validates per-kind `publicationArgs`\n * and performs the idempotent owner write. Every kind is a Firestore-owner adapter.\n */\nexport const MediaPublicationKindSchema = z.enum([\n 'profilePicture',\n 'squarePostMedia',\n 'workAsset',\n 'hallCover',\n // Realm cover — Firestore-owner adapter writes `realmCoverAssetId` onto\n // workRealms/{workRealmId} (the 'realm-cover' upload origin).\n 'realmCover',\n 'workContentMedia', // sub-item media (tale chapter / tune track / television episode) — attaches the *AssetId field on the workContent doc; scoped to the work project\n 'auditionMedia',\n 'commissionListingMedia',\n 'commissionProposalMedia',\n 'craftSkillMedia',\n // Conversation File: the ONE adapter that creates a visible Conversation File owner\n // record ({conversationParent}/conversationFiles/{conversationFileId}) and transfers\n // the quota reservation to published counters in the same transaction. Replaces the\n // removed `chatAttachment` (Channel-DO flip) and `adminSupportAttachment` (message\n // placeholder flip) kinds. Carries the typed `guildInvite` / `adminSupport`\n // MediaServingScope of the owning conversation.\n 'conversationFile',\n]);\nexport type MediaPublicationKind = z.infer<typeof MediaPublicationKindSchema>;\n\n/**\n * The normalized serving record — the SAME contract used to generate both\n * the DO authority row and the KV cache payload (one function, so they can't\n * drift). The R2 object key stays deterministic (`mediaAssets/{assetId}/{key}`)\n * and is NOT persisted here. `payloadHash` is computed over the canonical\n * payload EXCLUDING the hash itself (see edge-protocol-core `hashPayload`).\n */\nexport const MediaServingAuthorityRecordSchema = z.object({\n schemaVersion: z.number().int().positive(),\n assetId: z.string().min(1),\n authorityVersion: z.number().int().nonnegative(),\n operationId: z.string().min(1),\n payloadHash: z.string().min(1),\n\n servingStatus: MediaServingStatusSchema,\n accessTier: MediaAccessTierSchema,\n\n ownerType: MediaAssetOwnerTypeSchema,\n ownerId: z.string().min(1),\n scope: MediaServingScopeSchema.nullable(),\n\n variants: z.record(z.string(), MediaAssetVariantSchema),\n\n updatedAtMs: z.number(),\n}).strict();\nexport type MediaServingAuthorityRecord = z.infer<typeof MediaServingAuthorityRecordSchema>;\n\nexport const MediaAssetSchema = z.object({\n mediaAssetId: z.string().min(1),\n mediaKind: ContentMediaKindSchema,\n fileOrigin: FileOriginSchema,\n\n // Ownership / scope. ownerId is the owning doc's id within ownerType's\n // surface; scope ids let the Worker/grant layer match scoped access.\n ownerType: MediaAssetOwnerTypeSchema,\n ownerId: z.string().min(1),\n workProjectId: z.string().optional(),\n realmId: z.string().optional(),\n createdByUid: z.string().min(1),\n\n // Access + serving (canonical; edge records derive from these).\n accessTier: MediaAccessTierSchema,\n servingStatus: MediaServingStatusSchema,\n\n // Variants by key. The object key in R2 (and the Storage emulator) is\n // deterministic — mediaAssets/{mediaAssetId}/{variantKey} — never stored.\n variants: z.record(z.string(), MediaAssetVariantSchema),\n\n // Lifecycle / trust-and-safety.\n moderationStatus: z.enum(['approved', 'quarantined']),\n retentionPolicy: MediaRetentionPolicySchema,\n legalHold: z.boolean(),\n originalDeletedAt: z.number().optional(),\n\n // T&S provenance lineage (Appendix A0). Additive/optional so assets written\n // before the lineage rollout still parse; set server-side at first accepted\n // ingest, inherited unchanged by every copy/variant. Never client-supplied.\n originLineage: MediaOriginLineageV1Schema.optional(),\n\n // ===== Realm shared-files seam (request → steward approval → foldered pool) =====\n // A file's standing in its realm's shared pool; set at creation to 'none' and moved\n // ONLY by the realm shared-files callables. The legal combinations of this field with\n // `realmId`, `realmFileFolderId`, and the three request fields are ENFORCED by the\n // refinement below — the fields are not independently optional.\n realmFileCanonStatus: RealmFileCanonStatusSchema,\n\n // The steward-chosen folder under `workRealms/{realmId}/realmFileFolders/{id}`. There is\n // no default folder: approval IS the folder assignment, so every approved file is in a\n // folder by construction. Cleared on decline, withdrawal, and admin un-share — but\n // PRESERVED through moderation hide/restore (hide is reversible and changes serving state\n // only; clearing it would restore an approved file with no folder and lose the steward's\n // organization).\n realmFileFolderId: z.string().min(1).optional(),\n\n // Pending-request metadata, present ONLY while `realmFileCanonStatus === 'pendingApproval'`.\n // `realmFileShareRequestId` is the CLIENT-GENERATED stable request id carried by the\n // request input; approval, decline, and withdrawal all compare against it, so a stale tab\n // can never decide a newer re-request. `realmFileShareRequestedByUid` is the recorded\n // requester — the resolution notification is addressed from THIS field, never guessed from\n // `createdByUid` (the uploader and the promoting file admin are frequently different\n // people). `realmFileShareRequestedAt` is epoch ms (ARCH-105).\n realmFileShareRequestId: z.string().min(1).optional(),\n realmFileShareRequestedByUid: z.string().min(1).optional(),\n realmFileShareRequestedAt: z.number().optional(),\n\n // Serving authority + publication gating. Additive/optional so assets\n // written before the authority build still parse: absent authorityVersion ⇒\n // 0/never-applied, absent publicationState ⇒ 'unpublished'. Every\n // serving-record mutation increments authorityVersion in an authoritative txn.\n authorityVersion: z.number().int().nonnegative().optional(),\n authorityPayloadHash: z.string().optional(),\n authoritySyncState: MediaAuthoritySyncStateSchema.optional(),\n publicationState: MediaAssetPublicationStateSchema.optional(),\n scope: MediaServingScopeSchema.optional(),\n authorityAppliedAt: z.number().optional(),\n publishedAt: z.number().optional(),\n lastAuthorityError: StructuredErrorSchema.optional(),\n // Authority-sync retry ledger (M1): the scheduled worker bumps attemptCount + sets a backoff\n // nextAttemptAt on a transient apply failure, and dead-letters (authoritySyncState='deadLetter')\n // past a threshold. Absent ⇒ 0 attempts / immediately due.\n authoritySyncAttemptCount: z.number().int().nonnegative().optional(),\n authoritySyncNextAttemptAt: z.number().optional(),\n\n createdAt: z.number(),\n updatedAt: z.number(),\n}).strict().superRefine((val, ctx) => {\n // ===== Realm-file legal-combination invariant =====\n // The realm-file field GROUP is one state machine, not five independently-optional\n // fields. Declared HERE, on the canonical doc schema (ARCH-102), so every writer inherits\n // it from one parse instead of each transition re-deciding — and so no reader ever has to\n // defend against a half-written state (an approved file with no folder, a pending file\n // already flipped into the realm, a decline that left request metadata behind).\n //\n // none → no realmId, no folder, no request fields\n // pendingApproval → realmId + ALL THREE request fields; NO folder (approval assigns it)\n // nonCanon|canon → realmId + folder; NO request fields (the request is resolved)\n //\n // DELIBERATELY NOT CONSTRAINED HERE: `accessTier`. Tier is origin-dependent across the\n // whole asset universe (this one schema covers every media origin, not just work files),\n // so binding tier to a realm-file status would misjudge assets that have nothing to do\n // with realms. Tier correctness on these transitions (`scoped` while pending, `artisan`\n // once approved) is enforced by the callable transactions and their tests.\n // `servingStatus` stays orthogonal too — moderation hide/quarantine is independent of a\n // file's realm standing.\n const requestFields = [\n ['realmFileShareRequestId', val.realmFileShareRequestId],\n ['realmFileShareRequestedByUid', val.realmFileShareRequestedByUid],\n ['realmFileShareRequestedAt', val.realmFileShareRequestedAt],\n ] as const;\n\n const forbid = (path: string, value: unknown, message: string) => {\n if (value !== undefined) ctx.addIssue({ code: 'custom', path: [path], message });\n };\n const require_ = (path: string, value: unknown, message: string) => {\n if (value === undefined) ctx.addIssue({ code: 'custom', path: [path], message });\n };\n\n if (val.realmFileCanonStatus === 'none') {\n forbid('realmId', val.realmId, 'realmId is only set on a realm-shared or pending asset (realmFileCanonStatus is \"none\")');\n forbid('realmFileFolderId', val.realmFileFolderId, 'realmFileFolderId is only set on an APPROVED realm-shared asset (realmFileCanonStatus is \"none\")');\n for (const [path, value] of requestFields) {\n forbid(path, value, `${path} is only set while a promotion request is pending (realmFileCanonStatus is \"none\")`);\n }\n return;\n }\n\n require_('realmId', val.realmId, `realmId is required whenever realmFileCanonStatus is \"${val.realmFileCanonStatus}\"`);\n\n if (val.realmFileCanonStatus === 'pendingApproval') {\n forbid('realmFileFolderId', val.realmFileFolderId, 'a pending request has no folder yet — the steward assigns the folder AT approval');\n for (const [path, value] of requestFields) {\n require_(path, value, `${path} is required while realmFileCanonStatus is \"pendingApproval\"`);\n }\n return;\n }\n\n // 'nonCanon' | 'canon' — approved into the pool.\n require_('realmFileFolderId', val.realmFileFolderId, `realmFileFolderId is required on an approved realm file (realmFileCanonStatus is \"${val.realmFileCanonStatus}\")`);\n for (const [path, value] of requestFields) {\n forbid(path, value, `${path} must be cleared once the request is resolved (realmFileCanonStatus is \"${val.realmFileCanonStatus}\")`);\n }\n});\nexport type MediaAsset = z.infer<typeof MediaAssetSchema>;\n"]}
@@ -15,7 +15,12 @@ export declare const workRealmIdSchema: z.ZodString;
15
15
  export declare const realmFileFolderIdSchema: z.ZodString;
16
16
  /** The CLIENT-generated stable id of one realm-file promotion request. Approval, decline,
17
17
  * and withdrawal all carry it and compare it against the pending request recorded on the
18
- * asset, so a stale tab can never decide a newer re-request. */
18
+ * asset, so a stale tab can never decide a newer re-request.
19
+ *
20
+ * BOUNDED at the atom: this id is client-chosen AND durably persisted (asset doc, audit
21
+ * payload, notification metadata, aggregation key), so an unbounded string is a write
22
+ * amplification an attacker can send without the UI. Every consumer inherits the cap by
23
+ * using this atom rather than restating a bound. */
19
24
  export declare const realmFileShareRequestIdSchema: z.ZodString;
20
25
  export declare const notificationFanoutJobIdSchema: z.ZodString;
21
26
  export declare const taleIdSchema: z.ZodString;
@@ -1 +1 @@
1
- {"version":3,"file":"atoms.d.ts","sourceRoot":"","sources":["../../src/schemas/atoms.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB,eAAO,MAAM,mBAAmB,aAAoB,CAAC;AACrD,eAAO,MAAM,YAAY,aAAoB,CAAC;AAC9C,eAAO,MAAM,mBAAmB,aAAoB,CAAC;AACrD,eAAO,MAAM,iBAAiB,aAAoB,CAAC;AACnD,eAAO,MAAM,gBAAgB,aAAoB,CAAC;AAClD,eAAO,MAAM,yBAAyB,aAAoB,CAAC;AAC3D,eAAO,MAAM,0BAA0B,aAAoB,CAAC;AAC5D,eAAO,MAAM,qBAAqB,aAAoB,CAAC;AACvD,eAAO,MAAM,wBAAwB,aAAoB,CAAC;AAC1D,eAAO,MAAM,sBAAsB,aAAoB,CAAC;AACxD,eAAO,MAAM,iBAAiB,aAAoB,CAAC;AACnD;4FAC4F;AAC5F,eAAO,MAAM,uBAAuB,aAAoB,CAAC;AACzD;;iEAEiE;AACjE,eAAO,MAAM,6BAA6B,aAAoB,CAAC;AAC/D,eAAO,MAAM,6BAA6B,aAAoB,CAAC;AAC/D,eAAO,MAAM,YAAY,aAAoB,CAAC;AAC9C,eAAO,MAAM,YAAY,aAAoB,CAAC;AAC9C,eAAO,MAAM,kBAAkB,aAAoB,CAAC;AACpD,eAAO,MAAM,eAAe,aAAoB,CAAC;AACjD,eAAO,MAAM,aAAa,aAAoB,CAAC;AAC/C,eAAO,MAAM,eAAe,aAAoB,CAAC;AACjD,eAAO,MAAM,kBAAkB,aAAoB,CAAC;AACpD,eAAO,MAAM,YAAY,aAAoB,CAAC;AAC9C,eAAO,MAAM,qBAAqB,aAAoB,CAAC;AACvD,eAAO,MAAM,mBAAmB,aAAoB,CAAC;AACrD,eAAO,MAAM,kBAAkB,aAAoB,CAAC;AACpD,eAAO,MAAM,gBAAgB,aAAoB,CAAC;AAClD,eAAO,MAAM,YAAY,aAAoB,CAAC;AAC9C,eAAO,MAAM,qBAAqB,aAAoB,CAAC;AACvD,eAAO,MAAM,qBAAqB,aAAoB,CAAC;AAGvD,eAAO,MAAM,qBAAqB;;;EAA4B,CAAC;AAE/D,eAAO,MAAM,qBAAqB;;;;EAAiC,CAAC;AACpE,eAAO,MAAM,kBAAkB;;;;EAA4D,CAAC;AAU5F,eAAO,MAAM,gCAAgC;;;;;;;;;EAK5C,CAAC;AAOF,eAAO,MAAM,mCAAmC;;;;;;EAM9C,CAAC;AACH,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mCAAmC,CAAC,CAAC;AAEhG;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,aAA0C,CAAC;AAK1E,eAAO,MAAM,WAAW,aAAuD,CAAC"}
1
+ {"version":3,"file":"atoms.d.ts","sourceRoot":"","sources":["../../src/schemas/atoms.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAcxB,eAAO,MAAM,mBAAmB,aAAoB,CAAC;AACrD,eAAO,MAAM,YAAY,aAAoB,CAAC;AAC9C,eAAO,MAAM,mBAAmB,aAAoB,CAAC;AACrD,eAAO,MAAM,iBAAiB,aAAoB,CAAC;AACnD,eAAO,MAAM,gBAAgB,aAAoB,CAAC;AAClD,eAAO,MAAM,yBAAyB,aAAoB,CAAC;AAC3D,eAAO,MAAM,0BAA0B,aAAoB,CAAC;AAC5D,eAAO,MAAM,qBAAqB,aAAoB,CAAC;AACvD,eAAO,MAAM,wBAAwB,aAAoB,CAAC;AAC1D,eAAO,MAAM,sBAAsB,aAAoB,CAAC;AACxD,eAAO,MAAM,iBAAiB,aAAoB,CAAC;AACnD;4FAC4F;AAC5F,eAAO,MAAM,uBAAuB,aAAoB,CAAC;AACzD;;;;;;;qDAOqD;AACrD,eAAO,MAAM,6BAA6B,aAGI,CAAC;AAC/C,eAAO,MAAM,6BAA6B,aAAoB,CAAC;AAC/D,eAAO,MAAM,YAAY,aAAoB,CAAC;AAC9C,eAAO,MAAM,YAAY,aAAoB,CAAC;AAC9C,eAAO,MAAM,kBAAkB,aAAoB,CAAC;AACpD,eAAO,MAAM,eAAe,aAAoB,CAAC;AACjD,eAAO,MAAM,aAAa,aAAoB,CAAC;AAC/C,eAAO,MAAM,eAAe,aAAoB,CAAC;AACjD,eAAO,MAAM,kBAAkB,aAAoB,CAAC;AACpD,eAAO,MAAM,YAAY,aAAoB,CAAC;AAC9C,eAAO,MAAM,qBAAqB,aAAoB,CAAC;AACvD,eAAO,MAAM,mBAAmB,aAAoB,CAAC;AACrD,eAAO,MAAM,kBAAkB,aAAoB,CAAC;AACpD,eAAO,MAAM,gBAAgB,aAAoB,CAAC;AAClD,eAAO,MAAM,YAAY,aAAoB,CAAC;AAC9C,eAAO,MAAM,qBAAqB,aAAoB,CAAC;AACvD,eAAO,MAAM,qBAAqB,aAAoB,CAAC;AAGvD,eAAO,MAAM,qBAAqB;;;EAA4B,CAAC;AAE/D,eAAO,MAAM,qBAAqB;;;;EAAiC,CAAC;AACpE,eAAO,MAAM,kBAAkB;;;;EAA4D,CAAC;AAU5F,eAAO,MAAM,gCAAgC;;;;;;;;;EAK5C,CAAC;AAOF,eAAO,MAAM,mCAAmC;;;;;;EAM9C,CAAC;AACH,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mCAAmC,CAAC,CAAC;AAEhG;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,aAA0C,CAAC;AAK1E,eAAO,MAAM,WAAW,aAAuD,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { MAX_WORK_PROJECT_TITLE_LENGTH } from '../constants/business.js';
2
+ import { MAX_WORK_PROJECT_TITLE_LENGTH, MAX_REALM_FILE_SHARE_REQUEST_ID_LENGTH, } from '../constants/business.js';
3
3
  import { WORK_PROJECT_TYPE_KEYS } from '../types/content.js';
4
4
  import { MODERATION_CLEARABLE_TEXT_FIELDS, } from '../constants/business-content.js';
5
5
  // ID atoms — every callable input that includes an ID field uses one of these.
@@ -21,8 +21,16 @@ export const workRealmIdSchema = z.string().min(1);
21
21
  export const realmFileFolderIdSchema = z.string().min(1);
22
22
  /** The CLIENT-generated stable id of one realm-file promotion request. Approval, decline,
23
23
  * and withdrawal all carry it and compare it against the pending request recorded on the
24
- * asset, so a stale tab can never decide a newer re-request. */
25
- export const realmFileShareRequestIdSchema = z.string().min(1);
24
+ * asset, so a stale tab can never decide a newer re-request.
25
+ *
26
+ * BOUNDED at the atom: this id is client-chosen AND durably persisted (asset doc, audit
27
+ * payload, notification metadata, aggregation key), so an unbounded string is a write
28
+ * amplification an attacker can send without the UI. Every consumer inherits the cap by
29
+ * using this atom rather than restating a bound. */
30
+ export const realmFileShareRequestIdSchema = z
31
+ .string()
32
+ .min(1)
33
+ .max(MAX_REALM_FILE_SHARE_REQUEST_ID_LENGTH);
26
34
  export const notificationFanoutJobIdSchema = z.string().min(1);
27
35
  export const taleIdSchema = z.string().min(1);
28
36
  export const tuneIdSchema = z.string().min(1);
@@ -1 +1 @@
1
- {"version":3,"file":"atoms.js","sourceRoot":"","sources":["../../src/schemas/atoms.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\nimport { MAX_WORK_PROJECT_TITLE_LENGTH } from '../constants/business.js';\nimport { WORK_PROJECT_TYPE_KEYS } from '../types/content.js';\nimport {\n MODERATION_CLEARABLE_TEXT_FIELDS,\n type ModerationClearableSurface,\n} from '../constants/business-content.js';\n\n// ID atoms — every callable input that includes an ID field uses one of these.\n// Kept as separate constants (not aliases of a generic `idSchema`) so consumers\n// reading a callable's schema can see exactly which entity the field refers to.\nexport const workProjectIdSchema = z.string().min(1);\nexport const userIdSchema = z.string().min(1);\nexport const guildInviteIdSchema = z.string().min(1);\nexport const violationIdSchema = z.string().min(1);\nexport const auditionIdSchema = z.string().min(1);\nexport const commissionListingIdSchema = z.string().min(1);\nexport const commissionProposalIdSchema = z.string().min(1);\nexport const auditionEntryIdSchema = z.string().min(1);\nexport const guildChatChannelIdSchema = z.string().min(1);\nexport const workFileFolderIdSchema = z.string().min(1);\nexport const workRealmIdSchema = z.string().min(1);\n/** A folder in a Realm's shared-file pool (`workRealms/{id}/realmFileFolders/{id}`) —\n * distinct from `workFileFolderIdSchema`, which addresses a WORK's private file folder. */\nexport const realmFileFolderIdSchema = z.string().min(1);\n/** The CLIENT-generated stable id of one realm-file promotion request. Approval, decline,\n * and withdrawal all carry it and compare it against the pending request recorded on the\n * asset, so a stale tab can never decide a newer re-request. */\nexport const realmFileShareRequestIdSchema = z.string().min(1);\nexport const notificationFanoutJobIdSchema = z.string().min(1);\nexport const taleIdSchema = z.string().min(1);\nexport const tuneIdSchema = z.string().min(1);\nexport const televisionIdSchema = z.string().min(1);\nexport const chapterIdSchema = z.string().min(1);\nexport const trackIdSchema = z.string().min(1);\nexport const episodeIdSchema = z.string().min(1);\nexport const craftSkillIdSchema = z.string().min(1);\nexport const taskIdSchema = z.string().min(1);\nexport const adminDispatchIdSchema = z.string().min(1);\nexport const reportGroupIdSchema = z.string().min(1);\nexport const mediaAssetIdSchema = z.string().min(1);\nexport const hallItemIdSchema = z.string().min(1);\nexport const itemIdSchema = z.string().min(1);\nexport const thresholdItemIdSchema = z.string().min(1);\nexport const changeRequestIdSchema = z.string().min(1);\n\n// Action / enum atoms.\nexport const addRemoveActionSchema = z.enum(['add', 'remove']);\n// Derives from the ONE canonical WORK_PROJECT_TYPE_KEYS (types/content.ts) — never re-declared.\nexport const workProjectTypeSchema = z.enum(WORK_PROJECT_TYPE_KEYS);\nexport const hallWingTypeSchema = z.enum(['entertainment', 'educational', 'newsPolitical']);\n\n// The moderation-clearable SURFACE atom (`workProject` | `workRealm` | `tale` | `tune` |\n// `television` | `chapter` | `tuneTrack` | `televisionEpisode`). Derived from the KEYS of the\n// canonical MODERATION_CLEARABLE_TEXT_FIELDS map (constants/business-content.ts) rather than\n// restating them, so a surface added to that map is on the wire automatically and the enum can\n// never drift from the field map a consumer indexes with the parsed value. The cast only supplies\n// zod's non-empty-tuple shape — the runtime values ARE the map's keys, and `z.infer` is exactly\n// `ModerationClearableSurface`. Lives here (a leaf module) because the constants layer is\n// deliberately zod-free, mirroring `workProjectTypeSchema` above.\nexport const moderationClearableSurfaceSchema = z.enum(\n Object.keys(MODERATION_CLEARABLE_TEXT_FIELDS) as [\n ModerationClearableSurface,\n ...ModerationClearableSurface[],\n ],\n);\n\n// The ONE canonical guild-invite conversation status set (state machine: pending →\n// accepted (transient, trigger-consumed) → finalized, or pending → declined/cancelled).\n// Lives here (a leaf module) because both the doc schema (doc-schemas/messaging.ts) and\n// the list-invites input (work-project-management.ts) derive from it and those two files\n// import each other's siblings — never re-declare it inline.\nexport const guildInviteConversationStatusSchema = z.enum([\n 'pending',\n 'accepted',\n 'declined',\n 'cancelled',\n 'finalized',\n]);\nexport type GuildInviteConversationStatus = z.infer<typeof guildInviteConversationStatusSchema>;\n\n/**\n * A strict `YYYY-MM-DD` LOCAL calendar date. Declared once here (a leaf module) because both\n * the site-tour callable input (./users.ts) and the persisted site-tour state\n * (../doc-schemas/user.ts `notTodayDate`) must accept exactly the same shape — a looser\n * reader would let a value the writer rejects sit undetected in the document.\n * Deliberately NOT a full calendar validity check: it is a wire/shape bound, and the\n * semantic \"is this the member's today\" decision belongs to the reader.\n */\nexport const calendarDateSchema = z.string().regex(/^\\d{4}-\\d{2}-\\d{2}$/);\n\n// String shape atoms. Length derives from the owning constant — every title alias\n// (tale/tune/tv/chapter/track/episode/commission) resolves to the same value, so the\n// UI counter, the Save guard, and this server bound are provably the same rule.\nexport const titleSchema = z.string().min(1).max(MAX_WORK_PROJECT_TITLE_LENGTH);\n\n\n"]}
1
+ {"version":3,"file":"atoms.js","sourceRoot":"","sources":["../../src/schemas/atoms.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\nimport {\n MAX_WORK_PROJECT_TITLE_LENGTH,\n MAX_REALM_FILE_SHARE_REQUEST_ID_LENGTH,\n} from '../constants/business.js';\nimport { WORK_PROJECT_TYPE_KEYS } from '../types/content.js';\nimport {\n MODERATION_CLEARABLE_TEXT_FIELDS,\n type ModerationClearableSurface,\n} from '../constants/business-content.js';\n\n// ID atoms — every callable input that includes an ID field uses one of these.\n// Kept as separate constants (not aliases of a generic `idSchema`) so consumers\n// reading a callable's schema can see exactly which entity the field refers to.\nexport const workProjectIdSchema = z.string().min(1);\nexport const userIdSchema = z.string().min(1);\nexport const guildInviteIdSchema = z.string().min(1);\nexport const violationIdSchema = z.string().min(1);\nexport const auditionIdSchema = z.string().min(1);\nexport const commissionListingIdSchema = z.string().min(1);\nexport const commissionProposalIdSchema = z.string().min(1);\nexport const auditionEntryIdSchema = z.string().min(1);\nexport const guildChatChannelIdSchema = z.string().min(1);\nexport const workFileFolderIdSchema = z.string().min(1);\nexport const workRealmIdSchema = z.string().min(1);\n/** A folder in a Realm's shared-file pool (`workRealms/{id}/realmFileFolders/{id}`) —\n * distinct from `workFileFolderIdSchema`, which addresses a WORK's private file folder. */\nexport const realmFileFolderIdSchema = z.string().min(1);\n/** The CLIENT-generated stable id of one realm-file promotion request. Approval, decline,\n * and withdrawal all carry it and compare it against the pending request recorded on the\n * asset, so a stale tab can never decide a newer re-request.\n *\n * BOUNDED at the atom: this id is client-chosen AND durably persisted (asset doc, audit\n * payload, notification metadata, aggregation key), so an unbounded string is a write\n * amplification an attacker can send without the UI. Every consumer inherits the cap by\n * using this atom rather than restating a bound. */\nexport const realmFileShareRequestIdSchema = z\n .string()\n .min(1)\n .max(MAX_REALM_FILE_SHARE_REQUEST_ID_LENGTH);\nexport const notificationFanoutJobIdSchema = z.string().min(1);\nexport const taleIdSchema = z.string().min(1);\nexport const tuneIdSchema = z.string().min(1);\nexport const televisionIdSchema = z.string().min(1);\nexport const chapterIdSchema = z.string().min(1);\nexport const trackIdSchema = z.string().min(1);\nexport const episodeIdSchema = z.string().min(1);\nexport const craftSkillIdSchema = z.string().min(1);\nexport const taskIdSchema = z.string().min(1);\nexport const adminDispatchIdSchema = z.string().min(1);\nexport const reportGroupIdSchema = z.string().min(1);\nexport const mediaAssetIdSchema = z.string().min(1);\nexport const hallItemIdSchema = z.string().min(1);\nexport const itemIdSchema = z.string().min(1);\nexport const thresholdItemIdSchema = z.string().min(1);\nexport const changeRequestIdSchema = z.string().min(1);\n\n// Action / enum atoms.\nexport const addRemoveActionSchema = z.enum(['add', 'remove']);\n// Derives from the ONE canonical WORK_PROJECT_TYPE_KEYS (types/content.ts) — never re-declared.\nexport const workProjectTypeSchema = z.enum(WORK_PROJECT_TYPE_KEYS);\nexport const hallWingTypeSchema = z.enum(['entertainment', 'educational', 'newsPolitical']);\n\n// The moderation-clearable SURFACE atom (`workProject` | `workRealm` | `tale` | `tune` |\n// `television` | `chapter` | `tuneTrack` | `televisionEpisode`). Derived from the KEYS of the\n// canonical MODERATION_CLEARABLE_TEXT_FIELDS map (constants/business-content.ts) rather than\n// restating them, so a surface added to that map is on the wire automatically and the enum can\n// never drift from the field map a consumer indexes with the parsed value. The cast only supplies\n// zod's non-empty-tuple shape — the runtime values ARE the map's keys, and `z.infer` is exactly\n// `ModerationClearableSurface`. Lives here (a leaf module) because the constants layer is\n// deliberately zod-free, mirroring `workProjectTypeSchema` above.\nexport const moderationClearableSurfaceSchema = z.enum(\n Object.keys(MODERATION_CLEARABLE_TEXT_FIELDS) as [\n ModerationClearableSurface,\n ...ModerationClearableSurface[],\n ],\n);\n\n// The ONE canonical guild-invite conversation status set (state machine: pending →\n// accepted (transient, trigger-consumed) → finalized, or pending → declined/cancelled).\n// Lives here (a leaf module) because both the doc schema (doc-schemas/messaging.ts) and\n// the list-invites input (work-project-management.ts) derive from it and those two files\n// import each other's siblings — never re-declare it inline.\nexport const guildInviteConversationStatusSchema = z.enum([\n 'pending',\n 'accepted',\n 'declined',\n 'cancelled',\n 'finalized',\n]);\nexport type GuildInviteConversationStatus = z.infer<typeof guildInviteConversationStatusSchema>;\n\n/**\n * A strict `YYYY-MM-DD` LOCAL calendar date. Declared once here (a leaf module) because both\n * the site-tour callable input (./users.ts) and the persisted site-tour state\n * (../doc-schemas/user.ts `notTodayDate`) must accept exactly the same shape — a looser\n * reader would let a value the writer rejects sit undetected in the document.\n * Deliberately NOT a full calendar validity check: it is a wire/shape bound, and the\n * semantic \"is this the member's today\" decision belongs to the reader.\n */\nexport const calendarDateSchema = z.string().regex(/^\\d{4}-\\d{2}-\\d{2}$/);\n\n// String shape atoms. Length derives from the owning constant — every title alias\n// (tale/tune/tv/chapter/track/episode/commission) resolves to the same value, so the\n// UI counter, the Save guard, and this server bound are provably the same rule.\nexport const titleSchema = z.string().min(1).max(MAX_WORK_PROJECT_TITLE_LENGTH);\n\n\n"]}
@@ -19,12 +19,13 @@ export declare const RealmSharedFileProjectionSchema: z.ZodObject<{
19
19
  workFileId: z.ZodString;
20
20
  }, z.core.$strict>;
21
21
  export type RealmSharedFileProjection = z.infer<typeof RealmSharedFileProjectionSchema>;
22
- /** A Realm shared-file folder as the gallery sees it. Pure container no access lists, no
23
- * stored counts (counts derive from the files in the same response, so a count can never
24
- * disagree with the files actually served). */
22
+ /** A Realm shared-file folder as the gallery sees it. The FOLDER DOCUMENT stores no counts;
23
+ * `fileCount` here is SERVER-COMPUTED per response, so it can never drift the way a stored
24
+ * counter would. */
25
25
  export declare const RealmFileFolderProjectionSchema: z.ZodObject<{
26
26
  realmFileFolderId: z.ZodString;
27
27
  name: z.ZodString;
28
+ fileCount: z.ZodNumber;
28
29
  }, z.core.$strict>;
29
30
  export type RealmFileFolderProjection = z.infer<typeof RealmFileFolderProjectionSchema>;
30
31
  export declare const GetRealmSharedFilesInputSchema: z.ZodObject<{
@@ -58,6 +59,7 @@ export declare const GetRealmSharedFilesResponseSchema: z.ZodObject<{
58
59
  folders: z.ZodArray<z.ZodObject<{
59
60
  realmFileFolderId: z.ZodString;
60
61
  name: z.ZodString;
62
+ fileCount: z.ZodNumber;
61
63
  }, z.core.$strict>>;
62
64
  nextCursor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
63
65
  }, z.core.$strict>;
@@ -110,10 +112,51 @@ export declare const GetRealmFilePromotionQueueResponseSchema: z.ZodObject<{
110
112
  folders: z.ZodArray<z.ZodObject<{
111
113
  realmFileFolderId: z.ZodString;
112
114
  name: z.ZodString;
115
+ fileCount: z.ZodNumber;
113
116
  }, z.core.$strict>>;
114
117
  nextCursor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
115
118
  }, z.core.$strict>;
116
119
  export type GetRealmFilePromotionQueueResponse = z.infer<typeof GetRealmFilePromotionQueueResponseSchema>;
120
+ /** One work file's realm-share state.
121
+ *
122
+ * The `requestId` is present EXACTLY while the file is awaiting a decision — it is what the
123
+ * withdraw call must carry, and it is meaningless once the request is resolved. Enforced
124
+ * rather than merely optional, mirroring the asset's own legal-combination invariant, so the
125
+ * UI can never be handed a pending row with nothing to withdraw (or an approved row carrying
126
+ * a stale request id it might send).
127
+ *
128
+ * `workFileId` uses plain `z.string()` like the sibling projection rows in this file
129
+ * (inputs use `.min(1)`; projection rows describe server-produced data). */
130
+ export declare const WorkFileRealmShareStateSchema: z.ZodObject<{
131
+ workFileId: z.ZodString;
132
+ realmFileCanonStatus: z.ZodEnum<{
133
+ pendingApproval: "pendingApproval";
134
+ nonCanon: "nonCanon";
135
+ canon: "canon";
136
+ }>;
137
+ realmFileShareRequestId: z.ZodOptional<z.ZodString>;
138
+ }, z.core.$strict>;
139
+ export type WorkFileRealmShareState = z.infer<typeof WorkFileRealmShareStateSchema>;
140
+ export declare const GetWorkFileRealmShareStatesInputSchema: z.ZodObject<{
141
+ workProjectId: z.ZodString;
142
+ }, z.core.$strict>;
143
+ export type GetWorkFileRealmShareStatesInput = z.infer<typeof GetWorkFileRealmShareStatesInputSchema>;
144
+ /** Rows exist ONLY for files whose standing is not `none`. An ABSENT row therefore means the
145
+ * file has never been requested or shared — that is the encoding, so the client must treat a
146
+ * missing entry as "not shared" rather than "unknown". Bounded implicitly by the Work's own
147
+ * file cap (MAX_WORK_FILES), so this response needs no page cursor of its own. */
148
+ export declare const GetWorkFileRealmShareStatesResponseSchema: z.ZodObject<{
149
+ states: z.ZodArray<z.ZodObject<{
150
+ workFileId: z.ZodString;
151
+ realmFileCanonStatus: z.ZodEnum<{
152
+ pendingApproval: "pendingApproval";
153
+ nonCanon: "nonCanon";
154
+ canon: "canon";
155
+ }>;
156
+ realmFileShareRequestId: z.ZodOptional<z.ZodString>;
157
+ }, z.core.$strict>>;
158
+ }, z.core.$strict>;
159
+ export type GetWorkFileRealmShareStatesResponse = z.infer<typeof GetWorkFileRealmShareStatesResponseSchema>;
117
160
  export declare const realmWorkingTitleSchema: z.ZodString;
118
161
  export declare const RealmCreationModeSchema: z.ZodEnum<{
119
162
  newPublicRealm: "newPublicRealm";
@@ -1 +1 @@
1
- {"version":3,"file":"work-project-management.d.ts","sourceRoot":"","sources":["../../src/schemas/work-project-management.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"work-project-management.d.ts","sourceRoot":"","sources":["../../src/schemas/work-project-management.ts"],"names":[],"mappings":"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"}
@@ -4,7 +4,7 @@ import { TRADE_PROFESSION_OPTIONS, TRADE_PROFESSION_VALUES } from '../constants/
4
4
  import { GUILD_STANDING_VALUES } from '../permissions/index.js';
5
5
  import { MAX_GUILD_INVITE_MESSAGE_LENGTH, MAX_WORK_PROJECT_TITLE_LENGTH, MAX_WORK_PROJECT_DESCRIPTION_LENGTH, MAX_WORK_REALM_TITLE_LENGTH, MAX_WORK_REALM_DESCRIPTION_LENGTH, MAX_CRAFT_SKILL_NAME_LENGTH, MAX_FILE_FOLDER_NAME_LENGTH, } from '../constants/business.js';
6
6
  import { REALM_SHARED_FILES_PAGE_LIMIT, REALM_FILE_PROMOTION_QUEUE_PAGE_LIMIT, } from '../constants/pagination.js';
7
- import { RealmFileApprovedStatusSchema, RealmFilePendingApprovalStatusSchema, ContentMediaKindSchema, } from '../doc-schemas/media-assets.js';
7
+ import { RealmFileApprovedStatusSchema, RealmFilePendingApprovalStatusSchema, RealmFileActiveStatusSchema, REALM_FILE_PENDING_APPROVAL_STATUS, ContentMediaKindSchema, } from '../doc-schemas/media-assets.js';
8
8
  // ===========================================================================
9
9
  // S7 realm shared-files gallery (ARTISAN-ONLY, plus a full-admin bypass for the admin-only
10
10
  // un-share support action). `mediaAssets` is client-unreadable, so the gallery reads
@@ -38,12 +38,18 @@ export const RealmSharedFileProjectionSchema = z.object({
38
38
  workProjectId: workProjectIdSchema,
39
39
  workFileId: z.string(),
40
40
  }).strict();
41
- /** A Realm shared-file folder as the gallery sees it. Pure container no access lists, no
42
- * stored counts (counts derive from the files in the same response, so a count can never
43
- * disagree with the files actually served). */
41
+ /** A Realm shared-file folder as the gallery sees it. The FOLDER DOCUMENT stores no counts;
42
+ * `fileCount` here is SERVER-COMPUTED per response, so it can never drift the way a stored
43
+ * counter would. */
44
44
  export const RealmFileFolderProjectionSchema = z.object({
45
45
  realmFileFolderId: realmFileFolderIdSchema,
46
46
  name: z.string(),
47
+ /** Number of files currently ASSIGNED to this folder — counting every assigned file
48
+ * regardless of canon state and regardless of serving state (a hidden or quarantined file
49
+ * still occupies its folder, and is still why a delete-folder attempt will refuse).
50
+ * Server-computed so the steward UI stops deriving counts from whichever gallery pages
51
+ * happen to be loaded — a paged client can only ever see part of a folder. */
52
+ fileCount: z.number().int().min(0),
47
53
  }).strict();
48
54
  // Paginated: the pre-approval-gate query was unbounded. `limit` is bounded by the ONE named
49
55
  // page constant the server also clamps to, and `cursor` is an OPAQUE server-minted token —
@@ -98,6 +104,57 @@ export const GetRealmFilePromotionQueueResponseSchema = z.object({
98
104
  folders: z.array(RealmFileFolderProjectionSchema),
99
105
  nextCursor: z.string().min(1).nullable().optional(),
100
106
  }).strict();
107
+ // ---- WORK-side share-state projection --------------------------------------------------
108
+ // The mirror image of the two Realm-side projections above, for the WORK's own files surface:
109
+ // a file admin looking at their folder listing needs to know which files are already shared
110
+ // or awaiting a steward decision, so the row can show "Requested" / "Shared" and offer
111
+ // withdraw where it applies.
112
+ //
113
+ // It is a SERVER projection for the same reason the gallery is: `mediaAssets` is
114
+ // client-unreadable, so share state cannot be read from the file document. File-admin
115
+ // authorization is asserted in the callable; this shape carries no authority hint.
116
+ /** One work file's realm-share state.
117
+ *
118
+ * The `requestId` is present EXACTLY while the file is awaiting a decision — it is what the
119
+ * withdraw call must carry, and it is meaningless once the request is resolved. Enforced
120
+ * rather than merely optional, mirroring the asset's own legal-combination invariant, so the
121
+ * UI can never be handed a pending row with nothing to withdraw (or an approved row carrying
122
+ * a stale request id it might send).
123
+ *
124
+ * `workFileId` uses plain `z.string()` like the sibling projection rows in this file
125
+ * (inputs use `.min(1)`; projection rows describe server-produced data). */
126
+ export const WorkFileRealmShareStateSchema = z.object({
127
+ workFileId: z.string(),
128
+ // Never `none`: an unshared file simply has no row (see the response below).
129
+ realmFileCanonStatus: RealmFileActiveStatusSchema,
130
+ realmFileShareRequestId: realmFileShareRequestIdSchema.optional(),
131
+ }).strict().superRefine((val, ctx) => {
132
+ const isPending = val.realmFileCanonStatus === REALM_FILE_PENDING_APPROVAL_STATUS;
133
+ if (isPending && val.realmFileShareRequestId === undefined) {
134
+ ctx.addIssue({
135
+ code: 'custom',
136
+ path: ['realmFileShareRequestId'],
137
+ message: 'a pending row must carry its request id — it is what the withdraw call compares against',
138
+ });
139
+ }
140
+ if (!isPending && val.realmFileShareRequestId !== undefined) {
141
+ ctx.addIssue({
142
+ code: 'custom',
143
+ path: ['realmFileShareRequestId'],
144
+ message: 'a resolved row must not carry a request id — the request is no longer pending',
145
+ });
146
+ }
147
+ });
148
+ export const GetWorkFileRealmShareStatesInputSchema = z.object({
149
+ workProjectId: workProjectIdSchema,
150
+ }).strict();
151
+ /** Rows exist ONLY for files whose standing is not `none`. An ABSENT row therefore means the
152
+ * file has never been requested or shared — that is the encoding, so the client must treat a
153
+ * missing entry as "not shared" rather than "unknown". Bounded implicitly by the Work's own
154
+ * file cap (MAX_WORK_FILES), so this response needs no page cursor of its own. */
155
+ export const GetWorkFileRealmShareStatesResponseSchema = z.object({
156
+ states: z.array(WorkFileRealmShareStateSchema),
157
+ }).strict();
101
158
  const baseFields = {
102
159
  workingTitle: z.string().min(1).max(MAX_WORK_PROJECT_TITLE_LENGTH),
103
160
  workingDescription: z.string().min(1).max(MAX_WORK_PROJECT_DESCRIPTION_LENGTH),
@@ -1 +1 @@
1
- {"version":3,"file":"work-project-management.js","sourceRoot":"","sources":["../../src/schemas/work-project-management.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\nimport {\n workProjectIdSchema,\n userIdSchema,\n addRemoveActionSchema,\n workProjectTypeSchema,\n hallWingTypeSchema,\n commissionListingIdSchema,\n commissionProposalIdSchema,\n auditionIdSchema,\n auditionEntryIdSchema,\n craftSkillIdSchema,\n guildInviteConversationStatusSchema,\n mediaAssetIdSchema,\n workRealmIdSchema,\n realmFileFolderIdSchema,\n realmFileShareRequestIdSchema,\n} from './atoms.js';\nimport { TRADE_PROFESSION_OPTIONS, TRADE_PROFESSION_VALUES } from '../constants/options.js';\nimport { GUILD_STANDING_VALUES } from '../permissions/index.js';\nimport {\n MAX_GUILD_INVITE_MESSAGE_LENGTH,\n MAX_WORK_PROJECT_TITLE_LENGTH,\n MAX_WORK_PROJECT_DESCRIPTION_LENGTH,\n MAX_WORK_REALM_TITLE_LENGTH,\n MAX_WORK_REALM_DESCRIPTION_LENGTH,\n MAX_CRAFT_SKILL_NAME_LENGTH,\n MAX_FILE_FOLDER_NAME_LENGTH,\n} from '../constants/business.js';\nimport {\n REALM_SHARED_FILES_PAGE_LIMIT,\n REALM_FILE_PROMOTION_QUEUE_PAGE_LIMIT,\n} from '../constants/pagination.js';\nimport {\n RealmFileApprovedStatusSchema,\n RealmFilePendingApprovalStatusSchema,\n ContentMediaKindSchema,\n} from '../doc-schemas/media-assets.js';\n\n// ===========================================================================\n// S7 realm shared-files gallery (ARTISAN-ONLY, plus a full-admin bypass for the admin-only\n// un-share support action). `mediaAssets` is client-unreadable, so the gallery reads\n// realm-shared work files via THIS server projection callable (never a client query) — and\n// for the same reason the Realm's FOLDER documents are returned through the same projection\n// owner rather than opened to direct client reads: artisan / admin / hidden-Realm access is\n// decided in ONE backend owner.\n//\n// Serving is the `'artisan'` media tier (mutate-in-place scoped→artisan at APPROVAL — see the\n// approval gate below). V1 = view + download, grouped by the steward's folders.\n// ===========================================================================\n\n/** One APPROVED shared file. Accepts only the two approved standings — a pending or\n * unshared row is structurally inexpressible in this response. */\nexport const RealmSharedFileProjectionSchema = z.object({\n mediaAssetId: mediaAssetIdSchema,\n // The canonical stored media kind — RealmSharedFileProjection is a projection OF a\n // MediaAsset, so it shares the ONE ContentMediaKindSchema.\n mediaKind: ContentMediaKindSchema,\n // Never the full status union: 'nonCanon' | 'canon' only.\n realmFileCanonStatus: RealmFileApprovedStatusSchema,\n /** The Work file's own `name`. A file browser that groups unnamed thumbnails by folder is\n * not a file browser — the name is part of the projection, not something the client is\n * expected to resolve. (It is file metadata, NOT display identity: creator names and\n * avatars still resolve at render from `creatorUid`.) */\n name: z.string(),\n /** The steward-assigned folder this file sits in. Always present — approval IS folder\n * assignment, so an approved file without a folder cannot exist. */\n realmFileFolderId: realmFileFolderIdSchema,\n creatorUid: userIdSchema,\n // For the per-file steward canon toggle + download (updateWorkFileRealmCanon takes these).\n workProjectId: workProjectIdSchema,\n workFileId: z.string(),\n}).strict();\nexport type RealmSharedFileProjection = z.infer<typeof RealmSharedFileProjectionSchema>;\n\n/** A Realm shared-file folder as the gallery sees it. Pure container — no access lists, no\n * stored counts (counts derive from the files in the same response, so a count can never\n * disagree with the files actually served). */\nexport const RealmFileFolderProjectionSchema = z.object({\n realmFileFolderId: realmFileFolderIdSchema,\n name: z.string(),\n}).strict();\nexport type RealmFileFolderProjection = z.infer<typeof RealmFileFolderProjectionSchema>;\n\n// Paginated: the pre-approval-gate query was unbounded. `limit` is bounded by the ONE named\n// page constant the server also clamps to, and `cursor` is an OPAQUE server-minted token —\n// the client never constructs or interprets it, so the ordering fields stay a server detail.\nexport const GetRealmSharedFilesInputSchema = z.object({\n realmId: workRealmIdSchema,\n limit: z.number().int().min(1).max(REALM_SHARED_FILES_PAGE_LIMIT).optional(),\n cursor: z.string().min(1).optional(),\n}).strict();\nexport type GetRealmSharedFilesInput = z.infer<typeof GetRealmSharedFilesInputSchema>;\n\n/** `{ files }` is preserved as-is; `folders` and `nextCursor` are ADDITIVE. `folders` is the\n * Realm's complete folder set (bounded by MAX_REALM_FILE_FOLDERS), not a page — the gallery\n * must be able to render an empty folder, and the steward must see one to move files into.\n * `nextCursor` is absent/null on the last page. */\nexport const GetRealmSharedFilesResponseSchema = z.object({\n files: z.array(RealmSharedFileProjectionSchema),\n folders: z.array(RealmFileFolderProjectionSchema),\n nextCursor: z.string().min(1).nullable().optional(),\n}).strict();\nexport type GetRealmSharedFilesResponse = z.infer<typeof GetRealmSharedFilesResponseSchema>;\n\n// ---- realm-file promotion queue (steward / full admin) ---------------------------------\n// A SEPARATE bounded projection rather than an `includePending` flag on the artisan gallery:\n// a caller-controlled flag would put \"may this caller see pending rows\" in the client's\n// hands. Ordinary artisans can never enumerate pending requests.\n\n/** One AWAITING-DECISION request. Accepts only the pending-approval standing (via\n * RealmFilePendingApprovalStatusSchema) — an approved or unshared row is structurally\n * inexpressible in the queue. */\nexport const RealmFilePromotionQueueRowSchema = z.object({\n mediaAssetId: mediaAssetIdSchema,\n mediaKind: ContentMediaKindSchema,\n realmFileCanonStatus: RealmFilePendingApprovalStatusSchema,\n /** The Work file's own name — the steward decides on a named file, not a thumbnail. */\n name: z.string(),\n creatorUid: userIdSchema,\n workProjectId: workProjectIdSchema,\n workFileId: z.string(),\n /** Echoed so the approve/decline call can carry the exact observed request id; a stale tab\n * deciding a superseded request is then a visible conflict, not a silent overwrite. */\n realmFileShareRequestId: realmFileShareRequestIdSchema,\n /** The RECORDED requester — the resolution notification is addressed from this, never\n * guessed from the uploader. */\n realmFileShareRequestedByUid: userIdSchema,\n realmFileShareRequestedAt: z.number(),\n}).strict();\nexport type RealmFilePromotionQueueRow = z.infer<typeof RealmFilePromotionQueueRowSchema>;\n\nexport const GetRealmFilePromotionQueueInputSchema = z.object({\n workRealmId: workRealmIdSchema,\n limit: z.number().int().min(1).max(REALM_FILE_PROMOTION_QUEUE_PAGE_LIMIT).optional(),\n cursor: z.string().min(1).optional(),\n}).strict();\nexport type GetRealmFilePromotionQueueInput = z.infer<typeof GetRealmFilePromotionQueueInputSchema>;\n\n/** `folders` rides along so the approval UI can offer the folder picker (and detect the\n * \"no folders yet\" state) without a second round-trip. */\nexport const GetRealmFilePromotionQueueResponseSchema = z.object({\n requests: z.array(RealmFilePromotionQueueRowSchema),\n folders: z.array(RealmFileFolderProjectionSchema),\n nextCursor: z.string().min(1).nullable().optional(),\n}).strict();\nexport type GetRealmFilePromotionQueueResponse = z.infer<typeof GetRealmFilePromotionQueueResponseSchema>;\n\nconst baseFields = {\n workingTitle: z.string().min(1).max(MAX_WORK_PROJECT_TITLE_LENGTH),\n workingDescription: z.string().min(1).max(MAX_WORK_PROJECT_DESCRIPTION_LENGTH),\n workProjectType: workProjectTypeSchema,\n hallWingType: hallWingTypeSchema,\n};\n\n// A Realm working title is reserved under `reservedRealmNames/{UPPER(title)}` — the\n// UPPERCASED title IS the Firestore doc ID (runCreateWorkRealm.reservedRealmNameRef).\n// Firestore doc IDs cannot contain `/` and cannot be exactly `.` or `..`, so a title\n// that would produce an invalid/ambiguous doc ID must be rejected at the callable\n// boundary (both the create transaction and the soft availability check) rather than\n// hard-failing with an opaque `internal` error deep inside ref construction. Length\n// derives from MAX_WORK_REALM_TITLE_LENGTH; only the doc-ID-breaking characters are\n// forbidden. Keep CheckRealmNameAvailableInputSchema in lockstep so a valid-at-create\n// name is never rejected at form time (and vice-versa).\nexport const realmWorkingTitleSchema = z\n .string()\n .min(1)\n .max(MAX_WORK_REALM_TITLE_LENGTH)\n .refine((v) => !v.includes('/'), { message: 'Realm name cannot contain a slash (/).' })\n .refine((v) => v !== '.' && v !== '..', { message: 'Realm name cannot be \".\" or \"..\".' });\n\nexport const RealmCreationModeSchema = z.enum([\n 'newPublicRealm',\n 'newStandaloneRealm',\n 'existingPublicRealm',\n]);\nexport type RealmCreationMode = z.infer<typeof RealmCreationModeSchema>;\n\nexport const CreateWorkProjectInputSchema = z.discriminatedUnion('realmCreationMode', [\n z.object({\n ...baseFields,\n realmCreationMode: z.literal('newPublicRealm'),\n realmWorkingTitle: realmWorkingTitleSchema,\n realmWorkingDescription: z.string().min(1).max(MAX_WORK_REALM_DESCRIPTION_LENGTH),\n }).strict(),\n // Standalone realms are background plumbing (DJ ruling 2026-07-19): the user enters NO\n // realm information — the backend creates the realm shell with a synthetic unique\n // title/description (the generated workRealmId), so nothing user-authored exists on it\n // and no human realm name is consumed from the reservedRealmNames namespace.\n z.object({\n ...baseFields,\n realmCreationMode: z.literal('newStandaloneRealm'),\n }).strict(),\n z.object({\n ...baseFields,\n realmCreationMode: z.literal('existingPublicRealm'),\n workRealmId: z.string().min(1),\n }).strict(),\n]);\nexport type CreateWorkProjectInput = z.infer<typeof CreateWorkProjectInputSchema>;\n\n// Identified by the workAssets subcollection doc id — never by URL parsing\n// (no delete path may depend on a URL; see media-assets-and-protected-serving.md).\nexport const DeleteWorkAssetInputSchema = z.object({\n workProjectId: workProjectIdSchema,\n workAssetId: z.string().min(1),\n}).strict();\nexport type DeleteWorkAssetInput = z.infer<typeof DeleteWorkAssetInputSchema>;\n\nexport const InviteSourceSchema = z.discriminatedUnion('type', [\n z.object({\n type: z.literal('standalone'),\n }).strict(),\n z.object({\n type: z.literal('craftSkill'),\n data: z.object({\n craftSkillId: craftSkillIdSchema,\n craftSkillOwnerUserId: userIdSchema,\n craftSkillName: z.string().min(1).max(MAX_CRAFT_SKILL_NAME_LENGTH),\n }).strict(),\n }).strict(),\n z.object({\n type: z.literal('commission'),\n // Titles are NOT snapshotted here (Display Identity Invariant — client display text\n // must be re-sourced at render by id). `postingStakeSharesOffered` is not display text;\n // the server re-sources it from the posting doc in the invite transaction (never trusts\n // the client copy) — kept so the shape stays server-writable.\n data: z.object({\n commissionListingId: commissionListingIdSchema,\n commissionProposalId: commissionProposalIdSchema,\n proposalArtisanUserId: userIdSchema,\n postingStakeSharesOffered: z.number().int().min(1),\n }).strict(),\n }).strict(),\n z.object({\n type: z.literal('audition'),\n data: z.object({\n auditionId: auditionIdSchema,\n auditionEntryId: auditionEntryIdSchema,\n respondentUserId: userIdSchema,\n postingStakeSharesOffered: z.number().int().min(1),\n }).strict(),\n }).strict(),\n]);\nexport type InviteSource = z.infer<typeof InviteSourceSchema>;\nexport type InviteSourceType = InviteSource['type'];\n\nexport const InviteUserToGuildInputSchema = z.object({\n workProjectId: workProjectIdSchema,\n inviteeUid: userIdSchema,\n message: z.string().min(1).max(MAX_GUILD_INVITE_MESSAGE_LENGTH),\n stakeSharesOffered: z.number().int().min(1),\n source: InviteSourceSchema,\n}).strict();\nexport type InviteUserToGuildInput = z.infer<typeof InviteUserToGuildInputSchema>;\n\n// `finalized` is the terminal SUCCESS state (`accepted` is a transient state a trigger\n// consumes within seconds). Managers must be able to list finalized invites to see the\n// guild's actual recruitment history — not only failures and in-flight items. Derives from\n// the ONE canonical status enum (schemas/atoms.ts), never a re-declared literal.\nexport const ListGuildInvitesInputSchema = z.object({\n workProjectId: workProjectIdSchema,\n statuses: z.array(guildInviteConversationStatusSchema).min(1),\n}).strict();\nexport type ListGuildInvitesInput = z.infer<typeof ListGuildInvitesInputSchema>;\n\nexport const UpdateGuildmateTradeProfessionsInputSchema = z.object({\n workProjectId: workProjectIdSchema,\n userId: userIdSchema,\n tradeProfession: z.enum(TRADE_PROFESSION_VALUES),\n action: addRemoveActionSchema,\n}).strict();\nexport type UpdateGuildmateTradeProfessionsInput = z.infer<typeof UpdateGuildmateTradeProfessionsInputSchema>;\n\nconst GUILD_STANDING_VALUES_ENUM = GUILD_STANDING_VALUES as [typeof GUILD_STANDING_VALUES[number], ...typeof GUILD_STANDING_VALUES[number][]];\n\nexport const UpdateGuildmateStandingInputSchema = z.object({\n workProjectId: workProjectIdSchema,\n userId: userIdSchema,\n guildStanding: z.enum(GUILD_STANDING_VALUES_ENUM),\n action: addRemoveActionSchema,\n}).strict();\nexport type UpdateGuildmateStandingInput = z.infer<typeof UpdateGuildmateStandingInputSchema>;\n\n// Member self-leave (leaveWorkProject). The leaver is ALWAYS request.auth.uid — never a\n// client-supplied uid (invariant 3) — so the input carries only the workProjectId. The\n// callable composes the internal `depart` stake-share operation for ctx.uid.\nexport const LeaveWorkProjectInputSchema = z.object({\n workProjectId: workProjectIdSchema,\n}).strict();\nexport type LeaveWorkProjectInput = z.infer<typeof LeaveWorkProjectInputSchema>;\n\nexport const UpdatePublicWorkProjectDetailsInputSchema = z.object({\n workProjectId: workProjectIdSchema,\n workingTitle: z.string().min(1).max(MAX_WORK_PROJECT_TITLE_LENGTH),\n workingDescription: z.string().min(1).max(MAX_WORK_PROJECT_DESCRIPTION_LENGTH),\n}).strict();\nexport type UpdatePublicWorkProjectDetailsInput = z.infer<typeof UpdatePublicWorkProjectDetailsInputSchema>;\n\nexport const UpdateWorkRealmDetailsInputSchema = z.object({\n workRealmId: z.string().min(1),\n workingTitle: z.string().min(1).max(MAX_WORK_REALM_TITLE_LENGTH),\n workingDescription: z.string().min(1).max(MAX_WORK_REALM_DESCRIPTION_LENGTH),\n}).strict();\nexport type UpdateWorkRealmDetailsInput = z.infer<typeof UpdateWorkRealmDetailsInputSchema>;\n\n// Unauthenticated soft-check for a Realm working title. Must match the authoritative\n// realmWorkingTitle contract in CreateWorkProjectInputSchema (realmWorkingTitleSchema:\n// MAX_WORK_REALM_TITLE_LENGTH, rejecting the doc-ID-breaking `/` and reserved `.`/`..`). Never be\n// stricter than the create transaction or a valid-at-create name would be rejected at\n// form time — reuse the SAME schema so the two can never drift.\nexport const CheckRealmNameAvailableInputSchema = z.object({\n workingTitle: realmWorkingTitleSchema,\n}).strict();\nexport type CheckRealmNameAvailableInput = z.infer<typeof CheckRealmNameAvailableInputSchema>;\n\n// ---- work-project file folders (S7) ---------------------------------------------------\n// The default \"All Guildmates\" folder is immutable; custom-folder access is by trade\n// profession. All four callables require a file-admin standing via assertCanManageFolders.\n\nconst tradeProfessionListSchema = z\n .array(z.enum(TRADE_PROFESSION_VALUES))\n .max(TRADE_PROFESSION_OPTIONS.length);\n\nexport const CreateFileFolderInputSchema = z.object({\n workProjectId: z.string().min(1),\n name: z.string().min(1).max(MAX_FILE_FOLDER_NAME_LENGTH),\n canViewTradeProfessions: tradeProfessionListSchema,\n canUploadTradeProfessions: tradeProfessionListSchema,\n canDeleteTradeProfessions: tradeProfessionListSchema,\n}).strict();\nexport type CreateFileFolderInput = z.infer<typeof CreateFileFolderInputSchema>;\n\nexport const RenameFileFolderInputSchema = z.object({\n workProjectId: z.string().min(1),\n folderId: z.string().min(1),\n name: z.string().min(1).max(MAX_FILE_FOLDER_NAME_LENGTH),\n}).strict();\nexport type RenameFileFolderInput = z.infer<typeof RenameFileFolderInputSchema>;\n\nexport const UpdateFolderProfessionsInputSchema = z.object({\n workProjectId: z.string().min(1),\n folderId: z.string().min(1),\n canViewTradeProfessions: tradeProfessionListSchema,\n canUploadTradeProfessions: tradeProfessionListSchema,\n canDeleteTradeProfessions: tradeProfessionListSchema,\n}).strict();\nexport type UpdateFolderProfessionsInput = z.infer<typeof UpdateFolderProfessionsInputSchema>;\n\nexport const DeleteFileFolderInputSchema = z.object({\n workProjectId: z.string().min(1),\n folderId: z.string().min(1),\n}).strict();\nexport type DeleteFileFolderInput = z.infer<typeof DeleteFileFolderInputSchema>;\n\n// ---- realm shared files ---------------------------------------------------------------\n\n// Delete a single work file (by folder + file id). File-admin authz is enforced in the\n// callable/core transaction.\nexport const DeleteWorkFileInputSchema = z.object({\n workProjectId: z.string().min(1),\n folderId: z.string().min(1),\n workFileId: z.string().min(1),\n}).strict();\nexport type DeleteWorkFileInput = z.infer<typeof DeleteWorkFileInputSchema>;\n\n// Set canon status on a realm shared file. Realm-steward-only authz is enforced inside the\n// core's transaction against workRealms/{workRealmId}.workStewardUid.\nexport const UpdateWorkFileRealmCanonInputSchema = z.object({\n workRealmId: workRealmIdSchema,\n mediaAssetId: mediaAssetIdSchema,\n canon: z.boolean(),\n}).strict();\nexport type UpdateWorkFileRealmCanonInput = z.infer<typeof UpdateWorkFileRealmCanonInputSchema>;\n\n// ---- the promotion approval gate -------------------------------------------------------\n// Promotion is a REQUEST, not an instant share: the Work file admin asks, and the REALM\n// steward approves (choosing the folder) or declines. Nothing is served to the Realm until\n// approval — a requested file stays `scoped` and invisible to the member gallery.\n//\n// Every one of these carries the `requestId` so a decision always names the exact request it\n// observed. Realm-side authority (steward, public + non-hidden Realm) is derived from the\n// Realm document inside each core's transaction; these shapes carry no authority hints.\n\n// REQUEST promotion of a work file into its Realm's shared-file pool. File-admin authz\n// (`workFile.promoteToRealm`) is enforced inside the core's transaction.\n// `requestId` is CLIENT-generated and stable: replaying the same id is an idempotent success\n// (no second audit event, no second notification), while a DIFFERENT id arriving while one\n// request is already pending is a conflict — never a silent overwrite.\nexport const UpdateWorkFileRealmShareInputSchema = z.object({\n workProjectId: workProjectIdSchema,\n workFileId: z.string().min(1),\n requestId: realmFileShareRequestIdSchema,\n}).strict();\nexport type UpdateWorkFileRealmShareInput = z.infer<typeof UpdateWorkFileRealmShareInputSchema>;\n\n// WITHDRAW a still-pending request (the requesting Work's file admin). Realm-share\n// permanence begins at APPROVAL — before a steward decides, an accidental request must be\n// correctable by the side that made it. Addressed by Work coordinates like the request\n// itself, and compares `requestId` so a withdrawal can never cancel a newer re-request.\nexport const WithdrawRealmFilePromotionRequestInputSchema = z.object({\n workProjectId: workProjectIdSchema,\n workFileId: z.string().min(1),\n requestId: realmFileShareRequestIdSchema,\n}).strict();\nexport type WithdrawRealmFilePromotionRequestInput = z.infer<typeof WithdrawRealmFilePromotionRequestInputSchema>;\n\n// APPROVE a pending request (Realm steward). Approval assigns the folder — there is no\n// default folder, so `realmFileFolderId` is REQUIRED and the core verifies the folder is\n// under this exact Realm before flipping the file to `nonCanon` + the artisan tier.\nexport const ApproveRealmFilePromotionInputSchema = z.object({\n workRealmId: workRealmIdSchema,\n mediaAssetId: mediaAssetIdSchema,\n realmFileFolderId: realmFileFolderIdSchema,\n requestId: realmFileShareRequestIdSchema,\n}).strict();\nexport type ApproveRealmFilePromotionInput = z.infer<typeof ApproveRealmFilePromotionInputSchema>;\n\n// DECLINE a pending request (Realm steward). Returns the file to `none` and clears the Realm\n// + request fields. No folder is involved — a declined file never entered the pool.\nexport const DeclineRealmFilePromotionInputSchema = z.object({\n workRealmId: workRealmIdSchema,\n mediaAssetId: mediaAssetIdSchema,\n requestId: realmFileShareRequestIdSchema,\n}).strict();\nexport type DeclineRealmFilePromotionInput = z.infer<typeof DeclineRealmFilePromotionInputSchema>;\n\n// ADMIN un-share of an ALREADY-APPROVED realm file (`adminUpdateWorkFileRealmUnshare`).\n// Once a steward approves, sharing is PERMANENT for members — the only way out is an admin\n// acting on a support thread. This is its own input rather than a reuse of the share/request\n// shape: an approved file has NO pending request, so `requestId` is meaningless here and\n// requiring one would make the callable unusable against exactly the state it exists to\n// unwind. It carries the ORIGINAL two-field Work-coordinate shape the share input had before\n// the approval gate; the core resolves the file by collection-group query on\n// (`workProjectId`, `workFileId`). Admin authority is asserted at the callable's admin gate\n// and re-asserted in the core (which rejects any non-`adminOverride` actor) — never inferred\n// from anything in this payload.\nexport const AdminUpdateWorkFileRealmUnshareInputSchema = z.object({\n workProjectId: workProjectIdSchema,\n workFileId: z.string().min(1),\n}).strict();\nexport type AdminUpdateWorkFileRealmUnshareInput = z.infer<typeof AdminUpdateWorkFileRealmUnshareInputSchema>;\n\n// ---- realm shared-file folders (steward-managed) ---------------------------------------\n// Mirrors the Work-side folder CRUD shapes, minus the trade-profession access lists: Realm\n// folders are organizational only (Realm-level visibility is the whole access model at\n// launch). Names reuse the ONE platform folder-name bound; the server derives\n// `name_lowercase` and enforces case-insensitive uniqueness within the Realm.\n\nexport const CreateRealmFileFolderInputSchema = z.object({\n workRealmId: workRealmIdSchema,\n name: z.string().min(1).max(MAX_FILE_FOLDER_NAME_LENGTH),\n}).strict();\nexport type CreateRealmFileFolderInput = z.infer<typeof CreateRealmFileFolderInputSchema>;\n\n/** Rename. `update*` per BACKEND-305 — it modifies an existing doc in place. */\nexport const UpdateRealmFileFolderInputSchema = z.object({\n workRealmId: workRealmIdSchema,\n realmFileFolderId: realmFileFolderIdSchema,\n name: z.string().min(1).max(MAX_FILE_FOLDER_NAME_LENGTH),\n}).strict();\nexport type UpdateRealmFileFolderInput = z.infer<typeof UpdateRealmFileFolderInputSchema>;\n\n/** Delete requires the folder to be EMPTY (the steward moves files out first) — no surprise\n * data moves and no reassignment-target picker at launch. Emptiness is proven by an\n * in-transaction query for ANY asset carrying this folder id, regardless of serving/hidden/\n * canon state: a hidden file still occupies its folder. */\nexport const DeleteRealmFileFolderInputSchema = z.object({\n workRealmId: workRealmIdSchema,\n realmFileFolderId: realmFileFolderIdSchema,\n}).strict();\nexport type DeleteRealmFileFolderInput = z.infer<typeof DeleteRealmFileFolderInputSchema>;\n\n/** Move an approved shared file between folders. `expectedRealmFileFolderId` is a\n * compare-and-set precondition — a steward acting on a stale view must not silently undo a\n * move made from another tab. */\nexport const UpdateRealmFileFolderAssignmentInputSchema = z.object({\n workRealmId: workRealmIdSchema,\n mediaAssetId: mediaAssetIdSchema,\n expectedRealmFileFolderId: realmFileFolderIdSchema,\n realmFileFolderId: realmFileFolderIdSchema,\n}).strict();\nexport type UpdateRealmFileFolderAssignmentInput = z.infer<typeof UpdateRealmFileFolderAssignmentInputSchema>;\n\n\n"]}
1
+ {"version":3,"file":"work-project-management.js","sourceRoot":"","sources":["../../src/schemas/work-project-management.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,mBAAmB,EACnB,YAAY,EACZ,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,EAClB,yBAAyB,EACzB,0BAA0B,EAC1B,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,EAClB,mCAAmC,EACnC,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,EACvB,6BAA6B,GAC9B,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAC5F,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EACL,+BAA+B,EAC/B,6BAA6B,EAC7B,mCAAmC,EACnC,2BAA2B,EAC3B,iCAAiC,EACjC,2BAA2B,EAC3B,2BAA2B,GAC5B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,6BAA6B,EAC7B,qCAAqC,GACtC,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,6BAA6B,EAC7B,oCAAoC,EACpC,2BAA2B,EAC3B,kCAAkC,EAClC,sBAAsB,GACvB,MAAM,gCAAgC,CAAC;AAExC,8EAA8E;AAC9E,2FAA2F;AAC3F,qFAAqF;AACrF,2FAA2F;AAC3F,4FAA4F;AAC5F,4FAA4F;AAC5F,gCAAgC;AAChC,EAAE;AACF,8FAA8F;AAC9F,gFAAgF;AAChF,8EAA8E;AAE9E;mEACmE;AACnE,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,CAAC,MAAM,CAAC;IACtD,YAAY,EAAE,kBAAkB;IAChC,mFAAmF;IACnF,2DAA2D;IAC3D,SAAS,EAAE,sBAAsB;IACjC,0DAA0D;IAC1D,oBAAoB,EAAE,6BAA6B;IACnD;;;8DAG0D;IAC1D,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB;yEACqE;IACrE,iBAAiB,EAAE,uBAAuB;IAC1C,UAAU,EAAE,YAAY;IACxB,2FAA2F;IAC3F,aAAa,EAAE,mBAAmB;IAClC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;CACvB,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ;;qBAEqB;AACrB,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAC,CAAC,MAAM,CAAC;IACtD,iBAAiB,EAAE,uBAAuB;IAC1C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB;;;;mFAI+E;IAC/E,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACnC,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,4FAA4F;AAC5F,2FAA2F;AAC3F,6FAA6F;AAC7F,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC,MAAM,CAAC;IACrD,OAAO,EAAE,iBAAiB;IAC1B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC,QAAQ,EAAE;IAC5E,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CACrC,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ;;;oDAGoD;AACpD,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAAC,CAAC,MAAM,CAAC;IACxD,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,+BAA+B,CAAC;IAC/C,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,+BAA+B,CAAC;IACjD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;CACpD,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,2FAA2F;AAC3F,6FAA6F;AAC7F,wFAAwF;AACxF,iEAAiE;AAEjE;;kCAEkC;AAClC,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,CAAC,MAAM,CAAC;IACvD,YAAY,EAAE,kBAAkB;IAChC,SAAS,EAAE,sBAAsB;IACjC,oBAAoB,EAAE,oCAAoC;IAC1D,uFAAuF;IACvF,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,UAAU,EAAE,YAAY;IACxB,aAAa,EAAE,mBAAmB;IAClC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB;4FACwF;IACxF,uBAAuB,EAAE,6BAA6B;IACtD;qCACiC;IACjC,4BAA4B,EAAE,YAAY;IAC1C,yBAAyB,EAAE,CAAC,CAAC,MAAM,EAAE;CACtC,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,MAAM,CAAC,MAAM,qCAAqC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5D,WAAW,EAAE,iBAAiB;IAC9B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC,QAAQ,EAAE;IACpF,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CACrC,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ;2DAC2D;AAC3D,MAAM,CAAC,MAAM,wCAAwC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/D,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,gCAAgC,CAAC;IACnD,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,+BAA+B,CAAC;IACjD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;CACpD,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,2FAA2F;AAC3F,8FAA8F;AAC9F,4FAA4F;AAC5F,uFAAuF;AACvF,6BAA6B;AAC7B,EAAE;AACF,iFAAiF;AACjF,sFAAsF;AACtF,mFAAmF;AAEnF;;;;;;;;;6EAS6E;AAC7E,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC,MAAM,CAAC;IACpD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,6EAA6E;IAC7E,oBAAoB,EAAE,2BAA2B;IACjD,uBAAuB,EAAE,6BAA6B,CAAC,QAAQ,EAAE;CAClE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;IACnC,MAAM,SAAS,GAAG,GAAG,CAAC,oBAAoB,KAAK,kCAAkC,CAAC;IAClF,IAAI,SAAS,IAAI,GAAG,CAAC,uBAAuB,KAAK,SAAS,EAAE,CAAC;QAC3D,GAAG,CAAC,QAAQ,CAAC;YACX,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,yBAAyB,CAAC;YACjC,OAAO,EAAE,yFAAyF;SACnG,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC,SAAS,IAAI,GAAG,CAAC,uBAAuB,KAAK,SAAS,EAAE,CAAC;QAC5D,GAAG,CAAC,QAAQ,CAAC;YACX,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,yBAAyB,CAAC;YACjC,OAAO,EAAE,+EAA+E;SACzF,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,sCAAsC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7D,aAAa,EAAE,mBAAmB;CACnC,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ;;;mFAGmF;AACnF,MAAM,CAAC,MAAM,yCAAyC,GAAG,CAAC,CAAC,MAAM,CAAC;IAChE,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,6BAA6B,CAAC;CAC/C,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,MAAM,UAAU,GAAG;IACjB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,6BAA6B,CAAC;IAClE,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,mCAAmC,CAAC;IAC9E,eAAe,EAAE,qBAAqB;IACtC,YAAY,EAAE,kBAAkB;CACjC,CAAC;AAEF,oFAAoF;AACpF,sFAAsF;AACtF,qFAAqF;AACrF,kFAAkF;AAClF,qFAAqF;AACrF,oFAAoF;AACpF,oFAAoF;AACpF,sFAAsF;AACtF,wDAAwD;AACxD,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC;KACrC,MAAM,EAAE;KACR,GAAG,CAAC,CAAC,CAAC;KACN,GAAG,CAAC,2BAA2B,CAAC;KAChC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,wCAAwC,EAAE,CAAC;KACtF,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,OAAO,EAAE,mCAAmC,EAAE,CAAC,CAAC;AAE5F,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,IAAI,CAAC;IAC5C,gBAAgB;IAChB,oBAAoB;IACpB,qBAAqB;CACtB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC,kBAAkB,CAAC,mBAAmB,EAAE;IACpF,CAAC,CAAC,MAAM,CAAC;QACP,GAAG,UAAU;QACb,iBAAiB,EAAE,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC;QAC9C,iBAAiB,EAAE,uBAAuB;QAC1C,uBAAuB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,iCAAiC,CAAC;KAClF,CAAC,CAAC,MAAM,EAAE;IACX,uFAAuF;IACvF,kFAAkF;IAClF,uFAAuF;IACvF,6EAA6E;IAC7E,CAAC,CAAC,MAAM,CAAC;QACP,GAAG,UAAU;QACb,iBAAiB,EAAE,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC;KACnD,CAAC,CAAC,MAAM,EAAE;IACX,CAAC,CAAC,MAAM,CAAC;QACP,GAAG,UAAU;QACb,iBAAiB,EAAE,CAAC,CAAC,OAAO,CAAC,qBAAqB,CAAC;QACnD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;KAC/B,CAAC,CAAC,MAAM,EAAE;CACZ,CAAC,CAAC;AAGH,2EAA2E;AAC3E,mFAAmF;AACnF,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IACjD,aAAa,EAAE,mBAAmB;IAClC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC/B,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IAC7D,CAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC;KAC9B,CAAC,CAAC,MAAM,EAAE;IACX,CAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC;QAC7B,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;YACb,YAAY,EAAE,kBAAkB;YAChC,qBAAqB,EAAE,YAAY;YACnC,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,2BAA2B,CAAC;SACnE,CAAC,CAAC,MAAM,EAAE;KACZ,CAAC,CAAC,MAAM,EAAE;IACX,CAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC;QAC7B,oFAAoF;QACpF,wFAAwF;QACxF,wFAAwF;QACxF,8DAA8D;QAC9D,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;YACb,mBAAmB,EAAE,yBAAyB;YAC9C,oBAAoB,EAAE,0BAA0B;YAChD,qBAAqB,EAAE,YAAY;YACnC,yBAAyB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;SACnD,CAAC,CAAC,MAAM,EAAE;KACZ,CAAC,CAAC,MAAM,EAAE;IACX,CAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;QAC3B,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;YACb,UAAU,EAAE,gBAAgB;YAC5B,eAAe,EAAE,qBAAqB;YACtC,gBAAgB,EAAE,YAAY;YAC9B,yBAAyB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;SACnD,CAAC,CAAC,MAAM,EAAE;KACZ,CAAC,CAAC,MAAM,EAAE;CACZ,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC;IACnD,aAAa,EAAE,mBAAmB;IAClC,UAAU,EAAE,YAAY;IACxB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,+BAA+B,CAAC;IAC/D,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3C,MAAM,EAAE,kBAAkB;CAC3B,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,uFAAuF;AACvF,uFAAuF;AACvF,2FAA2F;AAC3F,iFAAiF;AACjF,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,MAAM,CAAC;IAClD,aAAa,EAAE,mBAAmB;IAClC,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;CAC9D,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,MAAM,CAAC,MAAM,0CAA0C,GAAG,CAAC,CAAC,MAAM,CAAC;IACjE,aAAa,EAAE,mBAAmB;IAClC,MAAM,EAAE,YAAY;IACpB,eAAe,EAAE,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC;IAChD,MAAM,EAAE,qBAAqB;CAC9B,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,MAAM,0BAA0B,GAAG,qBAA0G,CAAC;AAE9I,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,CAAC,MAAM,CAAC;IACzD,aAAa,EAAE,mBAAmB;IAClC,MAAM,EAAE,YAAY;IACpB,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC;IACjD,MAAM,EAAE,qBAAqB;CAC9B,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,wFAAwF;AACxF,uFAAuF;AACvF,6EAA6E;AAC7E,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,MAAM,CAAC;IAClD,aAAa,EAAE,mBAAmB;CACnC,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,MAAM,CAAC,MAAM,yCAAyC,GAAG,CAAC,CAAC,MAAM,CAAC;IAChE,aAAa,EAAE,mBAAmB;IAClC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,6BAA6B,CAAC;IAClE,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,mCAAmC,CAAC;CAC/E,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAAC,CAAC,MAAM,CAAC;IACxD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,2BAA2B,CAAC;IAChE,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,iCAAiC,CAAC;CAC7E,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,qFAAqF;AACrF,uFAAuF;AACvF,kGAAkG;AAClG,sFAAsF;AACtF,gEAAgE;AAChE,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,CAAC,MAAM,CAAC;IACzD,YAAY,EAAE,uBAAuB;CACtC,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,0FAA0F;AAC1F,qFAAqF;AACrF,2FAA2F;AAE3F,MAAM,yBAAyB,GAAG,CAAC;KAChC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;KACtC,GAAG,CAAC,wBAAwB,CAAC,MAAM,CAAC,CAAC;AAExC,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,MAAM,CAAC;IAClD,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAChC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,2BAA2B,CAAC;IACxD,uBAAuB,EAAE,yBAAyB;IAClD,yBAAyB,EAAE,yBAAyB;IACpD,yBAAyB,EAAE,yBAAyB;CACrD,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,MAAM,CAAC;IAClD,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAChC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,2BAA2B,CAAC;CACzD,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,CAAC,MAAM,CAAC;IACzD,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAChC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,uBAAuB,EAAE,yBAAyB;IAClD,yBAAyB,EAAE,yBAAyB;IACpD,yBAAyB,EAAE,yBAAyB;CACrD,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,MAAM,CAAC;IAClD,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAChC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC5B,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,0FAA0F;AAE1F,uFAAuF;AACvF,6BAA6B;AAC7B,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChD,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAChC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC9B,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,2FAA2F;AAC3F,sEAAsE;AACtE,MAAM,CAAC,MAAM,mCAAmC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1D,WAAW,EAAE,iBAAiB;IAC9B,YAAY,EAAE,kBAAkB;IAChC,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE;CACnB,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,2FAA2F;AAC3F,wFAAwF;AACxF,2FAA2F;AAC3F,kFAAkF;AAClF,EAAE;AACF,6FAA6F;AAC7F,0FAA0F;AAC1F,wFAAwF;AAExF,uFAAuF;AACvF,yEAAyE;AACzE,6FAA6F;AAC7F,2FAA2F;AAC3F,uEAAuE;AACvE,MAAM,CAAC,MAAM,mCAAmC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1D,aAAa,EAAE,mBAAmB;IAClC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,SAAS,EAAE,6BAA6B;CACzC,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,mFAAmF;AACnF,0FAA0F;AAC1F,uFAAuF;AACvF,wFAAwF;AACxF,MAAM,CAAC,MAAM,4CAA4C,GAAG,CAAC,CAAC,MAAM,CAAC;IACnE,aAAa,EAAE,mBAAmB;IAClC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,SAAS,EAAE,6BAA6B;CACzC,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,uFAAuF;AACvF,yFAAyF;AACzF,oFAAoF;AACpF,MAAM,CAAC,MAAM,oCAAoC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3D,WAAW,EAAE,iBAAiB;IAC9B,YAAY,EAAE,kBAAkB;IAChC,iBAAiB,EAAE,uBAAuB;IAC1C,SAAS,EAAE,6BAA6B;CACzC,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,6FAA6F;AAC7F,oFAAoF;AACpF,MAAM,CAAC,MAAM,oCAAoC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3D,WAAW,EAAE,iBAAiB;IAC9B,YAAY,EAAE,kBAAkB;IAChC,SAAS,EAAE,6BAA6B;CACzC,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,wFAAwF;AACxF,2FAA2F;AAC3F,6FAA6F;AAC7F,yFAAyF;AACzF,wFAAwF;AACxF,6FAA6F;AAC7F,6EAA6E;AAC7E,4FAA4F;AAC5F,6FAA6F;AAC7F,iCAAiC;AACjC,MAAM,CAAC,MAAM,0CAA0C,GAAG,CAAC,CAAC,MAAM,CAAC;IACjE,aAAa,EAAE,mBAAmB;IAClC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC9B,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,2FAA2F;AAC3F,2FAA2F;AAC3F,uFAAuF;AACvF,8EAA8E;AAC9E,8EAA8E;AAE9E,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,CAAC,MAAM,CAAC;IACvD,WAAW,EAAE,iBAAiB;IAC9B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,2BAA2B,CAAC;CACzD,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,gFAAgF;AAChF,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,CAAC,MAAM,CAAC;IACvD,WAAW,EAAE,iBAAiB;IAC9B,iBAAiB,EAAE,uBAAuB;IAC1C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,2BAA2B,CAAC;CACzD,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ;;;4DAG4D;AAC5D,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAAC,CAAC,MAAM,CAAC;IACvD,WAAW,EAAE,iBAAiB;IAC9B,iBAAiB,EAAE,uBAAuB;CAC3C,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ;;kCAEkC;AAClC,MAAM,CAAC,MAAM,0CAA0C,GAAG,CAAC,CAAC,MAAM,CAAC;IACjE,WAAW,EAAE,iBAAiB;IAC9B,YAAY,EAAE,kBAAkB;IAChC,yBAAyB,EAAE,uBAAuB;IAClD,iBAAiB,EAAE,uBAAuB;CAC3C,CAAC,CAAC,MAAM,EAAE,CAAC","sourcesContent":["import { z } from 'zod';\nimport {\n workProjectIdSchema,\n userIdSchema,\n addRemoveActionSchema,\n workProjectTypeSchema,\n hallWingTypeSchema,\n commissionListingIdSchema,\n commissionProposalIdSchema,\n auditionIdSchema,\n auditionEntryIdSchema,\n craftSkillIdSchema,\n guildInviteConversationStatusSchema,\n mediaAssetIdSchema,\n workRealmIdSchema,\n realmFileFolderIdSchema,\n realmFileShareRequestIdSchema,\n} from './atoms.js';\nimport { TRADE_PROFESSION_OPTIONS, TRADE_PROFESSION_VALUES } from '../constants/options.js';\nimport { GUILD_STANDING_VALUES } from '../permissions/index.js';\nimport {\n MAX_GUILD_INVITE_MESSAGE_LENGTH,\n MAX_WORK_PROJECT_TITLE_LENGTH,\n MAX_WORK_PROJECT_DESCRIPTION_LENGTH,\n MAX_WORK_REALM_TITLE_LENGTH,\n MAX_WORK_REALM_DESCRIPTION_LENGTH,\n MAX_CRAFT_SKILL_NAME_LENGTH,\n MAX_FILE_FOLDER_NAME_LENGTH,\n} from '../constants/business.js';\nimport {\n REALM_SHARED_FILES_PAGE_LIMIT,\n REALM_FILE_PROMOTION_QUEUE_PAGE_LIMIT,\n} from '../constants/pagination.js';\nimport {\n RealmFileApprovedStatusSchema,\n RealmFilePendingApprovalStatusSchema,\n RealmFileActiveStatusSchema,\n REALM_FILE_PENDING_APPROVAL_STATUS,\n ContentMediaKindSchema,\n} from '../doc-schemas/media-assets.js';\n\n// ===========================================================================\n// S7 realm shared-files gallery (ARTISAN-ONLY, plus a full-admin bypass for the admin-only\n// un-share support action). `mediaAssets` is client-unreadable, so the gallery reads\n// realm-shared work files via THIS server projection callable (never a client query) — and\n// for the same reason the Realm's FOLDER documents are returned through the same projection\n// owner rather than opened to direct client reads: artisan / admin / hidden-Realm access is\n// decided in ONE backend owner.\n//\n// Serving is the `'artisan'` media tier (mutate-in-place scoped→artisan at APPROVAL — see the\n// approval gate below). V1 = view + download, grouped by the steward's folders.\n// ===========================================================================\n\n/** One APPROVED shared file. Accepts only the two approved standings — a pending or\n * unshared row is structurally inexpressible in this response. */\nexport const RealmSharedFileProjectionSchema = z.object({\n mediaAssetId: mediaAssetIdSchema,\n // The canonical stored media kind — RealmSharedFileProjection is a projection OF a\n // MediaAsset, so it shares the ONE ContentMediaKindSchema.\n mediaKind: ContentMediaKindSchema,\n // Never the full status union: 'nonCanon' | 'canon' only.\n realmFileCanonStatus: RealmFileApprovedStatusSchema,\n /** The Work file's own `name`. A file browser that groups unnamed thumbnails by folder is\n * not a file browser — the name is part of the projection, not something the client is\n * expected to resolve. (It is file metadata, NOT display identity: creator names and\n * avatars still resolve at render from `creatorUid`.) */\n name: z.string(),\n /** The steward-assigned folder this file sits in. Always present — approval IS folder\n * assignment, so an approved file without a folder cannot exist. */\n realmFileFolderId: realmFileFolderIdSchema,\n creatorUid: userIdSchema,\n // For the per-file steward canon toggle + download (updateWorkFileRealmCanon takes these).\n workProjectId: workProjectIdSchema,\n workFileId: z.string(),\n}).strict();\nexport type RealmSharedFileProjection = z.infer<typeof RealmSharedFileProjectionSchema>;\n\n/** A Realm shared-file folder as the gallery sees it. The FOLDER DOCUMENT stores no counts;\n * `fileCount` here is SERVER-COMPUTED per response, so it can never drift the way a stored\n * counter would. */\nexport const RealmFileFolderProjectionSchema = z.object({\n realmFileFolderId: realmFileFolderIdSchema,\n name: z.string(),\n /** Number of files currently ASSIGNED to this folder — counting every assigned file\n * regardless of canon state and regardless of serving state (a hidden or quarantined file\n * still occupies its folder, and is still why a delete-folder attempt will refuse).\n * Server-computed so the steward UI stops deriving counts from whichever gallery pages\n * happen to be loaded — a paged client can only ever see part of a folder. */\n fileCount: z.number().int().min(0),\n}).strict();\nexport type RealmFileFolderProjection = z.infer<typeof RealmFileFolderProjectionSchema>;\n\n// Paginated: the pre-approval-gate query was unbounded. `limit` is bounded by the ONE named\n// page constant the server also clamps to, and `cursor` is an OPAQUE server-minted token —\n// the client never constructs or interprets it, so the ordering fields stay a server detail.\nexport const GetRealmSharedFilesInputSchema = z.object({\n realmId: workRealmIdSchema,\n limit: z.number().int().min(1).max(REALM_SHARED_FILES_PAGE_LIMIT).optional(),\n cursor: z.string().min(1).optional(),\n}).strict();\nexport type GetRealmSharedFilesInput = z.infer<typeof GetRealmSharedFilesInputSchema>;\n\n/** `{ files }` is preserved as-is; `folders` and `nextCursor` are ADDITIVE. `folders` is the\n * Realm's complete folder set (bounded by MAX_REALM_FILE_FOLDERS), not a page — the gallery\n * must be able to render an empty folder, and the steward must see one to move files into.\n * `nextCursor` is absent/null on the last page. */\nexport const GetRealmSharedFilesResponseSchema = z.object({\n files: z.array(RealmSharedFileProjectionSchema),\n folders: z.array(RealmFileFolderProjectionSchema),\n nextCursor: z.string().min(1).nullable().optional(),\n}).strict();\nexport type GetRealmSharedFilesResponse = z.infer<typeof GetRealmSharedFilesResponseSchema>;\n\n// ---- realm-file promotion queue (steward / full admin) ---------------------------------\n// A SEPARATE bounded projection rather than an `includePending` flag on the artisan gallery:\n// a caller-controlled flag would put \"may this caller see pending rows\" in the client's\n// hands. Ordinary artisans can never enumerate pending requests.\n\n/** One AWAITING-DECISION request. Accepts only the pending-approval standing (via\n * RealmFilePendingApprovalStatusSchema) — an approved or unshared row is structurally\n * inexpressible in the queue. */\nexport const RealmFilePromotionQueueRowSchema = z.object({\n mediaAssetId: mediaAssetIdSchema,\n mediaKind: ContentMediaKindSchema,\n realmFileCanonStatus: RealmFilePendingApprovalStatusSchema,\n /** The Work file's own name — the steward decides on a named file, not a thumbnail. */\n name: z.string(),\n creatorUid: userIdSchema,\n workProjectId: workProjectIdSchema,\n workFileId: z.string(),\n /** Echoed so the approve/decline call can carry the exact observed request id; a stale tab\n * deciding a superseded request is then a visible conflict, not a silent overwrite. */\n realmFileShareRequestId: realmFileShareRequestIdSchema,\n /** The RECORDED requester — the resolution notification is addressed from this, never\n * guessed from the uploader. */\n realmFileShareRequestedByUid: userIdSchema,\n realmFileShareRequestedAt: z.number(),\n}).strict();\nexport type RealmFilePromotionQueueRow = z.infer<typeof RealmFilePromotionQueueRowSchema>;\n\nexport const GetRealmFilePromotionQueueInputSchema = z.object({\n workRealmId: workRealmIdSchema,\n limit: z.number().int().min(1).max(REALM_FILE_PROMOTION_QUEUE_PAGE_LIMIT).optional(),\n cursor: z.string().min(1).optional(),\n}).strict();\nexport type GetRealmFilePromotionQueueInput = z.infer<typeof GetRealmFilePromotionQueueInputSchema>;\n\n/** `folders` rides along so the approval UI can offer the folder picker (and detect the\n * \"no folders yet\" state) without a second round-trip. */\nexport const GetRealmFilePromotionQueueResponseSchema = z.object({\n requests: z.array(RealmFilePromotionQueueRowSchema),\n folders: z.array(RealmFileFolderProjectionSchema),\n nextCursor: z.string().min(1).nullable().optional(),\n}).strict();\nexport type GetRealmFilePromotionQueueResponse = z.infer<typeof GetRealmFilePromotionQueueResponseSchema>;\n\n// ---- WORK-side share-state projection --------------------------------------------------\n// The mirror image of the two Realm-side projections above, for the WORK's own files surface:\n// a file admin looking at their folder listing needs to know which files are already shared\n// or awaiting a steward decision, so the row can show \"Requested\" / \"Shared\" and offer\n// withdraw where it applies.\n//\n// It is a SERVER projection for the same reason the gallery is: `mediaAssets` is\n// client-unreadable, so share state cannot be read from the file document. File-admin\n// authorization is asserted in the callable; this shape carries no authority hint.\n\n/** One work file's realm-share state.\n *\n * The `requestId` is present EXACTLY while the file is awaiting a decision — it is what the\n * withdraw call must carry, and it is meaningless once the request is resolved. Enforced\n * rather than merely optional, mirroring the asset's own legal-combination invariant, so the\n * UI can never be handed a pending row with nothing to withdraw (or an approved row carrying\n * a stale request id it might send).\n *\n * `workFileId` uses plain `z.string()` like the sibling projection rows in this file\n * (inputs use `.min(1)`; projection rows describe server-produced data). */\nexport const WorkFileRealmShareStateSchema = z.object({\n workFileId: z.string(),\n // Never `none`: an unshared file simply has no row (see the response below).\n realmFileCanonStatus: RealmFileActiveStatusSchema,\n realmFileShareRequestId: realmFileShareRequestIdSchema.optional(),\n}).strict().superRefine((val, ctx) => {\n const isPending = val.realmFileCanonStatus === REALM_FILE_PENDING_APPROVAL_STATUS;\n if (isPending && val.realmFileShareRequestId === undefined) {\n ctx.addIssue({\n code: 'custom',\n path: ['realmFileShareRequestId'],\n message: 'a pending row must carry its request id — it is what the withdraw call compares against',\n });\n }\n if (!isPending && val.realmFileShareRequestId !== undefined) {\n ctx.addIssue({\n code: 'custom',\n path: ['realmFileShareRequestId'],\n message: 'a resolved row must not carry a request id — the request is no longer pending',\n });\n }\n});\nexport type WorkFileRealmShareState = z.infer<typeof WorkFileRealmShareStateSchema>;\n\nexport const GetWorkFileRealmShareStatesInputSchema = z.object({\n workProjectId: workProjectIdSchema,\n}).strict();\nexport type GetWorkFileRealmShareStatesInput = z.infer<typeof GetWorkFileRealmShareStatesInputSchema>;\n\n/** Rows exist ONLY for files whose standing is not `none`. An ABSENT row therefore means the\n * file has never been requested or shared — that is the encoding, so the client must treat a\n * missing entry as \"not shared\" rather than \"unknown\". Bounded implicitly by the Work's own\n * file cap (MAX_WORK_FILES), so this response needs no page cursor of its own. */\nexport const GetWorkFileRealmShareStatesResponseSchema = z.object({\n states: z.array(WorkFileRealmShareStateSchema),\n}).strict();\nexport type GetWorkFileRealmShareStatesResponse = z.infer<typeof GetWorkFileRealmShareStatesResponseSchema>;\n\nconst baseFields = {\n workingTitle: z.string().min(1).max(MAX_WORK_PROJECT_TITLE_LENGTH),\n workingDescription: z.string().min(1).max(MAX_WORK_PROJECT_DESCRIPTION_LENGTH),\n workProjectType: workProjectTypeSchema,\n hallWingType: hallWingTypeSchema,\n};\n\n// A Realm working title is reserved under `reservedRealmNames/{UPPER(title)}` — the\n// UPPERCASED title IS the Firestore doc ID (runCreateWorkRealm.reservedRealmNameRef).\n// Firestore doc IDs cannot contain `/` and cannot be exactly `.` or `..`, so a title\n// that would produce an invalid/ambiguous doc ID must be rejected at the callable\n// boundary (both the create transaction and the soft availability check) rather than\n// hard-failing with an opaque `internal` error deep inside ref construction. Length\n// derives from MAX_WORK_REALM_TITLE_LENGTH; only the doc-ID-breaking characters are\n// forbidden. Keep CheckRealmNameAvailableInputSchema in lockstep so a valid-at-create\n// name is never rejected at form time (and vice-versa).\nexport const realmWorkingTitleSchema = z\n .string()\n .min(1)\n .max(MAX_WORK_REALM_TITLE_LENGTH)\n .refine((v) => !v.includes('/'), { message: 'Realm name cannot contain a slash (/).' })\n .refine((v) => v !== '.' && v !== '..', { message: 'Realm name cannot be \".\" or \"..\".' });\n\nexport const RealmCreationModeSchema = z.enum([\n 'newPublicRealm',\n 'newStandaloneRealm',\n 'existingPublicRealm',\n]);\nexport type RealmCreationMode = z.infer<typeof RealmCreationModeSchema>;\n\nexport const CreateWorkProjectInputSchema = z.discriminatedUnion('realmCreationMode', [\n z.object({\n ...baseFields,\n realmCreationMode: z.literal('newPublicRealm'),\n realmWorkingTitle: realmWorkingTitleSchema,\n realmWorkingDescription: z.string().min(1).max(MAX_WORK_REALM_DESCRIPTION_LENGTH),\n }).strict(),\n // Standalone realms are background plumbing (DJ ruling 2026-07-19): the user enters NO\n // realm information — the backend creates the realm shell with a synthetic unique\n // title/description (the generated workRealmId), so nothing user-authored exists on it\n // and no human realm name is consumed from the reservedRealmNames namespace.\n z.object({\n ...baseFields,\n realmCreationMode: z.literal('newStandaloneRealm'),\n }).strict(),\n z.object({\n ...baseFields,\n realmCreationMode: z.literal('existingPublicRealm'),\n workRealmId: z.string().min(1),\n }).strict(),\n]);\nexport type CreateWorkProjectInput = z.infer<typeof CreateWorkProjectInputSchema>;\n\n// Identified by the workAssets subcollection doc id — never by URL parsing\n// (no delete path may depend on a URL; see media-assets-and-protected-serving.md).\nexport const DeleteWorkAssetInputSchema = z.object({\n workProjectId: workProjectIdSchema,\n workAssetId: z.string().min(1),\n}).strict();\nexport type DeleteWorkAssetInput = z.infer<typeof DeleteWorkAssetInputSchema>;\n\nexport const InviteSourceSchema = z.discriminatedUnion('type', [\n z.object({\n type: z.literal('standalone'),\n }).strict(),\n z.object({\n type: z.literal('craftSkill'),\n data: z.object({\n craftSkillId: craftSkillIdSchema,\n craftSkillOwnerUserId: userIdSchema,\n craftSkillName: z.string().min(1).max(MAX_CRAFT_SKILL_NAME_LENGTH),\n }).strict(),\n }).strict(),\n z.object({\n type: z.literal('commission'),\n // Titles are NOT snapshotted here (Display Identity Invariant — client display text\n // must be re-sourced at render by id). `postingStakeSharesOffered` is not display text;\n // the server re-sources it from the posting doc in the invite transaction (never trusts\n // the client copy) — kept so the shape stays server-writable.\n data: z.object({\n commissionListingId: commissionListingIdSchema,\n commissionProposalId: commissionProposalIdSchema,\n proposalArtisanUserId: userIdSchema,\n postingStakeSharesOffered: z.number().int().min(1),\n }).strict(),\n }).strict(),\n z.object({\n type: z.literal('audition'),\n data: z.object({\n auditionId: auditionIdSchema,\n auditionEntryId: auditionEntryIdSchema,\n respondentUserId: userIdSchema,\n postingStakeSharesOffered: z.number().int().min(1),\n }).strict(),\n }).strict(),\n]);\nexport type InviteSource = z.infer<typeof InviteSourceSchema>;\nexport type InviteSourceType = InviteSource['type'];\n\nexport const InviteUserToGuildInputSchema = z.object({\n workProjectId: workProjectIdSchema,\n inviteeUid: userIdSchema,\n message: z.string().min(1).max(MAX_GUILD_INVITE_MESSAGE_LENGTH),\n stakeSharesOffered: z.number().int().min(1),\n source: InviteSourceSchema,\n}).strict();\nexport type InviteUserToGuildInput = z.infer<typeof InviteUserToGuildInputSchema>;\n\n// `finalized` is the terminal SUCCESS state (`accepted` is a transient state a trigger\n// consumes within seconds). Managers must be able to list finalized invites to see the\n// guild's actual recruitment history — not only failures and in-flight items. Derives from\n// the ONE canonical status enum (schemas/atoms.ts), never a re-declared literal.\nexport const ListGuildInvitesInputSchema = z.object({\n workProjectId: workProjectIdSchema,\n statuses: z.array(guildInviteConversationStatusSchema).min(1),\n}).strict();\nexport type ListGuildInvitesInput = z.infer<typeof ListGuildInvitesInputSchema>;\n\nexport const UpdateGuildmateTradeProfessionsInputSchema = z.object({\n workProjectId: workProjectIdSchema,\n userId: userIdSchema,\n tradeProfession: z.enum(TRADE_PROFESSION_VALUES),\n action: addRemoveActionSchema,\n}).strict();\nexport type UpdateGuildmateTradeProfessionsInput = z.infer<typeof UpdateGuildmateTradeProfessionsInputSchema>;\n\nconst GUILD_STANDING_VALUES_ENUM = GUILD_STANDING_VALUES as [typeof GUILD_STANDING_VALUES[number], ...typeof GUILD_STANDING_VALUES[number][]];\n\nexport const UpdateGuildmateStandingInputSchema = z.object({\n workProjectId: workProjectIdSchema,\n userId: userIdSchema,\n guildStanding: z.enum(GUILD_STANDING_VALUES_ENUM),\n action: addRemoveActionSchema,\n}).strict();\nexport type UpdateGuildmateStandingInput = z.infer<typeof UpdateGuildmateStandingInputSchema>;\n\n// Member self-leave (leaveWorkProject). The leaver is ALWAYS request.auth.uid — never a\n// client-supplied uid (invariant 3) — so the input carries only the workProjectId. The\n// callable composes the internal `depart` stake-share operation for ctx.uid.\nexport const LeaveWorkProjectInputSchema = z.object({\n workProjectId: workProjectIdSchema,\n}).strict();\nexport type LeaveWorkProjectInput = z.infer<typeof LeaveWorkProjectInputSchema>;\n\nexport const UpdatePublicWorkProjectDetailsInputSchema = z.object({\n workProjectId: workProjectIdSchema,\n workingTitle: z.string().min(1).max(MAX_WORK_PROJECT_TITLE_LENGTH),\n workingDescription: z.string().min(1).max(MAX_WORK_PROJECT_DESCRIPTION_LENGTH),\n}).strict();\nexport type UpdatePublicWorkProjectDetailsInput = z.infer<typeof UpdatePublicWorkProjectDetailsInputSchema>;\n\nexport const UpdateWorkRealmDetailsInputSchema = z.object({\n workRealmId: z.string().min(1),\n workingTitle: z.string().min(1).max(MAX_WORK_REALM_TITLE_LENGTH),\n workingDescription: z.string().min(1).max(MAX_WORK_REALM_DESCRIPTION_LENGTH),\n}).strict();\nexport type UpdateWorkRealmDetailsInput = z.infer<typeof UpdateWorkRealmDetailsInputSchema>;\n\n// Unauthenticated soft-check for a Realm working title. Must match the authoritative\n// realmWorkingTitle contract in CreateWorkProjectInputSchema (realmWorkingTitleSchema:\n// MAX_WORK_REALM_TITLE_LENGTH, rejecting the doc-ID-breaking `/` and reserved `.`/`..`). Never be\n// stricter than the create transaction or a valid-at-create name would be rejected at\n// form time — reuse the SAME schema so the two can never drift.\nexport const CheckRealmNameAvailableInputSchema = z.object({\n workingTitle: realmWorkingTitleSchema,\n}).strict();\nexport type CheckRealmNameAvailableInput = z.infer<typeof CheckRealmNameAvailableInputSchema>;\n\n// ---- work-project file folders (S7) ---------------------------------------------------\n// The default \"All Guildmates\" folder is immutable; custom-folder access is by trade\n// profession. All four callables require a file-admin standing via assertCanManageFolders.\n\nconst tradeProfessionListSchema = z\n .array(z.enum(TRADE_PROFESSION_VALUES))\n .max(TRADE_PROFESSION_OPTIONS.length);\n\nexport const CreateFileFolderInputSchema = z.object({\n workProjectId: z.string().min(1),\n name: z.string().min(1).max(MAX_FILE_FOLDER_NAME_LENGTH),\n canViewTradeProfessions: tradeProfessionListSchema,\n canUploadTradeProfessions: tradeProfessionListSchema,\n canDeleteTradeProfessions: tradeProfessionListSchema,\n}).strict();\nexport type CreateFileFolderInput = z.infer<typeof CreateFileFolderInputSchema>;\n\nexport const RenameFileFolderInputSchema = z.object({\n workProjectId: z.string().min(1),\n folderId: z.string().min(1),\n name: z.string().min(1).max(MAX_FILE_FOLDER_NAME_LENGTH),\n}).strict();\nexport type RenameFileFolderInput = z.infer<typeof RenameFileFolderInputSchema>;\n\nexport const UpdateFolderProfessionsInputSchema = z.object({\n workProjectId: z.string().min(1),\n folderId: z.string().min(1),\n canViewTradeProfessions: tradeProfessionListSchema,\n canUploadTradeProfessions: tradeProfessionListSchema,\n canDeleteTradeProfessions: tradeProfessionListSchema,\n}).strict();\nexport type UpdateFolderProfessionsInput = z.infer<typeof UpdateFolderProfessionsInputSchema>;\n\nexport const DeleteFileFolderInputSchema = z.object({\n workProjectId: z.string().min(1),\n folderId: z.string().min(1),\n}).strict();\nexport type DeleteFileFolderInput = z.infer<typeof DeleteFileFolderInputSchema>;\n\n// ---- realm shared files ---------------------------------------------------------------\n\n// Delete a single work file (by folder + file id). File-admin authz is enforced in the\n// callable/core transaction.\nexport const DeleteWorkFileInputSchema = z.object({\n workProjectId: z.string().min(1),\n folderId: z.string().min(1),\n workFileId: z.string().min(1),\n}).strict();\nexport type DeleteWorkFileInput = z.infer<typeof DeleteWorkFileInputSchema>;\n\n// Set canon status on a realm shared file. Realm-steward-only authz is enforced inside the\n// core's transaction against workRealms/{workRealmId}.workStewardUid.\nexport const UpdateWorkFileRealmCanonInputSchema = z.object({\n workRealmId: workRealmIdSchema,\n mediaAssetId: mediaAssetIdSchema,\n canon: z.boolean(),\n}).strict();\nexport type UpdateWorkFileRealmCanonInput = z.infer<typeof UpdateWorkFileRealmCanonInputSchema>;\n\n// ---- the promotion approval gate -------------------------------------------------------\n// Promotion is a REQUEST, not an instant share: the Work file admin asks, and the REALM\n// steward approves (choosing the folder) or declines. Nothing is served to the Realm until\n// approval — a requested file stays `scoped` and invisible to the member gallery.\n//\n// Every one of these carries the `requestId` so a decision always names the exact request it\n// observed. Realm-side authority (steward, public + non-hidden Realm) is derived from the\n// Realm document inside each core's transaction; these shapes carry no authority hints.\n\n// REQUEST promotion of a work file into its Realm's shared-file pool. File-admin authz\n// (`workFile.promoteToRealm`) is enforced inside the core's transaction.\n// `requestId` is CLIENT-generated and stable: replaying the same id is an idempotent success\n// (no second audit event, no second notification), while a DIFFERENT id arriving while one\n// request is already pending is a conflict — never a silent overwrite.\nexport const UpdateWorkFileRealmShareInputSchema = z.object({\n workProjectId: workProjectIdSchema,\n workFileId: z.string().min(1),\n requestId: realmFileShareRequestIdSchema,\n}).strict();\nexport type UpdateWorkFileRealmShareInput = z.infer<typeof UpdateWorkFileRealmShareInputSchema>;\n\n// WITHDRAW a still-pending request (the requesting Work's file admin). Realm-share\n// permanence begins at APPROVAL — before a steward decides, an accidental request must be\n// correctable by the side that made it. Addressed by Work coordinates like the request\n// itself, and compares `requestId` so a withdrawal can never cancel a newer re-request.\nexport const WithdrawRealmFilePromotionRequestInputSchema = z.object({\n workProjectId: workProjectIdSchema,\n workFileId: z.string().min(1),\n requestId: realmFileShareRequestIdSchema,\n}).strict();\nexport type WithdrawRealmFilePromotionRequestInput = z.infer<typeof WithdrawRealmFilePromotionRequestInputSchema>;\n\n// APPROVE a pending request (Realm steward). Approval assigns the folder — there is no\n// default folder, so `realmFileFolderId` is REQUIRED and the core verifies the folder is\n// under this exact Realm before flipping the file to `nonCanon` + the artisan tier.\nexport const ApproveRealmFilePromotionInputSchema = z.object({\n workRealmId: workRealmIdSchema,\n mediaAssetId: mediaAssetIdSchema,\n realmFileFolderId: realmFileFolderIdSchema,\n requestId: realmFileShareRequestIdSchema,\n}).strict();\nexport type ApproveRealmFilePromotionInput = z.infer<typeof ApproveRealmFilePromotionInputSchema>;\n\n// DECLINE a pending request (Realm steward). Returns the file to `none` and clears the Realm\n// + request fields. No folder is involved — a declined file never entered the pool.\nexport const DeclineRealmFilePromotionInputSchema = z.object({\n workRealmId: workRealmIdSchema,\n mediaAssetId: mediaAssetIdSchema,\n requestId: realmFileShareRequestIdSchema,\n}).strict();\nexport type DeclineRealmFilePromotionInput = z.infer<typeof DeclineRealmFilePromotionInputSchema>;\n\n// ADMIN un-share of an ALREADY-APPROVED realm file (`adminUpdateWorkFileRealmUnshare`).\n// Once a steward approves, sharing is PERMANENT for members — the only way out is an admin\n// acting on a support thread. This is its own input rather than a reuse of the share/request\n// shape: an approved file has NO pending request, so `requestId` is meaningless here and\n// requiring one would make the callable unusable against exactly the state it exists to\n// unwind. It carries the ORIGINAL two-field Work-coordinate shape the share input had before\n// the approval gate; the core resolves the file by collection-group query on\n// (`workProjectId`, `workFileId`). Admin authority is asserted at the callable's admin gate\n// and re-asserted in the core (which rejects any non-`adminOverride` actor) — never inferred\n// from anything in this payload.\nexport const AdminUpdateWorkFileRealmUnshareInputSchema = z.object({\n workProjectId: workProjectIdSchema,\n workFileId: z.string().min(1),\n}).strict();\nexport type AdminUpdateWorkFileRealmUnshareInput = z.infer<typeof AdminUpdateWorkFileRealmUnshareInputSchema>;\n\n// ---- realm shared-file folders (steward-managed) ---------------------------------------\n// Mirrors the Work-side folder CRUD shapes, minus the trade-profession access lists: Realm\n// folders are organizational only (Realm-level visibility is the whole access model at\n// launch). Names reuse the ONE platform folder-name bound; the server derives\n// `name_lowercase` and enforces case-insensitive uniqueness within the Realm.\n\nexport const CreateRealmFileFolderInputSchema = z.object({\n workRealmId: workRealmIdSchema,\n name: z.string().min(1).max(MAX_FILE_FOLDER_NAME_LENGTH),\n}).strict();\nexport type CreateRealmFileFolderInput = z.infer<typeof CreateRealmFileFolderInputSchema>;\n\n/** Rename. `update*` per BACKEND-305 — it modifies an existing doc in place. */\nexport const UpdateRealmFileFolderInputSchema = z.object({\n workRealmId: workRealmIdSchema,\n realmFileFolderId: realmFileFolderIdSchema,\n name: z.string().min(1).max(MAX_FILE_FOLDER_NAME_LENGTH),\n}).strict();\nexport type UpdateRealmFileFolderInput = z.infer<typeof UpdateRealmFileFolderInputSchema>;\n\n/** Delete requires the folder to be EMPTY (the steward moves files out first) — no surprise\n * data moves and no reassignment-target picker at launch. Emptiness is proven by an\n * in-transaction query for ANY asset carrying this folder id, regardless of serving/hidden/\n * canon state: a hidden file still occupies its folder. */\nexport const DeleteRealmFileFolderInputSchema = z.object({\n workRealmId: workRealmIdSchema,\n realmFileFolderId: realmFileFolderIdSchema,\n}).strict();\nexport type DeleteRealmFileFolderInput = z.infer<typeof DeleteRealmFileFolderInputSchema>;\n\n/** Move an approved shared file between folders. `expectedRealmFileFolderId` is a\n * compare-and-set precondition — a steward acting on a stale view must not silently undo a\n * move made from another tab. */\nexport const UpdateRealmFileFolderAssignmentInputSchema = z.object({\n workRealmId: workRealmIdSchema,\n mediaAssetId: mediaAssetIdSchema,\n expectedRealmFileFolderId: realmFileFolderIdSchema,\n realmFileFolderId: realmFileFolderIdSchema,\n}).strict();\nexport type UpdateRealmFileFolderAssignmentInput = z.infer<typeof UpdateRealmFileFolderAssignmentInputSchema>;\n\n\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttt-productions/ttt-core",
3
- "version": "0.79.20",
3
+ "version": "0.79.21",
4
4
  "description": "Core types, Firestore path constants, and shared constants for TTT Productions",
5
5
  "repository": {
6
6
  "type": "git",