@ttt-productions/ttt-core 0.78.22 → 0.78.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/dist/constants/business-user.d.ts +1 -1
  2. package/dist/constants/business-user.js +1 -1
  3. package/dist/constants/business-user.js.map +1 -1
  4. package/dist/constants/release-flags.d.ts +2 -2
  5. package/dist/constants/release-flags.d.ts.map +1 -1
  6. package/dist/constants/release-flags.js +2 -2
  7. package/dist/constants/release-flags.js.map +1 -1
  8. package/dist/doc-schemas/chat-sync.d.ts.map +1 -1
  9. package/dist/doc-schemas/chat-sync.js +3 -2
  10. package/dist/doc-schemas/chat-sync.js.map +1 -1
  11. package/dist/doc-schemas/commissions.d.ts +14 -11
  12. package/dist/doc-schemas/commissions.d.ts.map +1 -1
  13. package/dist/doc-schemas/commissions.js +14 -4
  14. package/dist/doc-schemas/commissions.js.map +1 -1
  15. package/dist/doc-schemas/media-activation-jobs.d.ts.map +1 -1
  16. package/dist/doc-schemas/media-activation-jobs.js +4 -3
  17. package/dist/doc-schemas/media-activation-jobs.js.map +1 -1
  18. package/dist/doc-schemas/media-assets.d.ts +2 -2
  19. package/dist/doc-schemas/media-assets.d.ts.map +1 -1
  20. package/dist/doc-schemas/media-assets.js +5 -4
  21. package/dist/doc-schemas/media-assets.js.map +1 -1
  22. package/dist/doc-schemas/messaging.d.ts.map +1 -1
  23. package/dist/doc-schemas/messaging.js +3 -2
  24. package/dist/doc-schemas/messaging.js.map +1 -1
  25. package/dist/doc-schemas/ncii/allegations.js +3 -3
  26. package/dist/doc-schemas/ncii/allegations.js.map +1 -1
  27. package/dist/doc-schemas/ncii/cases.d.ts.map +1 -1
  28. package/dist/doc-schemas/ncii/cases.js +4 -3
  29. package/dist/doc-schemas/ncii/cases.js.map +1 -1
  30. package/dist/doc-schemas/ncii/config.d.ts.map +1 -1
  31. package/dist/doc-schemas/ncii/config.js +4 -3
  32. package/dist/doc-schemas/ncii/config.js.map +1 -1
  33. package/dist/doc-schemas/ncii/holds.js +3 -3
  34. package/dist/doc-schemas/ncii/holds.js.map +1 -1
  35. package/dist/doc-schemas/ncii/removal.js +3 -3
  36. package/dist/doc-schemas/ncii/removal.js.map +1 -1
  37. package/dist/doc-schemas/ncii/requests.d.ts.map +1 -1
  38. package/dist/doc-schemas/ncii/requests.js +4 -3
  39. package/dist/doc-schemas/ncii/requests.js.map +1 -1
  40. package/dist/doc-schemas/notification-ledger.d.ts.map +1 -1
  41. package/dist/doc-schemas/notification-ledger.js +3 -1
  42. package/dist/doc-schemas/notification-ledger.js.map +1 -1
  43. package/dist/doc-schemas/payments.d.ts.map +1 -1
  44. package/dist/doc-schemas/payments.js +2 -1
  45. package/dist/doc-schemas/payments.js.map +1 -1
  46. package/dist/doc-schemas/registry.d.ts +108 -35
  47. package/dist/doc-schemas/registry.d.ts.map +1 -1
  48. package/dist/doc-schemas/registry.js +4 -0
  49. package/dist/doc-schemas/registry.js.map +1 -1
  50. package/dist/doc-schemas/safety/age.d.ts.map +1 -1
  51. package/dist/doc-schemas/safety/age.js +4 -3
  52. package/dist/doc-schemas/safety/age.js.map +1 -1
  53. package/dist/doc-schemas/safety/case-aliases.d.ts.map +1 -1
  54. package/dist/doc-schemas/safety/case-aliases.js +5 -4
  55. package/dist/doc-schemas/safety/case-aliases.js.map +1 -1
  56. package/dist/doc-schemas/safety/case.d.ts.map +1 -1
  57. package/dist/doc-schemas/safety/case.js +4 -3
  58. package/dist/doc-schemas/safety/case.js.map +1 -1
  59. package/dist/doc-schemas/safety/evidence.js +3 -3
  60. package/dist/doc-schemas/safety/evidence.js.map +1 -1
  61. package/dist/doc-schemas/safety/foundation.d.ts.map +1 -1
  62. package/dist/doc-schemas/safety/foundation.js +5 -3
  63. package/dist/doc-schemas/safety/foundation.js.map +1 -1
  64. package/dist/doc-schemas/safety/holds.d.ts.map +1 -1
  65. package/dist/doc-schemas/safety/holds.js +4 -3
  66. package/dist/doc-schemas/safety/holds.js.map +1 -1
  67. package/dist/doc-schemas/safety/monitors.d.ts.map +1 -1
  68. package/dist/doc-schemas/safety/monitors.js +5 -3
  69. package/dist/doc-schemas/safety/monitors.js.map +1 -1
  70. package/dist/doc-schemas/safety/provenance.js +3 -3
  71. package/dist/doc-schemas/safety/provenance.js.map +1 -1
  72. package/dist/doc-schemas/safety/report.d.ts.map +1 -1
  73. package/dist/doc-schemas/safety/report.js +4 -3
  74. package/dist/doc-schemas/safety/report.js.map +1 -1
  75. package/dist/doc-schemas/safety/sagas.js +3 -3
  76. package/dist/doc-schemas/safety/sagas.js.map +1 -1
  77. package/dist/doc-schemas/social.d.ts +130 -0
  78. package/dist/doc-schemas/social.d.ts.map +1 -1
  79. package/dist/doc-schemas/social.js +91 -2
  80. package/dist/doc-schemas/social.js.map +1 -1
  81. package/dist/doc-schemas/square-announcement-jobs.d.ts +306 -14
  82. package/dist/doc-schemas/square-announcement-jobs.d.ts.map +1 -1
  83. package/dist/doc-schemas/square-announcement-jobs.js +15 -2
  84. package/dist/doc-schemas/square-announcement-jobs.js.map +1 -1
  85. package/dist/doc-schemas/user.js +3 -3
  86. package/dist/doc-schemas/user.js.map +1 -1
  87. package/dist/doc-schemas/work-project.js +2 -2
  88. package/dist/doc-schemas/work-project.js.map +1 -1
  89. package/dist/ids/chat-ids.d.ts +3 -2
  90. package/dist/ids/chat-ids.d.ts.map +1 -1
  91. package/dist/ids/chat-ids.js +3 -2
  92. package/dist/ids/chat-ids.js.map +1 -1
  93. package/dist/media/domain-events-admin.d.ts +0 -7
  94. package/dist/media/domain-events-admin.d.ts.map +1 -1
  95. package/dist/media/domain-events-admin.js +0 -11
  96. package/dist/media/domain-events-admin.js.map +1 -1
  97. package/dist/media/domain-events.d.ts +0 -6
  98. package/dist/media/domain-events.d.ts.map +1 -1
  99. package/dist/media/domain-events.js +1 -2
  100. package/dist/media/domain-events.js.map +1 -1
  101. package/dist/media/hall-library-target-fields.js +1 -1
  102. package/dist/media/hall-library-target-fields.js.map +1 -1
  103. package/dist/media/pending-media.d.ts +0 -54
  104. package/dist/media/pending-media.d.ts.map +1 -1
  105. package/dist/media/photodna-coverage.d.ts.map +1 -1
  106. package/dist/media/photodna-coverage.js +5 -3
  107. package/dist/media/photodna-coverage.js.map +1 -1
  108. package/dist/paths/related-ids.js +1 -1
  109. package/dist/paths/related-ids.js.map +1 -1
  110. package/dist/safety/ncii-intake-derivations.d.ts.map +1 -1
  111. package/dist/safety/ncii-intake-derivations.js +4 -2
  112. package/dist/safety/ncii-intake-derivations.js.map +1 -1
  113. package/dist/safety/resource-keys.d.ts +8 -0
  114. package/dist/safety/resource-keys.d.ts.map +1 -1
  115. package/dist/safety/resource-keys.js +12 -1
  116. package/dist/safety/resource-keys.js.map +1 -1
  117. package/dist/schemas/chat.js +3 -3
  118. package/dist/schemas/chat.js.map +1 -1
  119. package/dist/schemas/ncii.js +1 -1
  120. package/dist/schemas/ncii.js.map +1 -1
  121. package/dist/schemas/notification.d.ts +8 -8
  122. package/dist/schemas/notification.d.ts.map +1 -1
  123. package/dist/schemas/notification.js +17 -11
  124. package/dist/schemas/notification.js.map +1 -1
  125. package/dist/types/social.d.ts +1 -45
  126. package/dist/types/social.d.ts.map +1 -1
  127. package/dist/types/social.js.map +1 -1
  128. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"work-project.js","sourceRoot":"","sources":["../../src/doc-schemas/work-project.ts"],"names":[],"mappings":"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","sourcesContent":["// WorkProject / Realm / Guild Firestore document SCHEMAS — single source of truth.\n// Covers allWorkProjects/{workProjectId}, its guildmateUsers/publicGuildmateUsers/\n// workAssets subcollections, publicWorkProjects/{workProjectId}, workRealms/{workRealmId},\n// and the guildInviteConversations invite shell. Types are inferred via z.infer so a\n// document's shape and its TypeScript type cannot drift apart.\n//\n// Terminology: the current-owner field is `workStewardUid` (locked rename from the old\n// `ownerUid`; see docs/design/terminology-naming-convention.md — Steward row). The original\n// creator is `foundingArtisanUid` (locked rename from the old `createdByUid`; Founding Artisan).\n\nimport { z } from 'zod';\nimport { HALL_WING_TYPE_KEYS, WORK_PROJECT_TYPE_KEYS } from '../types/content.js';\nimport { isGuildStandingId, type GuildStandingId } from '../permissions/index.js';\n\nconst guildStandingIdSchema = z.custom<GuildStandingId>(isGuildStandingId);\nconst userRefSchema = z.object({ uid: z.string() });\n\nexport const GuildmateStatusSchema = z.enum(['active', 'departed']);\nexport type GuildmateStatus = z.infer<typeof GuildmateStatusSchema>;\n\nexport const GuildmateUserSchema = z.object({\n uid: z.string(),\n guildStandings: z.array(guildStandingIdSchema),\n tradeProfessions: z.array(z.string()),\n stakeShareCount: z.number(),\n joinedAt: z.number(),\n status: GuildmateStatusSchema,\n /**\n * Holder kind for this stake entry. Absent/`'user'` = a real guildmate person.\n * `'foundingWork'` = the realm founding-Work holder (keyed by the founding\n * workProjectId, NOT a user uid).\n */\n holderType: z.enum(['user', 'foundingWork']).optional(),\n /**\n * Per-(user, workProject) monotonic INPUT-trigger version for the chat\n * channel-auth projection (chat-edge-rebuild Contract B / P3). Absent ⇒ 0.\n * Bumped atomically in the authoritative mutation on member create/reactivate,\n * departure/removal, standing change, AND trade-profession change; the\n * `workChannelsForUser` fanout keys on the POST-increment value. It NEVER\n * increments or replaces the per-pair OUTPUT `channelAuthVersion`.\n */\n guildAuthInputVersion: z.number().optional(),\n /**\n * N3 data-deletion / account-end forfeiture tombstone. Set together with\n * `status: 'departed'` when a member leaves involuntarily-of-record: their\n * stake shares STAY in the immutable 1000-split (never removed) but are\n * forfeited — the future payout engine routes a tombstone's slice to the\n * community fund and excludes it from active distribution. `departedReason`\n * distinguishes the cause; `'bannedForCause'` is reserved for the future\n * ban-forfeiture path (included now so it needs no second package publish).\n *\n * `'selfLeave'` is DIFFERENT share semantics: a PRE-PUBLISH voluntary guild\n * exit (leaveWorkProject). There the 1000-split is still fluid, so the\n * member's `stakeShareCount` is ZEROED and returned to the pool for the\n * steward to re-allocate — NOT retained as a community-fund tombstone. A\n * self-leave is impossible once `status: 'published'` (the stake-share freeze\n * blocks it), so the tombstone and the pool-return dispositions never overlap\n * in a single Work's lifecycle.\n */\n departedReason: z.enum(['voluntaryDeletion', 'bannedForCause', 'selfLeave']).optional(),\n departedAt: z.number().optional(),\n});\nexport type GuildmateUser = z.infer<typeof GuildmateUserSchema>;\n\nexport const PublicGuildmateUserSchema = z.object({\n uid: z.string(),\n tradeProfessions: z.array(z.string()),\n joinedAt: z.number(),\n status: GuildmateStatusSchema,\n});\nexport type PublicGuildmateUser = z.infer<typeof PublicGuildmateUserSchema>;\n\nexport const PendingStakeSharesSchema = z.record(\n z.string(),\n z.object({ amount: z.number(), createdAt: z.number() }),\n);\nexport type PendingStakeShares = z.infer<typeof PendingStakeSharesSchema>;\n\nexport const FullWorkProjectSchema = z.object({\n workProjectId: z.string(),\n createdOn: z.number(),\n type: z.string(),\n workingDescription: z.string(),\n workingTitle: z.string(),\n hallWingType: z.enum(HALL_WING_TYPE_KEYS),\n createdBy: userRefSchema,\n status: z.enum(['open', 'pendingVerification', 'published', 'rejected']),\n guildmateUserIds: z.record(z.string(), z.boolean()).optional(),\n invitedUserIds: z.record(z.string(), z.boolean()).optional(),\n workRealmId: z.string(),\n realmCanonStatus: z.enum(['canon', 'nonCanon']),\n pendingStakeShares: PendingStakeSharesSchema.optional(),\n // Moderation \"require retitle\" remedy (work/realm report path). When an admin\n // upholds a report on an abusive public title/description, they may replace the\n // text with a generic placeholder and set this flag; the steward is prompted to\n // re-enter compliant text the next time they open the work (unpublished = direct\n // self-edit clears it; published = via the post-launch change-request flow).\n // Distinct from the `publicWorkHidden` hide (DMCA/copyright) — this keeps the\n // work visible under the placeholder. Backend-only-writable.\n moderationRetitleRequired: z.boolean().optional(),\n moderationRetitleReason: z.string().optional(),\n // Per-field extension of the retitle remedy (uniform with the Tale/Tune/Television content family):\n // which text fields ('title', 'description', …) an admin cleared to a placeholder — \"all or any\",\n // instead of the always-both retitle — and the operator's reason surfaced on the steward's edit\n // surface. Empty/absent when nothing was cleared. Backend-only-writable.\n moderationClearedFields: z.array(z.string()).optional(),\n moderationClearedReason: z.string().optional(),\n moderatedAt: z.number().optional(),\n});\nexport type FullWorkProject = z.infer<typeof FullWorkProjectSchema>;\n\n// Top-level safe signed-in-user Work shell / search projection. Server/callable-written only.\nexport const PublicWorkProjectSchema = z.object({\n workProjectId: z.string(),\n publicWorkStatus: z.enum(['draft', 'released']),\n publicWorkHidden: z.boolean(),\n workRealmId: z.string(),\n realmCanonStatus: z.enum(['canon', 'nonCanon']),\n type: z.enum(WORK_PROJECT_TYPE_KEYS),\n hallWingType: z.enum(HALL_WING_TYPE_KEYS),\n workingTitle: z.string(),\n workingTitle_lowercase: z.string(),\n workingDescription: z.string(),\n coverAssetId: z.string().optional(),\n workStewardUid: z.string(),\n foundingArtisanUid: z.string(),\n createdOn: z.number(),\n updatedOn: z.number(),\n});\nexport type PublicWorkProject = z.infer<typeof PublicWorkProjectSchema>;\n\n// ===========================================================================\n// Work-project FILE FOLDER system (S7) — supersedes the flat workAssets model.\n// A default folder (every active guildmate views/uploads) + custom folders whose\n// audience is controlled by TRADE PROFESSIONS, while file-system ADMINISTRATION is\n// controlled by guild standings (StewardOwner / WorkProjectManager / WorkAssetAdmin).\n// See docs/design/work-project-file-folders.md. Realm sharing of a file is the\n// `realmFileCanonStatus` seam on the file's mediaAssets doc (media-assets.ts).\n// ===========================================================================\n\n/** `allWorkProjects/{workProjectId}/workFileFolders/{workFileFolderId}`. */\nexport const WorkFileFolderSchema = z.object({\n workFileFolderId: z.string(),\n workProjectId: z.string(),\n name: z.string(),\n // The auto-created \"All Guildmates\" folder (view/upload open to every active\n // guildmate; delete/manage needs file-admin). Exactly one per work project.\n isDefault: z.boolean(),\n // Custom-folder access — trade-profession ids (TRADE_PROFESSION_OPTIONS). Empty\n // on the default folder; file admins always see/manage every folder regardless.\n canViewTradeProfessions: z.array(z.string()),\n canUploadTradeProfessions: z.array(z.string()),\n canDeleteTradeProfessions: z.array(z.string()),\n fileCount: z.number(),\n /** Sum of this folder's files' `sizeBytes`. Maintained alongside `fileCount`\n * (increment on upload, decrement on delete); the project-wide storage usage +\n * `MAX_WORK_FILE_STORAGE_BYTES` cap are computed by summing this across folders. */\n storageBytes: z.number(),\n createdBy: userRefSchema,\n createdAt: z.number(),\n updatedAt: z.number(),\n});\nexport type WorkFileFolder = z.infer<typeof WorkFileFolderSchema>;\n\n/** `allWorkProjects/{workProjectId}/workFileFolders/{workFileFolderId}/workFiles/{workFileId}`. */\nexport const WorkFileSchema = z.object({\n workFileId: z.string(),\n workProjectId: z.string(),\n workFileFolderId: z.string(),\n name: z.string(),\n mediaAssetId: z.string(),\n contentType: z.string(),\n sizeBytes: z.number(),\n uploadedBy: userRefSchema,\n createdAt: z.number(),\n});\nexport type WorkFile = z.infer<typeof WorkFileSchema>;\n\n// Realm source of truth and Realm search/tag surface. Server/callable-written only.\nexport const WorkRealmSchema = z.object({\n workRealmId: z.string(),\n realmType: z.enum(['public', 'standalone']),\n realmStatus: z.enum(['draft', 'released']),\n realmHidden: z.boolean(),\n workingTitle: z.string(),\n workingTitle_lowercase: z.string(),\n workingDescription: z.string(),\n // Square realm cover art (the 'realm-cover' upload origin; processor-written).\n // Optional while the realm is a DRAFT; releasing the realm REQUIRES it — the\n // realm release callable enforces presence (never required at founding, so a\n // work creation is never blocked on realm art).\n realmCoverAssetId: z.string().optional(),\n workStewardUid: z.string(),\n foundingArtisanUid: z.string(),\n foundingWorkProjectId: z.string(),\n createdOn: z.number(),\n updatedOn: z.number(),\n // MONOTONIC publish lock (R1 ruling, 2026-07-12): set true by the hall publish\n // core the first time any work in this realm publishes, and never unset — even\n // if that work later unpublishes (the realm name already went public). While\n // absent/false, realm info is direct-edit; once true, realm text changes route\n // exclusively through the change-request pipeline (surface 'workRealm').\n // Backend-only-writable.\n hasEverPublishedWork: z.boolean().optional(),\n // Moderation \"require retitle\" remedy (see FullWorkProject above) — admin\n // replaces an abusive realm title/description with a placeholder + sets this so\n // the steward must re-enter compliant text. Distinct from `realmHidden` (the\n // DMCA/copyright takedown). Backend-only-writable.\n moderationRetitleRequired: z.boolean().optional(),\n moderationRetitleReason: z.string().optional(),\n // Per-field extension of the retitle remedy (see FullWorkProject) — which realm text fields an\n // admin cleared to a placeholder (\"all or any\"), plus the operator's reason. Backend-only-writable.\n moderationClearedFields: z.array(z.string()).optional(),\n moderationClearedReason: z.string().optional(),\n moderatedAt: z.number().optional(),\n});\nexport type WorkRealm = z.infer<typeof WorkRealmSchema>;\n"]}
1
+ {"version":3,"file":"work-project.js","sourceRoot":"","sources":["../../src/doc-schemas/work-project.ts"],"names":[],"mappings":"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","sourcesContent":["// WorkProject / Realm / Guild Firestore document SCHEMAS — single source of truth.\n// Covers allWorkProjects/{workProjectId}, its guildmateUsers/publicGuildmateUsers/\n// workAssets subcollections, publicWorkProjects/{workProjectId}, workRealms/{workRealmId},\n// and the guildInviteConversations invite shell. Types are inferred via z.infer so a\n// document's shape and its TypeScript type cannot drift apart.\n//\n// Terminology: the current-owner field is `workStewardUid` (locked rename from the old\n// `ownerUid`; see ttt-prod docs/design/terminology-naming-convention.md — Steward row). The original\n// creator is `foundingArtisanUid` (locked rename from the old `createdByUid`; Founding Artisan).\n\nimport { z } from 'zod';\nimport { HALL_WING_TYPE_KEYS, WORK_PROJECT_TYPE_KEYS } from '../types/content.js';\nimport { isGuildStandingId, type GuildStandingId } from '../permissions/index.js';\n\nconst guildStandingIdSchema = z.custom<GuildStandingId>(isGuildStandingId);\nconst userRefSchema = z.object({ uid: z.string() });\n\nexport const GuildmateStatusSchema = z.enum(['active', 'departed']);\nexport type GuildmateStatus = z.infer<typeof GuildmateStatusSchema>;\n\nexport const GuildmateUserSchema = z.object({\n uid: z.string(),\n guildStandings: z.array(guildStandingIdSchema),\n tradeProfessions: z.array(z.string()),\n stakeShareCount: z.number(),\n joinedAt: z.number(),\n status: GuildmateStatusSchema,\n /**\n * Holder kind for this stake entry. Absent/`'user'` = a real guildmate person.\n * `'foundingWork'` = the realm founding-Work holder (keyed by the founding\n * workProjectId, NOT a user uid).\n */\n holderType: z.enum(['user', 'foundingWork']).optional(),\n /**\n * Per-(user, workProject) monotonic INPUT-trigger version for the chat\n * channel-auth projection (chat-edge-rebuild Contract B / P3). Absent ⇒ 0.\n * Bumped atomically in the authoritative mutation on member create/reactivate,\n * departure/removal, standing change, AND trade-profession change; the\n * `workChannelsForUser` fanout keys on the POST-increment value. It NEVER\n * increments or replaces the per-pair OUTPUT `channelAuthVersion`.\n */\n guildAuthInputVersion: z.number().optional(),\n /**\n * N3 data-deletion / account-end forfeiture tombstone. Set together with\n * `status: 'departed'` when a member leaves involuntarily-of-record: their\n * stake shares STAY in the immutable 1000-split (never removed) but are\n * forfeited — the future payout engine routes a tombstone's slice to the\n * community fund and excludes it from active distribution. `departedReason`\n * distinguishes the cause; `'bannedForCause'` is reserved for the future\n * ban-forfeiture path (included now so it needs no second package publish).\n *\n * `'selfLeave'` is DIFFERENT share semantics: a PRE-PUBLISH voluntary guild\n * exit (leaveWorkProject). There the 1000-split is still fluid, so the\n * member's `stakeShareCount` is ZEROED and returned to the pool for the\n * steward to re-allocate — NOT retained as a community-fund tombstone. A\n * self-leave is impossible once `status: 'published'` (the stake-share freeze\n * blocks it), so the tombstone and the pool-return dispositions never overlap\n * in a single Work's lifecycle.\n */\n departedReason: z.enum(['voluntaryDeletion', 'bannedForCause', 'selfLeave']).optional(),\n departedAt: z.number().optional(),\n});\nexport type GuildmateUser = z.infer<typeof GuildmateUserSchema>;\n\nexport const PublicGuildmateUserSchema = z.object({\n uid: z.string(),\n tradeProfessions: z.array(z.string()),\n joinedAt: z.number(),\n status: GuildmateStatusSchema,\n});\nexport type PublicGuildmateUser = z.infer<typeof PublicGuildmateUserSchema>;\n\nexport const PendingStakeSharesSchema = z.record(\n z.string(),\n z.object({ amount: z.number(), createdAt: z.number() }),\n);\nexport type PendingStakeShares = z.infer<typeof PendingStakeSharesSchema>;\n\nexport const FullWorkProjectSchema = z.object({\n workProjectId: z.string(),\n createdOn: z.number(),\n type: z.string(),\n workingDescription: z.string(),\n workingTitle: z.string(),\n hallWingType: z.enum(HALL_WING_TYPE_KEYS),\n createdBy: userRefSchema,\n status: z.enum(['open', 'pendingVerification', 'published', 'rejected']),\n guildmateUserIds: z.record(z.string(), z.boolean()).optional(),\n invitedUserIds: z.record(z.string(), z.boolean()).optional(),\n workRealmId: z.string(),\n realmCanonStatus: z.enum(['canon', 'nonCanon']),\n pendingStakeShares: PendingStakeSharesSchema.optional(),\n // Moderation \"require retitle\" remedy (work/realm report path). When an admin\n // upholds a report on an abusive public title/description, they may replace the\n // text with a generic placeholder and set this flag; the steward is prompted to\n // re-enter compliant text the next time they open the work (unpublished = direct\n // self-edit clears it; published = via the post-launch change-request flow).\n // Distinct from the `publicWorkHidden` hide (DMCA/copyright) — this keeps the\n // work visible under the placeholder. Backend-only-writable.\n moderationRetitleRequired: z.boolean().optional(),\n moderationRetitleReason: z.string().optional(),\n // Per-field extension of the retitle remedy (uniform with the Tale/Tune/Television content family):\n // which text fields ('title', 'description', …) an admin cleared to a placeholder — \"all or any\",\n // instead of the always-both retitle — and the operator's reason surfaced on the steward's edit\n // surface. Empty/absent when nothing was cleared. Backend-only-writable.\n moderationClearedFields: z.array(z.string()).optional(),\n moderationClearedReason: z.string().optional(),\n moderatedAt: z.number().optional(),\n});\nexport type FullWorkProject = z.infer<typeof FullWorkProjectSchema>;\n\n// Top-level safe signed-in-user Work shell / search projection. Server/callable-written only.\nexport const PublicWorkProjectSchema = z.object({\n workProjectId: z.string(),\n publicWorkStatus: z.enum(['draft', 'released']),\n publicWorkHidden: z.boolean(),\n workRealmId: z.string(),\n realmCanonStatus: z.enum(['canon', 'nonCanon']),\n type: z.enum(WORK_PROJECT_TYPE_KEYS),\n hallWingType: z.enum(HALL_WING_TYPE_KEYS),\n workingTitle: z.string(),\n workingTitle_lowercase: z.string(),\n workingDescription: z.string(),\n coverAssetId: z.string().optional(),\n workStewardUid: z.string(),\n foundingArtisanUid: z.string(),\n createdOn: z.number(),\n updatedOn: z.number(),\n});\nexport type PublicWorkProject = z.infer<typeof PublicWorkProjectSchema>;\n\n// ===========================================================================\n// Work-project FILE FOLDER system (S7) — supersedes the flat workAssets model.\n// A default folder (every active guildmate views/uploads) + custom folders whose\n// audience is controlled by TRADE PROFESSIONS, while file-system ADMINISTRATION is\n// controlled by guild standings (StewardOwner / WorkProjectManager / WorkAssetAdmin).\n// See ttt-prod docs/design/work-project-file-folders.md. Realm sharing of a file is the\n// `realmFileCanonStatus` seam on the file's mediaAssets doc (media-assets.ts).\n// ===========================================================================\n\n/** `allWorkProjects/{workProjectId}/workFileFolders/{workFileFolderId}`. */\nexport const WorkFileFolderSchema = z.object({\n workFileFolderId: z.string(),\n workProjectId: z.string(),\n name: z.string(),\n // The auto-created \"All Guildmates\" folder (view/upload open to every active\n // guildmate; delete/manage needs file-admin). Exactly one per work project.\n isDefault: z.boolean(),\n // Custom-folder access — trade-profession ids (TRADE_PROFESSION_OPTIONS). Empty\n // on the default folder; file admins always see/manage every folder regardless.\n canViewTradeProfessions: z.array(z.string()),\n canUploadTradeProfessions: z.array(z.string()),\n canDeleteTradeProfessions: z.array(z.string()),\n fileCount: z.number(),\n /** Sum of this folder's files' `sizeBytes`. Maintained alongside `fileCount`\n * (increment on upload, decrement on delete); the project-wide storage usage +\n * `MAX_WORK_FILE_STORAGE_BYTES` cap are computed by summing this across folders. */\n storageBytes: z.number(),\n createdBy: userRefSchema,\n createdAt: z.number(),\n updatedAt: z.number(),\n});\nexport type WorkFileFolder = z.infer<typeof WorkFileFolderSchema>;\n\n/** `allWorkProjects/{workProjectId}/workFileFolders/{workFileFolderId}/workFiles/{workFileId}`. */\nexport const WorkFileSchema = z.object({\n workFileId: z.string(),\n workProjectId: z.string(),\n workFileFolderId: z.string(),\n name: z.string(),\n mediaAssetId: z.string(),\n contentType: z.string(),\n sizeBytes: z.number(),\n uploadedBy: userRefSchema,\n createdAt: z.number(),\n});\nexport type WorkFile = z.infer<typeof WorkFileSchema>;\n\n// Realm source of truth and Realm search/tag surface. Server/callable-written only.\nexport const WorkRealmSchema = z.object({\n workRealmId: z.string(),\n realmType: z.enum(['public', 'standalone']),\n realmStatus: z.enum(['draft', 'released']),\n realmHidden: z.boolean(),\n workingTitle: z.string(),\n workingTitle_lowercase: z.string(),\n workingDescription: z.string(),\n // Square realm cover art (the 'realm-cover' upload origin; processor-written).\n // Optional while the realm is a DRAFT; releasing the realm REQUIRES it — the\n // realm release callable enforces presence (never required at founding, so a\n // work creation is never blocked on realm art).\n realmCoverAssetId: z.string().optional(),\n workStewardUid: z.string(),\n foundingArtisanUid: z.string(),\n foundingWorkProjectId: z.string(),\n createdOn: z.number(),\n updatedOn: z.number(),\n // MONOTONIC publish lock (R1 ruling, 2026-07-12): set true by the hall publish\n // core the first time any work in this realm publishes, and never unset — even\n // if that work later unpublishes (the realm name already went public). While\n // absent/false, realm info is direct-edit; once true, realm text changes route\n // exclusively through the change-request pipeline (surface 'workRealm').\n // Backend-only-writable.\n hasEverPublishedWork: z.boolean().optional(),\n // Moderation \"require retitle\" remedy (see FullWorkProject above) — admin\n // replaces an abusive realm title/description with a placeholder + sets this so\n // the steward must re-enter compliant text. Distinct from `realmHidden` (the\n // DMCA/copyright takedown). Backend-only-writable.\n moderationRetitleRequired: z.boolean().optional(),\n moderationRetitleReason: z.string().optional(),\n // Per-field extension of the retitle remedy (see FullWorkProject) — which realm text fields an\n // admin cleared to a placeholder (\"all or any\"), plus the operator's reason. Backend-only-writable.\n moderationClearedFields: z.array(z.string()).optional(),\n moderationClearedReason: z.string().optional(),\n moderatedAt: z.number().optional(),\n});\nexport type WorkRealm = z.infer<typeof WorkRealmSchema>;\n"]}
@@ -1,6 +1,7 @@
1
1
  /**
2
- * Frozen deterministic IDs for the chat realtime + notification redesign
3
- * (IMPLEMENTATION_MATRIX.md "Deterministic ID + eventId formulas").
2
+ * Frozen deterministic ID + eventId formulas for the chat realtime + notification
3
+ * redesign. The durable design owners are ttt-prod
4
+ * docs/design/chat-realtime-system.md and docs/design/notification-system.md.
4
5
  *
5
6
  * These ids are computed INDEPENDENTLY by multiple producers/consumers
6
7
  * (Cloud Functions, the chat Worker, sometimes the client) and MUST match
@@ -1 +1 @@
1
- {"version":3,"file":"chat-ids.d.ts","sourceRoot":"","sources":["../../src/ids/chat-ids.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chat-ids.d.ts","sourceRoot":"","sources":["../../src/ids/chat-ids.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  /**
2
- * Frozen deterministic IDs for the chat realtime + notification redesign
3
- * (IMPLEMENTATION_MATRIX.md "Deterministic ID + eventId formulas").
2
+ * Frozen deterministic ID + eventId formulas for the chat realtime + notification
3
+ * redesign. The durable design owners are ttt-prod
4
+ * docs/design/chat-realtime-system.md and docs/design/notification-system.md.
4
5
  *
5
6
  * These ids are computed INDEPENDENTLY by multiple producers/consumers
6
7
  * (Cloud Functions, the chat Worker, sometimes the client) and MUST match
@@ -1 +1 @@
1
- {"version":3,"file":"chat-ids.js","sourceRoot":"","sources":["../../src/ids/chat-ids.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AAEhE,qFAAqF;AACrF,MAAM,cAAc,GAAG,MAAM,CAAC;AAC9B,6EAA6E;AAC7E,MAAM,SAAS,GAAG,MAAM,CAAC;AAEzB,SAAS,UAAU,CAAC,IAAwC;IAC1D,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1D,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACxD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,IAAI,CAClB,SAAiB,EACjB,GAAG,KAAgD;IAEnD,MAAM,KAAK,GAAG,SAAS,GAAG,cAAc,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACtF,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC;AAC1B,CAAC;AASD,yGAAyG;AACzG,MAAM,UAAU,UAAU,CAAC,GAAe;IACxC,OAAO,GAAG,CAAC,KAAK,KAAK,SAAS;QAC5B,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,CAAC,aAAa,EAAE,GAAG,CAAC,kBAAkB,CAAC;QACjE,CAAC,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;AAC7C,CAAC;AAED,yFAAyF;AACzF,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAe,EAAE,GAAW;IAC5D,OAAO,IAAI,CAAC,mBAAmB,EAAE,MAAM,UAAU,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;AAC/D,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,aAAqB;IACjE,OAAO,IAAI,CAAC,gBAAgB,EAAE,GAAG,EAAE,aAAa,CAAC,CAAC;AACpD,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,4BAA4B,CAAC,GAAW,EAAE,aAAqB;IAC7E,OAAO,IAAI,CAAC,yBAAyB,EAAE,GAAG,EAAE,aAAa,CAAC,CAAC;AAC7D,CAAC;AAED,uGAAuG;AACvG,MAAM,UAAU,eAAe,CAAC,IAA+B,EAAE,GAAW;IAC1E,OAAO,IAAI,CAAC,qBAAqB,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;AAChD,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,kBAAkB,CAAC,cAAsB,EAAE,GAAW,EAAE,kBAA0B;IAChG,OAAO,IAAI,CAAC,cAAc,EAAE,cAAc,EAAE,GAAG,EAAE,kBAAkB,CAAC,CAAC;AACvE,CAAC;AACD,MAAM,UAAU,oBAAoB,CAAC,GAAW,EAAE,oBAA4B,EAAE,cAAsB;IACpG,OAAO,IAAI,CAAC,gBAAgB,EAAE,GAAG,EAAE,oBAAoB,EAAE,cAAc,CAAC,CAAC;AAC3E,CAAC;AACD,MAAM,UAAU,aAAa,CAAC,cAAsB,EAAE,aAAqB;IACzE,OAAO,IAAI,CAAC,QAAQ,EAAE,cAAc,EAAE,aAAa,CAAC,CAAC;AACvD,CAAC;AACD,MAAM,UAAU,qBAAqB,CAAC,cAAsB,EAAE,aAAqB;IACjF,OAAO,IAAI,CAAC,iBAAiB,EAAE,cAAc,EAAE,aAAa,CAAC,CAAC;AAChE,CAAC;AACD,MAAM,UAAU,oBAAoB,CAAC,SAAiB,EAAE,WAAmB;IACzE,OAAO,IAAI,CAAC,YAAY,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;AACpD,CAAC;AAED,gHAAgH;AAChH,MAAM,UAAU,sBAAsB,CAAC,SAAiB,EAAE,WAAmB;IAC3E,OAAO,IAAI,CAAC,YAAY,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;AACpD,CAAC;AAMD;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CACjC,YAAoC,EACpC,QAAgB,EAChB,YAAoB;IAEpB,OAAO,IAAI,CAAC,kBAAkB,EAAE,YAAY,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;AACxE,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,sBAAsB,CACpC,cAAsB,EACtB,YAAoB,EACpB,IAAY,EACZ,aAAqB;IAErB,OAAO,IAAI,CAAC,kBAAkB,EAAE,cAAc,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;AACrF,CAAC;AAED,+EAA+E;AAE/E,0GAA0G;AAC1G,MAAM,UAAU,sBAAsB,CACpC,YAA2B,EAC3B,gBAAwB,EACxB,OAAe;IAEf,OAAO,IAAI,CAAC,gBAAgB,EAAE,YAAY,IAAI,QAAQ,EAAE,gBAAgB,EAAE,OAAO,CAAC,CAAC;AACrF,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,4BAA4B,CAC1C,QAAgB,EAChB,aAAqB,EACrB,SAAiB;IAEjB,OAAO,IAAI,CAAC,sBAAsB,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;AAC1E,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,8BAA8B,CAC5C,QAAgB,EAChB,0BAAkC,EAClC,QAAgB,EAChB,aAAqB;IAErB,OAAO,IAAI,CAAC,8BAA8B,EAAE,QAAQ,EAAE,0BAA0B,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;AAC7G,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,0BAA0B,CAAC,SAAiB;IAC1D,OAAO,IAAI,CAAC,2BAA2B,EAAE,SAAS,CAAC,CAAC;AACtD,CAAC;AACD,MAAM,UAAU,wBAAwB,CAAC,SAAiB,EAAE,wBAAgC;IAC1F,OAAO,IAAI,CAAC,yBAAyB,EAAE,SAAS,EAAE,wBAAwB,CAAC,CAAC;AAC9E,CAAC;AACD,MAAM,UAAU,uBAAuB,CAAC,SAAiB,EAAE,yBAAiC;IAC1F,OAAO,IAAI,CAAC,wBAAwB,EAAE,SAAS,EAAE,yBAAyB,CAAC,CAAC;AAC9E,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,kBAAkB,CAAC,WAAmB,EAAE,KAAa,EAAE,aAAqB;IAC1F,OAAO,IAAI,CAAC,gBAAgB,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;AACnE,CAAC","sourcesContent":["/**\n * Frozen deterministic IDs for the chat realtime + notification redesign\n * (IMPLEMENTATION_MATRIX.md \"Deterministic ID + eventId formulas\").\n *\n * These ids are computed INDEPENDENTLY by multiple producers/consumers\n * (Cloud Functions, the chat Worker, sometimes the client) and MUST match\n * byte-for-byte, so the construction is frozen here as the single source of\n * truth. Hashing uses `@ttt-productions/edge-protocol-core`'s runtime-neutral\n * WebCrypto SHA-256 (works in Node 22, Cloudflare Workers, and browsers), so\n * every builder is async.\n */\n\nimport { sha256Hex } from '@ttt-productions/edge-protocol-core';\n\n/** ASCII unit separator — never appears in uids/doc-ids/collection names/numbers. */\nconst UNIT_SEPARATOR = '\\x1f';\n/** A null/absent part hashes as this byte (distinct from any real value). */\nconst NULL_BYTE = '\\x00';\n\nfunction encodePart(part: string | number | null | undefined): string {\n if (part === null || part === undefined) return NULL_BYTE;\n return typeof part === 'number' ? String(part) : part;\n}\n\n/**\n * Canonical collision-safe hash — every `hash(...)` in the chat/notification\n * doc set uses THIS. `domainTag` then each part, separated by `0x1F`; numbers\n * base-10; a null/absent part becomes the literal byte `0x00`. The full 64-char\n * lowercase-hex SHA-256 is the document id. Two id families can never collide\n * because their `domainTag`s differ.\n */\nexport function hash(\n domainTag: string,\n ...parts: Array<string | number | null | undefined>\n): Promise<string> {\n const input = domainTag + UNIT_SEPARATOR + parts.map(encodePart).join(UNIT_SEPARATOR);\n return sha256Hex(input);\n}\n\n// ── Channel identity ────────────────────────────────────────────────────────\n\n/** A logical chat channel — a typed tuple, NEVER a Firestore path string. */\nexport type ChannelRef =\n | { scope: 'channel'; workProjectId: string; guildChatChannelId: string }\n | { scope: 'invite'; guildInviteId: string };\n\n/** Per-scope collision-safe channel key. The raw tuple is stored alongside wherever this is a doc id. */\nexport function channelKey(ref: ChannelRef): Promise<string> {\n return ref.scope === 'channel'\n ? hash('chat-channel', ref.workProjectId, ref.guildChatChannelId)\n : hash('chat-invite', ref.guildInviteId);\n}\n\n/** Per-(channel, user) projection doc id (replaces the unsafe `{channelRef}__{uid}`). */\nexport async function authPairKey(ref: ChannelRef, uid: string): Promise<string> {\n return hash('chat-channel-auth', await channelKey(ref), uid);\n}\n\n/** Member-in-work degraded scope key (the `workChannelsForUser` selector blocks per uid×Work). */\nexport function userWorkScopeKey(uid: string, workProjectId: string): Promise<string> {\n return hash('chat-user-work', uid, workProjectId);\n}\n\n/** member-in-work degraded summary doc id. */\nexport function degradedMemberInWorkScopeKey(uid: string, workProjectId: string): Promise<string> {\n return hash('chat-degraded-user-work', uid, workProjectId);\n}\n\n/** Namespaced degraded cause id (`kind` keeps event-derived and job-derived causes from colliding). */\nexport function degradedCauseId(kind: 'syncEvent' | 'fanoutJob', ref: string): Promise<string> {\n return hash('chat-degraded-cause', kind, ref);\n}\n\n// ── chatSyncEvents eventIds ─────────────────────────────────────────────────\n\nexport function channelAuthEventId(channelKeyHash: string, uid: string, channelAuthVersion: number): Promise<string> {\n return hash('channel-auth', channelKeyHash, uid, channelAuthVersion);\n}\nexport function accountAccessEventId(uid: string, accountAccessVersion: number, channelKeyHash: string): Promise<string> {\n return hash('account-access', uid, accountAccessVersion, channelKeyHash);\n}\nexport function configEventId(channelKeyHash: string, configVersion: number): Promise<string> {\n return hash('config', channelKeyHash, configVersion);\n}\nexport function attachmentFlipEventId(pendingMediaId: string, terminalState: string): Promise<string> {\n return hash('attachment-flip', pendingMediaId, terminalState);\n}\nexport function serverMessageEventId(threadRef: string, sourceDocId: string): Promise<string> {\n return hash('server-msg', threadRef, sourceDocId);\n}\n\n/** `chatMessageOutbox` commandId for invite/system messages (= attachment uses the pendingMediaId directly). */\nexport function serverMessageCommandId(threadRef: string, sourceDocId: string): Promise<string> {\n return hash('server-msg', threadRef, sourceDocId);\n}\n\n// ── chatSyncFanoutJobs ──────────────────────────────────────────────────────\n\nexport type SyncFanoutSelectorKind = 'channelMembers' | 'workChannelsForUser' | 'policyEditAffectedUsers';\n\n/**\n * `scopeKey` = `channelKey` for channelMembers/policyEditAffectedUsers, or\n * `userWorkScopeKey(uid, workProjectId)` for workChannelsForUser. `causeVersion`\n * = the channel's post-mutation configVersion, or the user's post-mutation\n * guildAuthInputVersion respectively.\n */\nexport function chatSyncFanoutJobId(\n selectorKind: SyncFanoutSelectorKind,\n scopeKey: string,\n causeVersion: number,\n): Promise<string> {\n return hash('chat-sync-fanout', selectorKind, scopeKey, causeVersion);\n}\n\n// ── Inbox projection eventId ────────────────────────────────────────────────\n\nexport function inboxProjectionEventId(\n channelKeyHash: string,\n recipientUid: string,\n kind: string,\n sourceVersion: number,\n): Promise<string> {\n return hash('chat-inbox-event', channelKeyHash, recipientUid, kind, sourceVersion);\n}\n\n// ── Notification ledger / archive ───────────────────────────────────────────\n\n/** Delivery-ledger row id. Shared-admin occurrences pass `recipientUid = null` (hashed as `'shared'`). */\nexport function notificationDeliveryId(\n recipientUid: string | null,\n notificationType: string,\n eventId: string,\n): Promise<string> {\n return hash('notif-delivery', recipientUid ?? 'shared', notificationType, eventId);\n}\n\n/** Archive history doc id (= `archiveOccurrenceId`). */\nexport function notificationArchiveHistoryId(\n category: string,\n audienceScope: string,\n requestId: string,\n): Promise<string> {\n return hash('notification-archive', category, audienceScope, requestId);\n}\n\n/** Archive replay-vs-conflict discriminator. */\nexport function notificationArchivePayloadHash(\n activeId: string,\n observedActivityGeneration: string,\n category: string,\n audienceScope: string,\n): Promise<string> {\n return hash('notification-archive-payload', activeId, observedActivityGeneration, category, audienceScope);\n}\n\n// ── Moderation audit ids (append-only; create-if-absent) ────────────────────\n\nexport function moderationRequestedAuditId(requestId: string): Promise<string> {\n return hash('chat-moderation-requested', requestId);\n}\nexport function moderationAppliedAuditId(requestId: string, resultingMessageRevision: number): Promise<string> {\n return hash('chat-moderation-applied', requestId, resultingMessageRevision);\n}\nexport function moderationFailedAuditId(requestId: string, terminalFailureGeneration: number): Promise<string> {\n return hash('chat-moderation-failed', requestId, terminalFailureGeneration);\n}\n\n// ── History anonymization ───────────────────────────────────────────────────\n\nexport function chatAnonymizeJobId(channelDoId: string, epoch: number, anonymizedUid: string): Promise<string> {\n return hash('chat-anonymize', channelDoId, epoch, anonymizedUid);\n}\n"]}
1
+ {"version":3,"file":"chat-ids.js","sourceRoot":"","sources":["../../src/ids/chat-ids.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AAEhE,qFAAqF;AACrF,MAAM,cAAc,GAAG,MAAM,CAAC;AAC9B,6EAA6E;AAC7E,MAAM,SAAS,GAAG,MAAM,CAAC;AAEzB,SAAS,UAAU,CAAC,IAAwC;IAC1D,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1D,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACxD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,IAAI,CAClB,SAAiB,EACjB,GAAG,KAAgD;IAEnD,MAAM,KAAK,GAAG,SAAS,GAAG,cAAc,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACtF,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC;AAC1B,CAAC;AASD,yGAAyG;AACzG,MAAM,UAAU,UAAU,CAAC,GAAe;IACxC,OAAO,GAAG,CAAC,KAAK,KAAK,SAAS;QAC5B,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,CAAC,aAAa,EAAE,GAAG,CAAC,kBAAkB,CAAC;QACjE,CAAC,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;AAC7C,CAAC;AAED,yFAAyF;AACzF,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAe,EAAE,GAAW;IAC5D,OAAO,IAAI,CAAC,mBAAmB,EAAE,MAAM,UAAU,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;AAC/D,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,aAAqB;IACjE,OAAO,IAAI,CAAC,gBAAgB,EAAE,GAAG,EAAE,aAAa,CAAC,CAAC;AACpD,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,4BAA4B,CAAC,GAAW,EAAE,aAAqB;IAC7E,OAAO,IAAI,CAAC,yBAAyB,EAAE,GAAG,EAAE,aAAa,CAAC,CAAC;AAC7D,CAAC;AAED,uGAAuG;AACvG,MAAM,UAAU,eAAe,CAAC,IAA+B,EAAE,GAAW;IAC1E,OAAO,IAAI,CAAC,qBAAqB,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;AAChD,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,kBAAkB,CAAC,cAAsB,EAAE,GAAW,EAAE,kBAA0B;IAChG,OAAO,IAAI,CAAC,cAAc,EAAE,cAAc,EAAE,GAAG,EAAE,kBAAkB,CAAC,CAAC;AACvE,CAAC;AACD,MAAM,UAAU,oBAAoB,CAAC,GAAW,EAAE,oBAA4B,EAAE,cAAsB;IACpG,OAAO,IAAI,CAAC,gBAAgB,EAAE,GAAG,EAAE,oBAAoB,EAAE,cAAc,CAAC,CAAC;AAC3E,CAAC;AACD,MAAM,UAAU,aAAa,CAAC,cAAsB,EAAE,aAAqB;IACzE,OAAO,IAAI,CAAC,QAAQ,EAAE,cAAc,EAAE,aAAa,CAAC,CAAC;AACvD,CAAC;AACD,MAAM,UAAU,qBAAqB,CAAC,cAAsB,EAAE,aAAqB;IACjF,OAAO,IAAI,CAAC,iBAAiB,EAAE,cAAc,EAAE,aAAa,CAAC,CAAC;AAChE,CAAC;AACD,MAAM,UAAU,oBAAoB,CAAC,SAAiB,EAAE,WAAmB;IACzE,OAAO,IAAI,CAAC,YAAY,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;AACpD,CAAC;AAED,gHAAgH;AAChH,MAAM,UAAU,sBAAsB,CAAC,SAAiB,EAAE,WAAmB;IAC3E,OAAO,IAAI,CAAC,YAAY,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;AACpD,CAAC;AAMD;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CACjC,YAAoC,EACpC,QAAgB,EAChB,YAAoB;IAEpB,OAAO,IAAI,CAAC,kBAAkB,EAAE,YAAY,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;AACxE,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,sBAAsB,CACpC,cAAsB,EACtB,YAAoB,EACpB,IAAY,EACZ,aAAqB;IAErB,OAAO,IAAI,CAAC,kBAAkB,EAAE,cAAc,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;AACrF,CAAC;AAED,+EAA+E;AAE/E,0GAA0G;AAC1G,MAAM,UAAU,sBAAsB,CACpC,YAA2B,EAC3B,gBAAwB,EACxB,OAAe;IAEf,OAAO,IAAI,CAAC,gBAAgB,EAAE,YAAY,IAAI,QAAQ,EAAE,gBAAgB,EAAE,OAAO,CAAC,CAAC;AACrF,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,4BAA4B,CAC1C,QAAgB,EAChB,aAAqB,EACrB,SAAiB;IAEjB,OAAO,IAAI,CAAC,sBAAsB,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;AAC1E,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,8BAA8B,CAC5C,QAAgB,EAChB,0BAAkC,EAClC,QAAgB,EAChB,aAAqB;IAErB,OAAO,IAAI,CAAC,8BAA8B,EAAE,QAAQ,EAAE,0BAA0B,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;AAC7G,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,0BAA0B,CAAC,SAAiB;IAC1D,OAAO,IAAI,CAAC,2BAA2B,EAAE,SAAS,CAAC,CAAC;AACtD,CAAC;AACD,MAAM,UAAU,wBAAwB,CAAC,SAAiB,EAAE,wBAAgC;IAC1F,OAAO,IAAI,CAAC,yBAAyB,EAAE,SAAS,EAAE,wBAAwB,CAAC,CAAC;AAC9E,CAAC;AACD,MAAM,UAAU,uBAAuB,CAAC,SAAiB,EAAE,yBAAiC;IAC1F,OAAO,IAAI,CAAC,wBAAwB,EAAE,SAAS,EAAE,yBAAyB,CAAC,CAAC;AAC9E,CAAC;AAED,+EAA+E;AAE/E,MAAM,UAAU,kBAAkB,CAAC,WAAmB,EAAE,KAAa,EAAE,aAAqB;IAC1F,OAAO,IAAI,CAAC,gBAAgB,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;AACnE,CAAC","sourcesContent":["/**\n * Frozen deterministic ID + eventId formulas for the chat realtime + notification\n * redesign. The durable design owners are ttt-prod\n * docs/design/chat-realtime-system.md and docs/design/notification-system.md.\n *\n * These ids are computed INDEPENDENTLY by multiple producers/consumers\n * (Cloud Functions, the chat Worker, sometimes the client) and MUST match\n * byte-for-byte, so the construction is frozen here as the single source of\n * truth. Hashing uses `@ttt-productions/edge-protocol-core`'s runtime-neutral\n * WebCrypto SHA-256 (works in Node 22, Cloudflare Workers, and browsers), so\n * every builder is async.\n */\n\nimport { sha256Hex } from '@ttt-productions/edge-protocol-core';\n\n/** ASCII unit separator — never appears in uids/doc-ids/collection names/numbers. */\nconst UNIT_SEPARATOR = '\\x1f';\n/** A null/absent part hashes as this byte (distinct from any real value). */\nconst NULL_BYTE = '\\x00';\n\nfunction encodePart(part: string | number | null | undefined): string {\n if (part === null || part === undefined) return NULL_BYTE;\n return typeof part === 'number' ? String(part) : part;\n}\n\n/**\n * Canonical collision-safe hash — every `hash(...)` in the chat/notification\n * doc set uses THIS. `domainTag` then each part, separated by `0x1F`; numbers\n * base-10; a null/absent part becomes the literal byte `0x00`. The full 64-char\n * lowercase-hex SHA-256 is the document id. Two id families can never collide\n * because their `domainTag`s differ.\n */\nexport function hash(\n domainTag: string,\n ...parts: Array<string | number | null | undefined>\n): Promise<string> {\n const input = domainTag + UNIT_SEPARATOR + parts.map(encodePart).join(UNIT_SEPARATOR);\n return sha256Hex(input);\n}\n\n// ── Channel identity ────────────────────────────────────────────────────────\n\n/** A logical chat channel — a typed tuple, NEVER a Firestore path string. */\nexport type ChannelRef =\n | { scope: 'channel'; workProjectId: string; guildChatChannelId: string }\n | { scope: 'invite'; guildInviteId: string };\n\n/** Per-scope collision-safe channel key. The raw tuple is stored alongside wherever this is a doc id. */\nexport function channelKey(ref: ChannelRef): Promise<string> {\n return ref.scope === 'channel'\n ? hash('chat-channel', ref.workProjectId, ref.guildChatChannelId)\n : hash('chat-invite', ref.guildInviteId);\n}\n\n/** Per-(channel, user) projection doc id (replaces the unsafe `{channelRef}__{uid}`). */\nexport async function authPairKey(ref: ChannelRef, uid: string): Promise<string> {\n return hash('chat-channel-auth', await channelKey(ref), uid);\n}\n\n/** Member-in-work degraded scope key (the `workChannelsForUser` selector blocks per uid×Work). */\nexport function userWorkScopeKey(uid: string, workProjectId: string): Promise<string> {\n return hash('chat-user-work', uid, workProjectId);\n}\n\n/** member-in-work degraded summary doc id. */\nexport function degradedMemberInWorkScopeKey(uid: string, workProjectId: string): Promise<string> {\n return hash('chat-degraded-user-work', uid, workProjectId);\n}\n\n/** Namespaced degraded cause id (`kind` keeps event-derived and job-derived causes from colliding). */\nexport function degradedCauseId(kind: 'syncEvent' | 'fanoutJob', ref: string): Promise<string> {\n return hash('chat-degraded-cause', kind, ref);\n}\n\n// ── chatSyncEvents eventIds ─────────────────────────────────────────────────\n\nexport function channelAuthEventId(channelKeyHash: string, uid: string, channelAuthVersion: number): Promise<string> {\n return hash('channel-auth', channelKeyHash, uid, channelAuthVersion);\n}\nexport function accountAccessEventId(uid: string, accountAccessVersion: number, channelKeyHash: string): Promise<string> {\n return hash('account-access', uid, accountAccessVersion, channelKeyHash);\n}\nexport function configEventId(channelKeyHash: string, configVersion: number): Promise<string> {\n return hash('config', channelKeyHash, configVersion);\n}\nexport function attachmentFlipEventId(pendingMediaId: string, terminalState: string): Promise<string> {\n return hash('attachment-flip', pendingMediaId, terminalState);\n}\nexport function serverMessageEventId(threadRef: string, sourceDocId: string): Promise<string> {\n return hash('server-msg', threadRef, sourceDocId);\n}\n\n/** `chatMessageOutbox` commandId for invite/system messages (= attachment uses the pendingMediaId directly). */\nexport function serverMessageCommandId(threadRef: string, sourceDocId: string): Promise<string> {\n return hash('server-msg', threadRef, sourceDocId);\n}\n\n// ── chatSyncFanoutJobs ──────────────────────────────────────────────────────\n\nexport type SyncFanoutSelectorKind = 'channelMembers' | 'workChannelsForUser' | 'policyEditAffectedUsers';\n\n/**\n * `scopeKey` = `channelKey` for channelMembers/policyEditAffectedUsers, or\n * `userWorkScopeKey(uid, workProjectId)` for workChannelsForUser. `causeVersion`\n * = the channel's post-mutation configVersion, or the user's post-mutation\n * guildAuthInputVersion respectively.\n */\nexport function chatSyncFanoutJobId(\n selectorKind: SyncFanoutSelectorKind,\n scopeKey: string,\n causeVersion: number,\n): Promise<string> {\n return hash('chat-sync-fanout', selectorKind, scopeKey, causeVersion);\n}\n\n// ── Inbox projection eventId ────────────────────────────────────────────────\n\nexport function inboxProjectionEventId(\n channelKeyHash: string,\n recipientUid: string,\n kind: string,\n sourceVersion: number,\n): Promise<string> {\n return hash('chat-inbox-event', channelKeyHash, recipientUid, kind, sourceVersion);\n}\n\n// ── Notification ledger / archive ───────────────────────────────────────────\n\n/** Delivery-ledger row id. Shared-admin occurrences pass `recipientUid = null` (hashed as `'shared'`). */\nexport function notificationDeliveryId(\n recipientUid: string | null,\n notificationType: string,\n eventId: string,\n): Promise<string> {\n return hash('notif-delivery', recipientUid ?? 'shared', notificationType, eventId);\n}\n\n/** Archive history doc id (= `archiveOccurrenceId`). */\nexport function notificationArchiveHistoryId(\n category: string,\n audienceScope: string,\n requestId: string,\n): Promise<string> {\n return hash('notification-archive', category, audienceScope, requestId);\n}\n\n/** Archive replay-vs-conflict discriminator. */\nexport function notificationArchivePayloadHash(\n activeId: string,\n observedActivityGeneration: string,\n category: string,\n audienceScope: string,\n): Promise<string> {\n return hash('notification-archive-payload', activeId, observedActivityGeneration, category, audienceScope);\n}\n\n// ── Moderation audit ids (append-only; create-if-absent) ────────────────────\n\nexport function moderationRequestedAuditId(requestId: string): Promise<string> {\n return hash('chat-moderation-requested', requestId);\n}\nexport function moderationAppliedAuditId(requestId: string, resultingMessageRevision: number): Promise<string> {\n return hash('chat-moderation-applied', requestId, resultingMessageRevision);\n}\nexport function moderationFailedAuditId(requestId: string, terminalFailureGeneration: number): Promise<string> {\n return hash('chat-moderation-failed', requestId, terminalFailureGeneration);\n}\n\n// ── History anonymization ───────────────────────────────────────────────────\n\nexport function chatAnonymizeJobId(channelDoId: string, epoch: number, anonymizedUid: string): Promise<string> {\n return hash('chat-anonymize', channelDoId, epoch, anonymizedUid);\n}\n"]}
@@ -36,13 +36,6 @@ export declare const ThresholdLibraryApprovedEventSchema: z.ZodObject<{
36
36
  hallItemId: z.ZodString;
37
37
  }, z.core.$strict>;
38
38
  }, z.core.$strict>;
39
- export declare const ThresholdLibraryRejectedEventSchema: z.ZodObject<{
40
- type: z.ZodLiteral<"thresholdLibrary.rejected">;
41
- ids: z.ZodObject<{
42
- thresholdItemId: z.ZodString;
43
- hallItemId: z.ZodString;
44
- }, z.core.$strict>;
45
- }, z.core.$strict>;
46
39
  export declare const ThresholdLibraryNeedsRevisionEventSchema: z.ZodObject<{
47
40
  type: z.ZodLiteral<"thresholdLibrary.needsRevision">;
48
41
  ids: z.ZodObject<{
@@ -1 +1 @@
1
- {"version":3,"file":"domain-events-admin.d.ts","sourceRoot":"","sources":["../../src/media/domain-events-admin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,eAAO,MAAM,qCAAqC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAYvC,CAAC;AAEZ,eAAO,MAAM,mCAAmC;;;;;;kBAUrC,CAAC;AAEZ,eAAO,MAAM,mCAAmC;;;;;;kBAUrC,CAAC;AAEZ,eAAO,MAAM,wCAAwC;;;;;;kBAU1C,CAAC;AAEZ,eAAO,MAAM,oCAAoC;;;;;kBAStC,CAAC;AAEZ,eAAO,MAAM,qCAAqC;;;;;kBASvC,CAAC;AAEZ,eAAO,MAAM,8BAA8B;;;;;;kBAUhC,CAAC;AAEZ,eAAO,MAAM,gCAAgC;;;kBAKlC,CAAC;AAEZ,eAAO,MAAM,mCAAmC;;;;;;kBAUrC,CAAC"}
1
+ {"version":3,"file":"domain-events-admin.d.ts","sourceRoot":"","sources":["../../src/media/domain-events-admin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,eAAO,MAAM,qCAAqC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAYvC,CAAC;AAEZ,eAAO,MAAM,mCAAmC;;;;;;kBAUrC,CAAC;AAEZ,eAAO,MAAM,wCAAwC;;;;;;kBAU1C,CAAC;AAEZ,eAAO,MAAM,oCAAoC;;;;;kBAStC,CAAC;AAEZ,eAAO,MAAM,qCAAqC;;;;;kBASvC,CAAC;AAEZ,eAAO,MAAM,8BAA8B;;;;;;kBAUhC,CAAC;AAEZ,eAAO,MAAM,gCAAgC;;;kBAKlC,CAAC;AAEZ,eAAO,MAAM,mCAAmC;;;;;;kBAUrC,CAAC"}
@@ -27,17 +27,6 @@ export const ThresholdLibraryApprovedEventSchema = z
27
27
  .strict(),
28
28
  })
29
29
  .strict();
30
- export const ThresholdLibraryRejectedEventSchema = z
31
- .object({
32
- type: z.literal('thresholdLibrary.rejected'),
33
- ids: z
34
- .object({
35
- thresholdItemId: z.string().min(1),
36
- hallItemId: z.string().min(1),
37
- })
38
- .strict(),
39
- })
40
- .strict();
41
30
  export const ThresholdLibraryNeedsRevisionEventSchema = z
42
31
  .object({
43
32
  type: z.literal('thresholdLibrary.needsRevision'),
@@ -1 +1 @@
1
- {"version":3,"file":"domain-events-admin.js","sourceRoot":"","sources":["../../src/media/domain-events-admin.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\nimport { FileOriginSchema } from \"./file-origin.js\";\n\n// DomainEvent schemas for the admin/moderation domain — content violations,\n// threshold-library review decisions, admin dispatch, and appeals. Assembled\n// into the discriminated union in ./domain-events.ts.\n\nexport const ModerationViolationCreatedEventSchema = z\n .object({\n type: z.literal('moderation.violationCreated'),\n ids: z\n .object({\n userId: z.string().min(1),\n violationId: z.string().min(1),\n fileOrigin: FileOriginSchema,\n pendingMediaId: z.string().min(1),\n })\n .strict(),\n })\n .strict();\n\nexport const ThresholdLibraryApprovedEventSchema = z\n .object({\n type: z.literal('thresholdLibrary.approved'),\n ids: z\n .object({\n thresholdItemId: z.string().min(1),\n hallItemId: z.string().min(1),\n })\n .strict(),\n })\n .strict();\n\nexport const ThresholdLibraryRejectedEventSchema = z\n .object({\n type: z.literal('thresholdLibrary.rejected'),\n ids: z\n .object({\n thresholdItemId: z.string().min(1),\n hallItemId: z.string().min(1),\n })\n .strict(),\n })\n .strict();\n\nexport const ThresholdLibraryNeedsRevisionEventSchema = z\n .object({\n type: z.literal('thresholdLibrary.needsRevision'),\n ids: z\n .object({\n thresholdItemId: z.string().min(1),\n hallItemId: z.string().min(1),\n })\n .strict(),\n })\n .strict();\n\nexport const AdminDispatchSystemMarkedEventSchema = z\n .object({\n type: z.literal('adminDispatch.systemMarked'),\n ids: z\n .object({\n userId: z.string().min(1),\n })\n .strict(),\n })\n .strict();\n\nexport const AdminDispatchThreadUpdatedEventSchema = z\n .object({\n type: z.literal('adminDispatch.threadUpdated'),\n ids: z\n .object({\n adminDispatchId: z.string().min(1).nullable(),\n })\n .strict(),\n })\n .strict();\n\nexport const AdminAppealReviewedEventSchema = z\n .object({\n type: z.literal('admin.appealReviewed'),\n ids: z\n .object({\n violationId: z.string().min(1),\n userId: z.string().min(1),\n })\n .strict(),\n })\n .strict();\n\nexport const AdminDispatchReviewedEventSchema = z\n .object({\n type: z.literal('admin.adminDispatchReviewed'),\n ids: z.object({}).strict(),\n })\n .strict();\n\nexport const ViolationAppealSubmittedEventSchema = z\n .object({\n type: z.literal('violation.appealSubmitted'),\n ids: z\n .object({\n userId: z.string().min(1),\n violationId: z.string().min(1),\n })\n .strict(),\n })\n .strict();\n"]}
1
+ {"version":3,"file":"domain-events-admin.js","sourceRoot":"","sources":["../../src/media/domain-events-admin.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\nimport { FileOriginSchema } from \"./file-origin.js\";\n\n// DomainEvent schemas for the admin/moderation domain — content violations,\n// threshold-library review decisions, admin dispatch, and appeals. Assembled\n// into the discriminated union in ./domain-events.ts.\n\nexport const ModerationViolationCreatedEventSchema = z\n .object({\n type: z.literal('moderation.violationCreated'),\n ids: z\n .object({\n userId: z.string().min(1),\n violationId: z.string().min(1),\n fileOrigin: FileOriginSchema,\n pendingMediaId: z.string().min(1),\n })\n .strict(),\n })\n .strict();\n\nexport const ThresholdLibraryApprovedEventSchema = z\n .object({\n type: z.literal('thresholdLibrary.approved'),\n ids: z\n .object({\n thresholdItemId: z.string().min(1),\n hallItemId: z.string().min(1),\n })\n .strict(),\n })\n .strict();\n\nexport const ThresholdLibraryNeedsRevisionEventSchema = z\n .object({\n type: z.literal('thresholdLibrary.needsRevision'),\n ids: z\n .object({\n thresholdItemId: z.string().min(1),\n hallItemId: z.string().min(1),\n })\n .strict(),\n })\n .strict();\n\nexport const AdminDispatchSystemMarkedEventSchema = z\n .object({\n type: z.literal('adminDispatch.systemMarked'),\n ids: z\n .object({\n userId: z.string().min(1),\n })\n .strict(),\n })\n .strict();\n\nexport const AdminDispatchThreadUpdatedEventSchema = z\n .object({\n type: z.literal('adminDispatch.threadUpdated'),\n ids: z\n .object({\n adminDispatchId: z.string().min(1).nullable(),\n })\n .strict(),\n })\n .strict();\n\nexport const AdminAppealReviewedEventSchema = z\n .object({\n type: z.literal('admin.appealReviewed'),\n ids: z\n .object({\n violationId: z.string().min(1),\n userId: z.string().min(1),\n })\n .strict(),\n })\n .strict();\n\nexport const AdminDispatchReviewedEventSchema = z\n .object({\n type: z.literal('admin.adminDispatchReviewed'),\n ids: z.object({}).strict(),\n })\n .strict();\n\nexport const ViolationAppealSubmittedEventSchema = z\n .object({\n type: z.literal('violation.appealSubmitted'),\n ids: z\n .object({\n userId: z.string().min(1),\n violationId: z.string().min(1),\n })\n .strict(),\n })\n .strict();\n"]}
@@ -261,12 +261,6 @@ export declare const DomainEventSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
261
261
  thresholdItemId: z.ZodString;
262
262
  hallItemId: z.ZodString;
263
263
  }, z.core.$strict>;
264
- }, z.core.$strict>, z.ZodObject<{
265
- type: z.ZodLiteral<"thresholdLibrary.rejected">;
266
- ids: z.ZodObject<{
267
- thresholdItemId: z.ZodString;
268
- hallItemId: z.ZodString;
269
- }, z.core.$strict>;
270
264
  }, z.core.$strict>, z.ZodObject<{
271
265
  type: z.ZodLiteral<"thresholdLibrary.needsRevision">;
272
266
  ids: z.ZodObject<{
@@ -1 +1 @@
1
- {"version":3,"file":"domain-events.d.ts","sourceRoot":"","sources":["../../src/media/domain-events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAqDxB,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AAgBzC,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BA4C5B,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAI5D,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,WAAW,CAAC,MAAM,CAAC,IAAI,OAAO,CACpE,WAAW,EACX;IAAE,IAAI,EAAE,CAAC,CAAA;CAAE,CACZ,CAAC,KAAK,CAAC,CAAC"}
1
+ {"version":3,"file":"domain-events.d.ts","sourceRoot":"","sources":["../../src/media/domain-events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAoDxB,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AAgBzC,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BA2C5B,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAI5D,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,WAAW,CAAC,MAAM,CAAC,IAAI,OAAO,CACpE,WAAW,EACX;IAAE,IAAI,EAAE,CAAC,CAAA;CAAE,CACZ,CAAC,KAAK,CAAC,CAAC"}
@@ -2,7 +2,7 @@ import { z } from "zod";
2
2
  import { ProfilePictureUpdatedEventSchema, ProfilePreferencesUpdatedEventSchema, CraftSkillCreatedEventSchema, CraftSkillUpdatedEventSchema, CraftSkillDeletedEventSchema, FollowCreatedEventSchema, FollowRemovedEventSchema, MentionReadEventSchema, AuthStatusChangedEventSchema, } from "./domain-events-user.js";
3
3
  import { WorkProjectCreatedEventSchema, WorkProjectUpdatedEventSchema, WorkProjectPublishedEventSchema, WorkProjectStakeSharesUpdatedEventSchema, GuildInviteSentEventSchema, GuildInviteAcceptedEventSchema, GuildInviteDeclinedEventSchema, GuildInviteCancelledEventSchema, AuditionPromptCreatedEventSchema, AuditionEntrySubmittedEventSchema, AuditionEntryVoteRecordedEventSchema, AuditionClosedEventSchema, CommissionCreatedEventSchema, CommissionProposalSubmittedEventSchema, CommissionDeletedEventSchema, CommissionProposalSavedEventSchema, CommissionProposalRemovedEventSchema, HallLibraryCoverUpdatedEventSchema, WorkRealmCoverUpdatedEventSchema, HallLibrarySubItemUpdatedEventSchema, ThresholdLibrarySubmittedEventSchema, } from "./domain-events-work.js";
4
4
  import { SquareStreetzPostCreatedEventSchema, SquareStreetzPostLikedEventSchema, SquareStreetzPostUnlikedEventSchema, ChatAttachmentFinalizedEventSchema, } from "./domain-events-social.js";
5
- import { ModerationViolationCreatedEventSchema, ThresholdLibraryApprovedEventSchema, ThresholdLibraryRejectedEventSchema, ThresholdLibraryNeedsRevisionEventSchema, AdminDispatchSystemMarkedEventSchema, AdminDispatchThreadUpdatedEventSchema, AdminAppealReviewedEventSchema, AdminDispatchReviewedEventSchema, ViolationAppealSubmittedEventSchema, } from "./domain-events-admin.js";
5
+ import { ModerationViolationCreatedEventSchema, ThresholdLibraryApprovedEventSchema, ThresholdLibraryNeedsRevisionEventSchema, AdminDispatchSystemMarkedEventSchema, AdminDispatchThreadUpdatedEventSchema, AdminAppealReviewedEventSchema, AdminDispatchReviewedEventSchema, ViolationAppealSubmittedEventSchema, } from "./domain-events-admin.js";
6
6
  export * from "./domain-events-user.js";
7
7
  export * from "./domain-events-work.js";
8
8
  export * from "./domain-events-social.js";
@@ -55,7 +55,6 @@ export const DomainEventSchema = z.discriminatedUnion('type', [
55
55
  CommissionProposalRemovedEventSchema,
56
56
  ThresholdLibrarySubmittedEventSchema,
57
57
  ThresholdLibraryApprovedEventSchema,
58
- ThresholdLibraryRejectedEventSchema,
59
58
  ThresholdLibraryNeedsRevisionEventSchema,
60
59
  AdminDispatchSystemMarkedEventSchema,
61
60
  AdminDispatchThreadUpdatedEventSchema,
@@ -1 +1 @@
1
- {"version":3,"file":"domain-events.js","sourceRoot":"","sources":["../../src/media/domain-events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,gCAAgC,EAChC,oCAAoC,EACpC,4BAA4B,EAC5B,4BAA4B,EAC5B,4BAA4B,EAC5B,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,4BAA4B,GAC7B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,6BAA6B,EAC7B,6BAA6B,EAC7B,+BAA+B,EAC/B,wCAAwC,EACxC,0BAA0B,EAC1B,8BAA8B,EAC9B,8BAA8B,EAC9B,+BAA+B,EAC/B,gCAAgC,EAChC,iCAAiC,EACjC,oCAAoC,EACpC,yBAAyB,EACzB,4BAA4B,EAC5B,sCAAsC,EACtC,4BAA4B,EAC5B,kCAAkC,EAClC,oCAAoC,EACpC,kCAAkC,EAClC,gCAAgC,EAChC,oCAAoC,EACpC,oCAAoC,GACrC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,mCAAmC,EACnC,iCAAiC,EACjC,mCAAmC,EACnC,kCAAkC,GACnC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,qCAAqC,EACrC,mCAAmC,EACnC,mCAAmC,EACnC,wCAAwC,EACxC,oCAAoC,EACpC,qCAAqC,EACrC,8BAA8B,EAC9B,gCAAgC,EAChC,mCAAmC,GACpC,MAAM,0BAA0B,CAAC;AAElC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AAEzC,+EAA+E;AAC/E,uEAAuE;AACvE,6EAA6E;AAC7E,gEAAgE;AAChE,EAAE;AACF,gDAAgD;AAChD,0CAA0C;AAC1C,iDAAiD;AACjD,mEAAmE;AACnE,EAAE;AACF,0EAA0E;AAC1E,mEAAmE;AACnE,+EAA+E;AAE/E,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IAC5D,gCAAgC;IAChC,4BAA4B;IAC5B,mCAAmC;IACnC,gCAAgC;IAChC,iCAAiC;IACjC,4BAA4B;IAC5B,sCAAsC;IACtC,6BAA6B;IAC7B,kCAAkC;IAClC,gCAAgC;IAChC,oCAAoC;IACpC,qCAAqC;IACrC,kCAAkC;IAClC,wBAAwB;IACxB,wBAAwB;IACxB,iCAAiC;IACjC,mCAAmC;IACnC,oCAAoC;IACpC,4BAA4B;IAC5B,4BAA4B;IAC5B,6BAA6B;IAC7B,+BAA+B;IAC/B,wCAAwC;IACxC,0BAA0B;IAC1B,8BAA8B;IAC9B,8BAA8B;IAC9B,+BAA+B;IAC/B,oCAAoC;IACpC,yBAAyB;IACzB,4BAA4B;IAC5B,kCAAkC;IAClC,oCAAoC;IACpC,oCAAoC;IACpC,mCAAmC;IACnC,mCAAmC;IACnC,wCAAwC;IACxC,oCAAoC;IACpC,qCAAqC;IACrC,8BAA8B;IAC9B,gCAAgC;IAChC,sBAAsB;IACtB,4BAA4B;IAC5B,mCAAmC;CACpC,CAAC,CAAC","sourcesContent":["import { z } from \"zod\";\nimport {\n ProfilePictureUpdatedEventSchema,\n ProfilePreferencesUpdatedEventSchema,\n CraftSkillCreatedEventSchema,\n CraftSkillUpdatedEventSchema,\n CraftSkillDeletedEventSchema,\n FollowCreatedEventSchema,\n FollowRemovedEventSchema,\n MentionReadEventSchema,\n AuthStatusChangedEventSchema,\n} from \"./domain-events-user.js\";\nimport {\n WorkProjectCreatedEventSchema,\n WorkProjectUpdatedEventSchema,\n WorkProjectPublishedEventSchema,\n WorkProjectStakeSharesUpdatedEventSchema,\n GuildInviteSentEventSchema,\n GuildInviteAcceptedEventSchema,\n GuildInviteDeclinedEventSchema,\n GuildInviteCancelledEventSchema,\n AuditionPromptCreatedEventSchema,\n AuditionEntrySubmittedEventSchema,\n AuditionEntryVoteRecordedEventSchema,\n AuditionClosedEventSchema,\n CommissionCreatedEventSchema,\n CommissionProposalSubmittedEventSchema,\n CommissionDeletedEventSchema,\n CommissionProposalSavedEventSchema,\n CommissionProposalRemovedEventSchema,\n HallLibraryCoverUpdatedEventSchema,\n WorkRealmCoverUpdatedEventSchema,\n HallLibrarySubItemUpdatedEventSchema,\n ThresholdLibrarySubmittedEventSchema,\n} from \"./domain-events-work.js\";\nimport {\n SquareStreetzPostCreatedEventSchema,\n SquareStreetzPostLikedEventSchema,\n SquareStreetzPostUnlikedEventSchema,\n ChatAttachmentFinalizedEventSchema,\n} from \"./domain-events-social.js\";\nimport {\n ModerationViolationCreatedEventSchema,\n ThresholdLibraryApprovedEventSchema,\n ThresholdLibraryRejectedEventSchema,\n ThresholdLibraryNeedsRevisionEventSchema,\n AdminDispatchSystemMarkedEventSchema,\n AdminDispatchThreadUpdatedEventSchema,\n AdminAppealReviewedEventSchema,\n AdminDispatchReviewedEventSchema,\n ViolationAppealSubmittedEventSchema,\n} from \"./domain-events-admin.js\";\n\nexport * from \"./domain-events-user.js\";\nexport * from \"./domain-events-work.js\";\nexport * from \"./domain-events-social.js\";\nexport * from \"./domain-events-admin.js\";\n\n// ============================================================================\n// DomainEvent — typed business actions emitted by mutations and upload\n// processors. The frontend registry (ttt-prod/src/lib/domain-events.ts) maps\n// each variant to a list of TanStack Query cache invalidations.\n//\n// Adding a new variant is a coordinated deploy:\n// 1. Add it here. Publish this package.\n// 2. Add a registry entry in ttt-prod. Deploy.\n// 3. Update producers (mutation hooks or processors) to emit it.\n//\n// The schema is .strict() end-to-end — unknown event types fail parse and\n// the consuming hook in ttt-prod logs to Sentry and skips the doc.\n// ============================================================================\n\nexport const DomainEventSchema = z.discriminatedUnion('type', [\n ProfilePictureUpdatedEventSchema,\n CraftSkillCreatedEventSchema,\n SquareStreetzPostCreatedEventSchema,\n AuditionPromptCreatedEventSchema,\n AuditionEntrySubmittedEventSchema,\n CommissionCreatedEventSchema,\n CommissionProposalSubmittedEventSchema,\n WorkProjectUpdatedEventSchema,\n HallLibraryCoverUpdatedEventSchema,\n WorkRealmCoverUpdatedEventSchema,\n HallLibrarySubItemUpdatedEventSchema,\n ModerationViolationCreatedEventSchema,\n ChatAttachmentFinalizedEventSchema,\n FollowCreatedEventSchema,\n FollowRemovedEventSchema,\n SquareStreetzPostLikedEventSchema,\n SquareStreetzPostUnlikedEventSchema,\n ProfilePreferencesUpdatedEventSchema,\n CraftSkillDeletedEventSchema,\n CraftSkillUpdatedEventSchema,\n WorkProjectCreatedEventSchema,\n WorkProjectPublishedEventSchema,\n WorkProjectStakeSharesUpdatedEventSchema,\n GuildInviteSentEventSchema,\n GuildInviteAcceptedEventSchema,\n GuildInviteDeclinedEventSchema,\n GuildInviteCancelledEventSchema,\n AuditionEntryVoteRecordedEventSchema,\n AuditionClosedEventSchema,\n CommissionDeletedEventSchema,\n CommissionProposalSavedEventSchema,\n CommissionProposalRemovedEventSchema,\n ThresholdLibrarySubmittedEventSchema,\n ThresholdLibraryApprovedEventSchema,\n ThresholdLibraryRejectedEventSchema,\n ThresholdLibraryNeedsRevisionEventSchema,\n AdminDispatchSystemMarkedEventSchema,\n AdminDispatchThreadUpdatedEventSchema,\n AdminAppealReviewedEventSchema,\n AdminDispatchReviewedEventSchema,\n MentionReadEventSchema,\n AuthStatusChangedEventSchema,\n ViolationAppealSubmittedEventSchema,\n]);\n\nexport type DomainEvent = z.infer<typeof DomainEventSchema>;\n\n// Helper for callers that need to extract the ids type for a specific\n// event variant (e.g. registry entries in the consuming repo).\nexport type DomainEventIdsFor<T extends DomainEvent['type']> = Extract<\n DomainEvent,\n { type: T }\n>['ids'];\n\n\n\n\n\n"]}
1
+ {"version":3,"file":"domain-events.js","sourceRoot":"","sources":["../../src/media/domain-events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,gCAAgC,EAChC,oCAAoC,EACpC,4BAA4B,EAC5B,4BAA4B,EAC5B,4BAA4B,EAC5B,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,4BAA4B,GAC7B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,6BAA6B,EAC7B,6BAA6B,EAC7B,+BAA+B,EAC/B,wCAAwC,EACxC,0BAA0B,EAC1B,8BAA8B,EAC9B,8BAA8B,EAC9B,+BAA+B,EAC/B,gCAAgC,EAChC,iCAAiC,EACjC,oCAAoC,EACpC,yBAAyB,EACzB,4BAA4B,EAC5B,sCAAsC,EACtC,4BAA4B,EAC5B,kCAAkC,EAClC,oCAAoC,EACpC,kCAAkC,EAClC,gCAAgC,EAChC,oCAAoC,EACpC,oCAAoC,GACrC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,mCAAmC,EACnC,iCAAiC,EACjC,mCAAmC,EACnC,kCAAkC,GACnC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,qCAAqC,EACrC,mCAAmC,EACnC,wCAAwC,EACxC,oCAAoC,EACpC,qCAAqC,EACrC,8BAA8B,EAC9B,gCAAgC,EAChC,mCAAmC,GACpC,MAAM,0BAA0B,CAAC;AAElC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AAEzC,+EAA+E;AAC/E,uEAAuE;AACvE,6EAA6E;AAC7E,gEAAgE;AAChE,EAAE;AACF,gDAAgD;AAChD,0CAA0C;AAC1C,iDAAiD;AACjD,mEAAmE;AACnE,EAAE;AACF,0EAA0E;AAC1E,mEAAmE;AACnE,+EAA+E;AAE/E,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IAC5D,gCAAgC;IAChC,4BAA4B;IAC5B,mCAAmC;IACnC,gCAAgC;IAChC,iCAAiC;IACjC,4BAA4B;IAC5B,sCAAsC;IACtC,6BAA6B;IAC7B,kCAAkC;IAClC,gCAAgC;IAChC,oCAAoC;IACpC,qCAAqC;IACrC,kCAAkC;IAClC,wBAAwB;IACxB,wBAAwB;IACxB,iCAAiC;IACjC,mCAAmC;IACnC,oCAAoC;IACpC,4BAA4B;IAC5B,4BAA4B;IAC5B,6BAA6B;IAC7B,+BAA+B;IAC/B,wCAAwC;IACxC,0BAA0B;IAC1B,8BAA8B;IAC9B,8BAA8B;IAC9B,+BAA+B;IAC/B,oCAAoC;IACpC,yBAAyB;IACzB,4BAA4B;IAC5B,kCAAkC;IAClC,oCAAoC;IACpC,oCAAoC;IACpC,mCAAmC;IACnC,wCAAwC;IACxC,oCAAoC;IACpC,qCAAqC;IACrC,8BAA8B;IAC9B,gCAAgC;IAChC,sBAAsB;IACtB,4BAA4B;IAC5B,mCAAmC;CACpC,CAAC,CAAC","sourcesContent":["import { z } from \"zod\";\nimport {\n ProfilePictureUpdatedEventSchema,\n ProfilePreferencesUpdatedEventSchema,\n CraftSkillCreatedEventSchema,\n CraftSkillUpdatedEventSchema,\n CraftSkillDeletedEventSchema,\n FollowCreatedEventSchema,\n FollowRemovedEventSchema,\n MentionReadEventSchema,\n AuthStatusChangedEventSchema,\n} from \"./domain-events-user.js\";\nimport {\n WorkProjectCreatedEventSchema,\n WorkProjectUpdatedEventSchema,\n WorkProjectPublishedEventSchema,\n WorkProjectStakeSharesUpdatedEventSchema,\n GuildInviteSentEventSchema,\n GuildInviteAcceptedEventSchema,\n GuildInviteDeclinedEventSchema,\n GuildInviteCancelledEventSchema,\n AuditionPromptCreatedEventSchema,\n AuditionEntrySubmittedEventSchema,\n AuditionEntryVoteRecordedEventSchema,\n AuditionClosedEventSchema,\n CommissionCreatedEventSchema,\n CommissionProposalSubmittedEventSchema,\n CommissionDeletedEventSchema,\n CommissionProposalSavedEventSchema,\n CommissionProposalRemovedEventSchema,\n HallLibraryCoverUpdatedEventSchema,\n WorkRealmCoverUpdatedEventSchema,\n HallLibrarySubItemUpdatedEventSchema,\n ThresholdLibrarySubmittedEventSchema,\n} from \"./domain-events-work.js\";\nimport {\n SquareStreetzPostCreatedEventSchema,\n SquareStreetzPostLikedEventSchema,\n SquareStreetzPostUnlikedEventSchema,\n ChatAttachmentFinalizedEventSchema,\n} from \"./domain-events-social.js\";\nimport {\n ModerationViolationCreatedEventSchema,\n ThresholdLibraryApprovedEventSchema,\n ThresholdLibraryNeedsRevisionEventSchema,\n AdminDispatchSystemMarkedEventSchema,\n AdminDispatchThreadUpdatedEventSchema,\n AdminAppealReviewedEventSchema,\n AdminDispatchReviewedEventSchema,\n ViolationAppealSubmittedEventSchema,\n} from \"./domain-events-admin.js\";\n\nexport * from \"./domain-events-user.js\";\nexport * from \"./domain-events-work.js\";\nexport * from \"./domain-events-social.js\";\nexport * from \"./domain-events-admin.js\";\n\n// ============================================================================\n// DomainEvent — typed business actions emitted by mutations and upload\n// processors. The frontend registry (ttt-prod/src/lib/domain-events.ts) maps\n// each variant to a list of TanStack Query cache invalidations.\n//\n// Adding a new variant is a coordinated deploy:\n// 1. Add it here. Publish this package.\n// 2. Add a registry entry in ttt-prod. Deploy.\n// 3. Update producers (mutation hooks or processors) to emit it.\n//\n// The schema is .strict() end-to-end — unknown event types fail parse and\n// the consuming hook in ttt-prod logs to Sentry and skips the doc.\n// ============================================================================\n\nexport const DomainEventSchema = z.discriminatedUnion('type', [\n ProfilePictureUpdatedEventSchema,\n CraftSkillCreatedEventSchema,\n SquareStreetzPostCreatedEventSchema,\n AuditionPromptCreatedEventSchema,\n AuditionEntrySubmittedEventSchema,\n CommissionCreatedEventSchema,\n CommissionProposalSubmittedEventSchema,\n WorkProjectUpdatedEventSchema,\n HallLibraryCoverUpdatedEventSchema,\n WorkRealmCoverUpdatedEventSchema,\n HallLibrarySubItemUpdatedEventSchema,\n ModerationViolationCreatedEventSchema,\n ChatAttachmentFinalizedEventSchema,\n FollowCreatedEventSchema,\n FollowRemovedEventSchema,\n SquareStreetzPostLikedEventSchema,\n SquareStreetzPostUnlikedEventSchema,\n ProfilePreferencesUpdatedEventSchema,\n CraftSkillDeletedEventSchema,\n CraftSkillUpdatedEventSchema,\n WorkProjectCreatedEventSchema,\n WorkProjectPublishedEventSchema,\n WorkProjectStakeSharesUpdatedEventSchema,\n GuildInviteSentEventSchema,\n GuildInviteAcceptedEventSchema,\n GuildInviteDeclinedEventSchema,\n GuildInviteCancelledEventSchema,\n AuditionEntryVoteRecordedEventSchema,\n AuditionClosedEventSchema,\n CommissionDeletedEventSchema,\n CommissionProposalSavedEventSchema,\n CommissionProposalRemovedEventSchema,\n ThresholdLibrarySubmittedEventSchema,\n ThresholdLibraryApprovedEventSchema,\n ThresholdLibraryNeedsRevisionEventSchema,\n AdminDispatchSystemMarkedEventSchema,\n AdminDispatchThreadUpdatedEventSchema,\n AdminAppealReviewedEventSchema,\n AdminDispatchReviewedEventSchema,\n MentionReadEventSchema,\n AuthStatusChangedEventSchema,\n ViolationAppealSubmittedEventSchema,\n]);\n\nexport type DomainEvent = z.infer<typeof DomainEventSchema>;\n\n// Helper for callers that need to extract the ids type for a specific\n// event variant (e.g. registry entries in the consuming repo).\nexport type DomainEventIdsFor<T extends DomainEvent['type']> = Extract<\n DomainEvent,\n { type: T }\n>['ids'];\n\n\n\n\n\n"]}
@@ -1,6 +1,6 @@
1
1
  // Server-side mapping from hallLibrary/sub-item fileOrigin to the doc field
2
2
  // that receives the processed media-asset reference (never a URL — see
3
- // docs/design/media-assets-and-protected-serving.md).
3
+ // ttt-prod docs/design/media-assets-and-protected-serving.md).
4
4
  //
5
5
  // Owned in ttt-core because it's a contract fact about the upload
6
6
  // pipeline — same tier as TTT_MEDIA_SPECS and PATH_BUILDERS. Frontend
@@ -1 +1 @@
1
- {"version":3,"file":"hall-library-target-fields.js","sourceRoot":"","sources":["../../src/media/hall-library-target-fields.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAC5E,uEAAuE;AACvE,sDAAsD;AACtD,EAAE;AACF,kEAAkE;AAClE,sEAAsE;AACtE,oEAAoE;AACpE,oDAAoD;AACpD,EAAE;AACF,qEAAqE;AACrE,qCAAqC;AACrC,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,0BAA0B,EAAK,oBAAoB;IACnD,0BAA0B,EAAK,oBAAoB;IACnD,6BAA6B,EAAE,uBAAuB;IACtD,eAAe,EAAY,cAAc;IACzC,kBAAkB,EAAe,cAAc;IAC/C,kBAAkB,EAAe,cAAc;IAC/C,0BAA0B,EAAe,cAAc;IACvD,0BAA0B,EAAe,cAAc;CACD,CAAC","sourcesContent":["import type { FileOrigin } from './file-origin.js';\n\n// Server-side mapping from hallLibrary/sub-item fileOrigin to the doc field\n// that receives the processed media-asset reference (never a URL — see\n// docs/design/media-assets-and-protected-serving.md).\n//\n// Owned in ttt-core because it's a contract fact about the upload\n// pipeline — same tier as TTT_MEDIA_SPECS and PATH_BUILDERS. Frontend\n// never reads this. Processors look the field up after deriving the\n// target doc path from the typed IDs in targetInfo.\n//\n// The Partial<Record<FileOrigin, string>> constraint guarantees only\n// valid FileOrigin strings are keys.\nexport const HALL_LIBRARY_TARGET_FIELDS = {\n 'hallLibrary-cover-square': 'coverSquareAssetId',\n 'hallLibrary-cover-poster': 'coverPosterAssetId',\n 'hallLibrary-cover-cinematic': 'coverCinematicAssetId',\n 'chapter-photo': 'photoAssetId',\n 'tune-track-photo': 'photoAssetId',\n 'tune-track-audio': 'audioAssetId',\n 'television-episode-photo': 'photoAssetId',\n 'television-episode-video': 'videoAssetId',\n} as const satisfies Partial<Record<FileOrigin, string>>;\n\nexport type HallLibraryFileOrigin = keyof typeof HALL_LIBRARY_TARGET_FIELDS;\nexport type HallLibraryTargetField = typeof HALL_LIBRARY_TARGET_FIELDS[HallLibraryFileOrigin];\n\n"]}
1
+ {"version":3,"file":"hall-library-target-fields.js","sourceRoot":"","sources":["../../src/media/hall-library-target-fields.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAC5E,uEAAuE;AACvE,+DAA+D;AAC/D,EAAE;AACF,kEAAkE;AAClE,sEAAsE;AACtE,oEAAoE;AACpE,oDAAoD;AACpD,EAAE;AACF,qEAAqE;AACrE,qCAAqC;AACrC,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,0BAA0B,EAAK,oBAAoB;IACnD,0BAA0B,EAAK,oBAAoB;IACnD,6BAA6B,EAAE,uBAAuB;IACtD,eAAe,EAAY,cAAc;IACzC,kBAAkB,EAAe,cAAc;IAC/C,kBAAkB,EAAe,cAAc;IAC/C,0BAA0B,EAAe,cAAc;IACvD,0BAA0B,EAAe,cAAc;CACD,CAAC","sourcesContent":["import type { FileOrigin } from './file-origin.js';\n\n// Server-side mapping from hallLibrary/sub-item fileOrigin to the doc field\n// that receives the processed media-asset reference (never a URL — see\n// ttt-prod docs/design/media-assets-and-protected-serving.md).\n//\n// Owned in ttt-core because it's a contract fact about the upload\n// pipeline — same tier as TTT_MEDIA_SPECS and PATH_BUILDERS. Frontend\n// never reads this. Processors look the field up after deriving the\n// target doc path from the typed IDs in targetInfo.\n//\n// The Partial<Record<FileOrigin, string>> constraint guarantees only\n// valid FileOrigin strings are keys.\nexport const HALL_LIBRARY_TARGET_FIELDS = {\n 'hallLibrary-cover-square': 'coverSquareAssetId',\n 'hallLibrary-cover-poster': 'coverPosterAssetId',\n 'hallLibrary-cover-cinematic': 'coverCinematicAssetId',\n 'chapter-photo': 'photoAssetId',\n 'tune-track-photo': 'photoAssetId',\n 'tune-track-audio': 'audioAssetId',\n 'television-episode-photo': 'photoAssetId',\n 'television-episode-video': 'videoAssetId',\n} as const satisfies Partial<Record<FileOrigin, string>>;\n\nexport type HallLibraryFileOrigin = keyof typeof HALL_LIBRARY_TARGET_FIELDS;\nexport type HallLibraryTargetField = typeof HALL_LIBRARY_TARGET_FIELDS[HallLibraryFileOrigin];\n\n"]}
@@ -266,12 +266,6 @@ export declare const PendingMediaResultSchema: z.ZodObject<{
266
266
  thresholdItemId: z.ZodString;
267
267
  hallItemId: z.ZodString;
268
268
  }, z.core.$strict>;
269
- }, z.core.$strict>, z.ZodObject<{
270
- type: z.ZodLiteral<"thresholdLibrary.rejected">;
271
- ids: z.ZodObject<{
272
- thresholdItemId: z.ZodString;
273
- hallItemId: z.ZodString;
274
- }, z.core.$strict>;
275
269
  }, z.core.$strict>, z.ZodObject<{
276
270
  type: z.ZodLiteral<"thresholdLibrary.needsRevision">;
277
271
  ids: z.ZodObject<{
@@ -693,12 +687,6 @@ export declare const PendingMediaCompletedSchema: z.ZodObject<{
693
687
  thresholdItemId: z.ZodString;
694
688
  hallItemId: z.ZodString;
695
689
  }, z.core.$strict>;
696
- }, z.core.$strict>, z.ZodObject<{
697
- type: z.ZodLiteral<"thresholdLibrary.rejected">;
698
- ids: z.ZodObject<{
699
- thresholdItemId: z.ZodString;
700
- hallItemId: z.ZodString;
701
- }, z.core.$strict>;
702
690
  }, z.core.$strict>, z.ZodObject<{
703
691
  type: z.ZodLiteral<"thresholdLibrary.needsRevision">;
704
692
  ids: z.ZodObject<{
@@ -1137,12 +1125,6 @@ export declare const PendingMediaRejectedSchema: z.ZodObject<{
1137
1125
  thresholdItemId: z.ZodString;
1138
1126
  hallItemId: z.ZodString;
1139
1127
  }, z.core.$strict>;
1140
- }, z.core.$strict>, z.ZodObject<{
1141
- type: z.ZodLiteral<"thresholdLibrary.rejected">;
1142
- ids: z.ZodObject<{
1143
- thresholdItemId: z.ZodString;
1144
- hallItemId: z.ZodString;
1145
- }, z.core.$strict>;
1146
1128
  }, z.core.$strict>, z.ZodObject<{
1147
1129
  type: z.ZodLiteral<"thresholdLibrary.needsRevision">;
1148
1130
  ids: z.ZodObject<{
@@ -1610,12 +1592,6 @@ export declare const PendingMediaSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1610
1592
  thresholdItemId: z.ZodString;
1611
1593
  hallItemId: z.ZodString;
1612
1594
  }, z.core.$strict>;
1613
- }, z.core.$strict>, z.ZodObject<{
1614
- type: z.ZodLiteral<"thresholdLibrary.rejected">;
1615
- ids: z.ZodObject<{
1616
- thresholdItemId: z.ZodString;
1617
- hallItemId: z.ZodString;
1618
- }, z.core.$strict>;
1619
1595
  }, z.core.$strict>, z.ZodObject<{
1620
1596
  type: z.ZodLiteral<"thresholdLibrary.needsRevision">;
1621
1597
  ids: z.ZodObject<{
@@ -2052,12 +2028,6 @@ export declare const PendingMediaSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
2052
2028
  thresholdItemId: z.ZodString;
2053
2029
  hallItemId: z.ZodString;
2054
2030
  }, z.core.$strict>;
2055
- }, z.core.$strict>, z.ZodObject<{
2056
- type: z.ZodLiteral<"thresholdLibrary.rejected">;
2057
- ids: z.ZodObject<{
2058
- thresholdItemId: z.ZodString;
2059
- hallItemId: z.ZodString;
2060
- }, z.core.$strict>;
2061
2031
  }, z.core.$strict>, z.ZodObject<{
2062
2032
  type: z.ZodLiteral<"thresholdLibrary.needsRevision">;
2063
2033
  ids: z.ZodObject<{
@@ -2425,12 +2395,6 @@ export declare const ArchivedPendingMediaCompletedSchema: z.ZodObject<{
2425
2395
  thresholdItemId: z.ZodString;
2426
2396
  hallItemId: z.ZodString;
2427
2397
  }, z.core.$strict>;
2428
- }, z.core.$strict>, z.ZodObject<{
2429
- type: z.ZodLiteral<"thresholdLibrary.rejected">;
2430
- ids: z.ZodObject<{
2431
- thresholdItemId: z.ZodString;
2432
- hallItemId: z.ZodString;
2433
- }, z.core.$strict>;
2434
2398
  }, z.core.$strict>, z.ZodObject<{
2435
2399
  type: z.ZodLiteral<"thresholdLibrary.needsRevision">;
2436
2400
  ids: z.ZodObject<{
@@ -2871,12 +2835,6 @@ export declare const ArchivedPendingMediaRejectedSchema: z.ZodObject<{
2871
2835
  thresholdItemId: z.ZodString;
2872
2836
  hallItemId: z.ZodString;
2873
2837
  }, z.core.$strict>;
2874
- }, z.core.$strict>, z.ZodObject<{
2875
- type: z.ZodLiteral<"thresholdLibrary.rejected">;
2876
- ids: z.ZodObject<{
2877
- thresholdItemId: z.ZodString;
2878
- hallItemId: z.ZodString;
2879
- }, z.core.$strict>;
2880
2838
  }, z.core.$strict>, z.ZodObject<{
2881
2839
  type: z.ZodLiteral<"thresholdLibrary.needsRevision">;
2882
2840
  ids: z.ZodObject<{
@@ -3245,12 +3203,6 @@ export declare const ArchivedPendingMediaSchema: z.ZodDiscriminatedUnion<[z.ZodO
3245
3203
  thresholdItemId: z.ZodString;
3246
3204
  hallItemId: z.ZodString;
3247
3205
  }, z.core.$strict>;
3248
- }, z.core.$strict>, z.ZodObject<{
3249
- type: z.ZodLiteral<"thresholdLibrary.rejected">;
3250
- ids: z.ZodObject<{
3251
- thresholdItemId: z.ZodString;
3252
- hallItemId: z.ZodString;
3253
- }, z.core.$strict>;
3254
3206
  }, z.core.$strict>, z.ZodObject<{
3255
3207
  type: z.ZodLiteral<"thresholdLibrary.needsRevision">;
3256
3208
  ids: z.ZodObject<{
@@ -3689,12 +3641,6 @@ export declare const ArchivedPendingMediaSchema: z.ZodDiscriminatedUnion<[z.ZodO
3689
3641
  thresholdItemId: z.ZodString;
3690
3642
  hallItemId: z.ZodString;
3691
3643
  }, z.core.$strict>;
3692
- }, z.core.$strict>, z.ZodObject<{
3693
- type: z.ZodLiteral<"thresholdLibrary.rejected">;
3694
- ids: z.ZodObject<{
3695
- thresholdItemId: z.ZodString;
3696
- hallItemId: z.ZodString;
3697
- }, z.core.$strict>;
3698
3644
  }, z.core.$strict>, z.ZodObject<{
3699
3645
  type: z.ZodLiteral<"thresholdLibrary.needsRevision">;
3700
3646
  ids: z.ZodObject<{
@@ -1 +1 @@
1
- {"version":3,"file":"pending-media.d.ts","sourceRoot":"","sources":["../../src/media/pending-media.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAS7B,eAAO,MAAM,+BAA+B;;;;;;;EAA0C,CAAC;AACvF,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAmC,CAAC;AACzE,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAoC,CAAC;AAC3E,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAuC,CAAC;AACjF,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAsC,CAAC;AAC/E,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAmC,CAAC;AACzE,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAqC,CAAC;AAC7E,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
1
+ {"version":3,"file":"pending-media.d.ts","sourceRoot":"","sources":["../../src/media/pending-media.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAS7B,eAAO,MAAM,+BAA+B;;;;;;;EAA0C,CAAC;AACvF,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAmC,CAAC;AACzE,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAoC,CAAC;AAC3E,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAuC,CAAC;AACjF,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAsC,CAAC;AAC/E,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAmC,CAAC;AACzE,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAAqC,CAAC;AAC7E,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
@@ -1 +1 @@
1
- {"version":3,"file":"photodna-coverage.d.ts","sourceRoot":"","sources":["../../src/media/photodna-coverage.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGrE;;;;;;;;GAQG;AACH,MAAM,MAAM,sBAAsB,GAC9B,eAAe,GACf,oBAAoB,GACpB,iBAAiB,CAAC;AAkCtB;;;;GAIG;AACH,wBAAgB,iCAAiC,CAC/C,MAAM,EAAE,UAAU,GACjB,sBAAsB,EAAE,CAO1B;AAED,yDAAyD;AACzD,MAAM,WAAW,qBAAqB;IACpC,qFAAqF;IACrF,QAAQ,CAAC,aAAa,EAAE,SAAS,SAAS,EAAE,CAAC;IAC7C,wEAAwE;IACxE,QAAQ,CAAC,gBAAgB,EAAE,SAAS,sBAAsB,EAAE,CAAC;CAC9D;AAED;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,UAAU,EAAE,qBAAqB,CAO1B,CAAC;AAEtD;;;;;;;;;;;GAWG;AACH,wBAAgB,oCAAoC,CAClD,UAAU,EAAE,SAAS,GACpB,sBAAsB,GAAG,IAAI,CAI/B"}
1
+ {"version":3,"file":"photodna-coverage.d.ts","sourceRoot":"","sources":["../../src/media/photodna-coverage.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGrE;;;;;;;;GAQG;AACH,MAAM,MAAM,sBAAsB,GAC9B,eAAe,GACf,oBAAoB,GACpB,iBAAiB,CAAC;AAkCtB;;;;GAIG;AACH,wBAAgB,iCAAiC,CAC/C,MAAM,EAAE,UAAU,GACjB,sBAAsB,EAAE,CAO1B;AAED,yDAAyD;AACzD,MAAM,WAAW,qBAAqB;IACpC,qFAAqF;IACrF,QAAQ,CAAC,aAAa,EAAE,SAAS,SAAS,EAAE,CAAC;IAC7C,wEAAwE;IACxE,QAAQ,CAAC,gBAAgB,EAAE,SAAS,sBAAsB,EAAE,CAAC;CAC9D;AAED;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,UAAU,EAAE,qBAAqB,CAO1B,CAAC;AAEtD;;;;;;;;;;;GAWG;AACH,wBAAgB,oCAAoC,CAClD,UAAU,EAAE,SAAS,GACpB,sBAAsB,GAAG,IAAI,CAI/B"}
@@ -1,6 +1,8 @@
1
- // PhotoDNA coverage matrix (IMPLEMENTATION_PLAN.md Appendix A §A10 — Finding-M3,
2
- // decision-free algorithm). The CI coverage test and the runtime router are BOTH
3
- // derived from this module so they cannot drift from `TTT_MEDIA_SPECS`.
1
+ // PhotoDNA coverage matrix (frozen Trust & Safety spec, Appendix A §A10 —
2
+ // Finding-M3, decision-free algorithm; durable design owner: ttt-prod
3
+ // docs/design/csam-detection-and-response.md). The CI coverage test and the
4
+ // runtime router are BOTH derived from this module so they cannot drift from
5
+ // `TTT_MEDIA_SPECS`.
4
6
  //
5
7
  // The source of truth for what a media origin accepts is
6
8
  // `TTT_MEDIA_SPECS[origin].accept.kinds`, NOT the top-level `spec.kind` (which
@@ -1 +1 @@
1
- {"version":3,"file":"photodna-coverage.js","sourceRoot":"","sources":["../../src/media/photodna-coverage.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,iFAAiF;AACjF,wEAAwE;AACxE,EAAE;AACF,yDAAyD;AACzD,+EAA+E;AAC/E,+DAA+D;AAC/D,+EAA+E;AAC/E,iFAAiF;AACjF,+EAA+E;AAC/E,4DAA4D;AAG5D,OAAO,EAAE,gBAAgB,EAAmB,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAuBvD;;;;;GAKG;AACH,MAAM,uBAAuB,GAAwD;IACnF,KAAK,EAAE,eAAe;IACtB,KAAK,EAAE,oBAAoB;IAC3B,KAAK,EAAE,iBAAiB;CACzB,CAAC;AAEF,MAAM,sBAAsB,GAAG,MAAM,CAAC,IAAI,CACxC,uBAAuB,CACC,CAAC;AAE3B,SAAS,qBAAqB,CAAC,IAAe;IAC5C,OAAQ,sBAAsC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAChE,CAAC;AAED,2EAA2E;AAC3E,SAAS,sBAAsB,CAAC,MAAkB;IAChD,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC;AACrD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iCAAiC,CAC/C,MAAkB;IAElB,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;IACtD,+EAA+E;IAC/E,sEAAsE;IACtE,OAAO,sBAAsB,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CACjE,CAAC,IAAI,EAAE,EAAE,CAAC,uBAAuB,CAAC,IAAI,CAAC,CACxC,CAAC;AACJ,CAAC;AAUD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GACnC,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE;IACjD,MAAM,CAAC,MAAM,CAAC,GAAG;QACf,aAAa,EAAE,sBAAsB,CAAC,MAAM,CAAC;QAC7C,gBAAgB,EAAE,iCAAiC,CAAC,MAAM,CAAC;KAC5D,CAAC;IACF,OAAO,MAAM,CAAC;AAChB,CAAC,EAAE,EAA+C,CAAC,CAAC;AAEtD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oCAAoC,CAClD,UAAqB;IAErB,OAAO,qBAAqB,CAAC,UAAU,CAAC;QACtC,CAAC,CAAC,uBAAuB,CAAC,UAAU,CAAC;QACrC,CAAC,CAAC,IAAI,CAAC;AACX,CAAC","sourcesContent":["// PhotoDNA coverage matrix (IMPLEMENTATION_PLAN.md Appendix A §A10 — Finding-M3,\n// decision-free algorithm). The CI coverage test and the runtime router are BOTH\n// derived from this module so they cannot drift from `TTT_MEDIA_SPECS`.\n//\n// The source of truth for what a media origin accepts is\n// `TTT_MEDIA_SPECS[origin].accept.kinds`, NOT the top-level `spec.kind` (which\n// mislabels `craft-skill-media`/`squareStreetz` as 'image' and\n// `guild-chat-message-attachment`/`work-asset` as 'generic', although all four\n// accept image+video+audio). Nothing here is hard-coded per-origin — every entry\n// is computed from the registry, so a new accepted kind on any origin fails CI\n// (via photodna-coverage.test.ts) until a branch covers it.\n\nimport type { MediaKind } from '@ttt-productions/media-schemas';\nimport { FileOriginSchema, type FileOrigin } from './file-origin.js';\nimport { TTT_MEDIA_SPECS } from './ttt-media-specs.js';\n\n/**\n * The required pre-publication PhotoDNA / spoof-guard branch implied by an\n * accepted (or, at runtime, magic-byte-detected) media kind:\n * - 'image' ⇒ image PhotoDNA (pre-publication, fail-closed)\n * - 'video' ⇒ frame-extraction (keyframes / ~1fps, capped) → PhotoDNA every frame\n * - 'audio' ⇒ AUDIO-ONLY SPOOF GUARD: confirm the bytes are genuinely audio\n * (a non-audio payload on an audio path is rejected, not skipped).\n * Audio is NOT image/video hashed.\n */\nexport type PhotoDnaRequiredBranch =\n | 'imagePhotoDna'\n | 'videoFramePhotoDna'\n | 'audioSpoofGuard';\n\n/**\n * The PhotoDNA-relevant subset of `MediaKind`. The generic 'file' kind has no\n * PhotoDNA / spoof-guard branch and never appears in any TTT origin's\n * `accept.kinds`, so it is excluded from the §A10 mapping.\n */\ntype PhotoDnaCoveredKind = Extract<MediaKind, 'image' | 'video' | 'audio'>;\n\n/**\n * The §A10 kind → required-branch mapping. This is the ONLY place the\n * kind↔branch correspondence is written; both the build-time matrix and the\n * runtime router derive from it. A newly accepted PhotoDNA-relevant kind must be\n * added here to compile (the `Record` is total over `PhotoDnaCoveredKind`).\n */\nconst REQUIRED_BRANCH_BY_KIND: Record<PhotoDnaCoveredKind, PhotoDnaRequiredBranch> = {\n image: 'imagePhotoDna',\n video: 'videoFramePhotoDna',\n audio: 'audioSpoofGuard',\n};\n\nconst PHOTODNA_COVERED_KINDS = Object.keys(\n REQUIRED_BRANCH_BY_KIND,\n) as PhotoDnaCoveredKind[];\n\nfunction isPhotoDnaCoveredKind(kind: MediaKind): kind is PhotoDnaCoveredKind {\n return (PHOTODNA_COVERED_KINDS as MediaKind[]).includes(kind);\n}\n\n/** The authoritative accepted-kinds set for an origin (`accept.kinds`). */\nfunction acceptedKindsForOrigin(origin: FileOrigin): MediaKind[] {\n return TTT_MEDIA_SPECS[origin].accept?.kinds ?? [];\n}\n\n/**\n * The required PhotoDNA / spoof-guard branches for an origin, derived from its\n * `accept.kinds` per the §A10 algorithm. Deduped, in\n * image → video → audio canonical order. Pure / decision-free.\n */\nexport function requiredPhotoDnaBranchesForOrigin(\n origin: FileOrigin,\n): PhotoDnaRequiredBranch[] {\n const kinds = new Set(acceptedKindsForOrigin(origin));\n // Iterate the canonical kind order (not the registry array order) so output is\n // deterministic regardless of how an origin lists its accepted kinds.\n return PHOTODNA_COVERED_KINDS.filter((kind) => kinds.has(kind)).map(\n (kind) => REQUIRED_BRANCH_BY_KIND[kind],\n );\n}\n\n/** One row of the derived build-time coverage matrix. */\nexport interface PhotoDnaCoverageEntry {\n /** The authoritative accepted-kinds set (`TTT_MEDIA_SPECS[origin].accept.kinds`). */\n readonly acceptedKinds: readonly MediaKind[];\n /** The required pre-publication branches implied by `acceptedKinds`. */\n readonly requiredBranches: readonly PhotoDnaRequiredBranch[];\n}\n\n/**\n * The build-time / CI coverage matrix: every `FileOriginSchema.options` value\n * mapped to its accepted kinds + required PhotoDNA branches. Derived from\n * `TTT_MEDIA_SPECS` at module load — never hand-maintained. `photodna-coverage.test.ts`\n * fails CI if any origin is missing OR any accepted kind has no required branch.\n */\nexport const PHOTODNA_COVERAGE_MATRIX: Record<FileOrigin, PhotoDnaCoverageEntry> =\n FileOriginSchema.options.reduce((matrix, origin) => {\n matrix[origin] = {\n acceptedKinds: acceptedKindsForOrigin(origin),\n requiredBranches: requiredPhotoDnaBranchesForOrigin(origin),\n };\n return matrix;\n }, {} as Record<FileOrigin, PhotoDnaCoverageEntry>);\n\n/**\n * Runtime dispatch (per uploaded object). `serverKind` is the SERVER-DETECTED\n * magic-byte kind — NEVER the client MIME / display kind — and MUST be a member\n * of `TTT_MEDIA_SPECS[origin].accept.kinds` for the upload's origin; a kind\n * outside that set is a spoof and the caller rejects (this helper does not see\n * the origin — the `accept.kinds ∋ serverKind` assertion is the caller's gate,\n * per §A10). For a covered kind it returns the branch the object must traverse:\n * image → imagePhotoDna, video → videoFramePhotoDna, audio → audioSpoofGuard.\n *\n * Returns `null` for the generic 'file' kind (no PhotoDNA path); callers treat a\n * `null` here on a non-'file' detection as a hard reject, never a skip.\n */\nexport function runtimePhotoDnaBranchForDetectedKind(\n serverKind: MediaKind,\n): PhotoDnaRequiredBranch | null {\n return isPhotoDnaCoveredKind(serverKind)\n ? REQUIRED_BRANCH_BY_KIND[serverKind]\n : null;\n}\n"]}
1
+ {"version":3,"file":"photodna-coverage.js","sourceRoot":"","sources":["../../src/media/photodna-coverage.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,sEAAsE;AACtE,4EAA4E;AAC5E,6EAA6E;AAC7E,qBAAqB;AACrB,EAAE;AACF,yDAAyD;AACzD,+EAA+E;AAC/E,+DAA+D;AAC/D,+EAA+E;AAC/E,iFAAiF;AACjF,+EAA+E;AAC/E,4DAA4D;AAG5D,OAAO,EAAE,gBAAgB,EAAmB,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAuBvD;;;;;GAKG;AACH,MAAM,uBAAuB,GAAwD;IACnF,KAAK,EAAE,eAAe;IACtB,KAAK,EAAE,oBAAoB;IAC3B,KAAK,EAAE,iBAAiB;CACzB,CAAC;AAEF,MAAM,sBAAsB,GAAG,MAAM,CAAC,IAAI,CACxC,uBAAuB,CACC,CAAC;AAE3B,SAAS,qBAAqB,CAAC,IAAe;IAC5C,OAAQ,sBAAsC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAChE,CAAC;AAED,2EAA2E;AAC3E,SAAS,sBAAsB,CAAC,MAAkB;IAChD,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC;AACrD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iCAAiC,CAC/C,MAAkB;IAElB,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;IACtD,+EAA+E;IAC/E,sEAAsE;IACtE,OAAO,sBAAsB,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CACjE,CAAC,IAAI,EAAE,EAAE,CAAC,uBAAuB,CAAC,IAAI,CAAC,CACxC,CAAC;AACJ,CAAC;AAUD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GACnC,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE;IACjD,MAAM,CAAC,MAAM,CAAC,GAAG;QACf,aAAa,EAAE,sBAAsB,CAAC,MAAM,CAAC;QAC7C,gBAAgB,EAAE,iCAAiC,CAAC,MAAM,CAAC;KAC5D,CAAC;IACF,OAAO,MAAM,CAAC;AAChB,CAAC,EAAE,EAA+C,CAAC,CAAC;AAEtD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oCAAoC,CAClD,UAAqB;IAErB,OAAO,qBAAqB,CAAC,UAAU,CAAC;QACtC,CAAC,CAAC,uBAAuB,CAAC,UAAU,CAAC;QACrC,CAAC,CAAC,IAAI,CAAC;AACX,CAAC","sourcesContent":["// PhotoDNA coverage matrix (frozen Trust & Safety spec, Appendix A §A10 —\n// Finding-M3, decision-free algorithm; durable design owner: ttt-prod\n// docs/design/csam-detection-and-response.md). The CI coverage test and the\n// runtime router are BOTH derived from this module so they cannot drift from\n// `TTT_MEDIA_SPECS`.\n//\n// The source of truth for what a media origin accepts is\n// `TTT_MEDIA_SPECS[origin].accept.kinds`, NOT the top-level `spec.kind` (which\n// mislabels `craft-skill-media`/`squareStreetz` as 'image' and\n// `guild-chat-message-attachment`/`work-asset` as 'generic', although all four\n// accept image+video+audio). Nothing here is hard-coded per-origin — every entry\n// is computed from the registry, so a new accepted kind on any origin fails CI\n// (via photodna-coverage.test.ts) until a branch covers it.\n\nimport type { MediaKind } from '@ttt-productions/media-schemas';\nimport { FileOriginSchema, type FileOrigin } from './file-origin.js';\nimport { TTT_MEDIA_SPECS } from './ttt-media-specs.js';\n\n/**\n * The required pre-publication PhotoDNA / spoof-guard branch implied by an\n * accepted (or, at runtime, magic-byte-detected) media kind:\n * - 'image' ⇒ image PhotoDNA (pre-publication, fail-closed)\n * - 'video' ⇒ frame-extraction (keyframes / ~1fps, capped) → PhotoDNA every frame\n * - 'audio' ⇒ AUDIO-ONLY SPOOF GUARD: confirm the bytes are genuinely audio\n * (a non-audio payload on an audio path is rejected, not skipped).\n * Audio is NOT image/video hashed.\n */\nexport type PhotoDnaRequiredBranch =\n | 'imagePhotoDna'\n | 'videoFramePhotoDna'\n | 'audioSpoofGuard';\n\n/**\n * The PhotoDNA-relevant subset of `MediaKind`. The generic 'file' kind has no\n * PhotoDNA / spoof-guard branch and never appears in any TTT origin's\n * `accept.kinds`, so it is excluded from the §A10 mapping.\n */\ntype PhotoDnaCoveredKind = Extract<MediaKind, 'image' | 'video' | 'audio'>;\n\n/**\n * The §A10 kind → required-branch mapping. This is the ONLY place the\n * kind↔branch correspondence is written; both the build-time matrix and the\n * runtime router derive from it. A newly accepted PhotoDNA-relevant kind must be\n * added here to compile (the `Record` is total over `PhotoDnaCoveredKind`).\n */\nconst REQUIRED_BRANCH_BY_KIND: Record<PhotoDnaCoveredKind, PhotoDnaRequiredBranch> = {\n image: 'imagePhotoDna',\n video: 'videoFramePhotoDna',\n audio: 'audioSpoofGuard',\n};\n\nconst PHOTODNA_COVERED_KINDS = Object.keys(\n REQUIRED_BRANCH_BY_KIND,\n) as PhotoDnaCoveredKind[];\n\nfunction isPhotoDnaCoveredKind(kind: MediaKind): kind is PhotoDnaCoveredKind {\n return (PHOTODNA_COVERED_KINDS as MediaKind[]).includes(kind);\n}\n\n/** The authoritative accepted-kinds set for an origin (`accept.kinds`). */\nfunction acceptedKindsForOrigin(origin: FileOrigin): MediaKind[] {\n return TTT_MEDIA_SPECS[origin].accept?.kinds ?? [];\n}\n\n/**\n * The required PhotoDNA / spoof-guard branches for an origin, derived from its\n * `accept.kinds` per the §A10 algorithm. Deduped, in\n * image → video → audio canonical order. Pure / decision-free.\n */\nexport function requiredPhotoDnaBranchesForOrigin(\n origin: FileOrigin,\n): PhotoDnaRequiredBranch[] {\n const kinds = new Set(acceptedKindsForOrigin(origin));\n // Iterate the canonical kind order (not the registry array order) so output is\n // deterministic regardless of how an origin lists its accepted kinds.\n return PHOTODNA_COVERED_KINDS.filter((kind) => kinds.has(kind)).map(\n (kind) => REQUIRED_BRANCH_BY_KIND[kind],\n );\n}\n\n/** One row of the derived build-time coverage matrix. */\nexport interface PhotoDnaCoverageEntry {\n /** The authoritative accepted-kinds set (`TTT_MEDIA_SPECS[origin].accept.kinds`). */\n readonly acceptedKinds: readonly MediaKind[];\n /** The required pre-publication branches implied by `acceptedKinds`. */\n readonly requiredBranches: readonly PhotoDnaRequiredBranch[];\n}\n\n/**\n * The build-time / CI coverage matrix: every `FileOriginSchema.options` value\n * mapped to its accepted kinds + required PhotoDNA branches. Derived from\n * `TTT_MEDIA_SPECS` at module load — never hand-maintained. `photodna-coverage.test.ts`\n * fails CI if any origin is missing OR any accepted kind has no required branch.\n */\nexport const PHOTODNA_COVERAGE_MATRIX: Record<FileOrigin, PhotoDnaCoverageEntry> =\n FileOriginSchema.options.reduce((matrix, origin) => {\n matrix[origin] = {\n acceptedKinds: acceptedKindsForOrigin(origin),\n requiredBranches: requiredPhotoDnaBranchesForOrigin(origin),\n };\n return matrix;\n }, {} as Record<FileOrigin, PhotoDnaCoverageEntry>);\n\n/**\n * Runtime dispatch (per uploaded object). `serverKind` is the SERVER-DETECTED\n * magic-byte kind — NEVER the client MIME / display kind — and MUST be a member\n * of `TTT_MEDIA_SPECS[origin].accept.kinds` for the upload's origin; a kind\n * outside that set is a spoof and the caller rejects (this helper does not see\n * the origin — the `accept.kinds ∋ serverKind` assertion is the caller's gate,\n * per §A10). For a covered kind it returns the branch the object must traverse:\n * image → imagePhotoDna, video → videoFramePhotoDna, audio → audioSpoofGuard.\n *\n * Returns `null` for the generic 'file' kind (no PhotoDNA path); callers treat a\n * `null` here on a non-'file' detection as a hard reject, never a skip.\n */\nexport function runtimePhotoDnaBranchForDetectedKind(\n serverKind: MediaKind,\n): PhotoDnaRequiredBranch | null {\n return isPhotoDnaCoveredKind(serverKind)\n ? REQUIRED_BRANCH_BY_KIND[serverKind]\n : null;\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  // Typed prefixes for structured relationship-array IDs (e.g. SquareStreetz post `relatedIds`).
2
2
  // Structured relationship arrays that mix entity types MUST store typed IDs using these
3
- // underscore prefixes. See docs/design/work-realm-discovery-system.md and
3
+ // underscore prefixes. See ttt-prod docs/design/work-realm-discovery-system.md and
4
4
  // engineering-rules BACKEND-206 (ttt-master-app/docs/engineering-rules/backend/sensitive-writes-and-audit.md).
5
5
  export const RELATED_ID_PREFIXES = {
6
6
  user: 'user_',
@@ -1 +1 @@
1
- {"version":3,"file":"related-ids.js","sourceRoot":"","sources":["../../src/paths/related-ids.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,wFAAwF;AACxF,0EAA0E;AAC1E,+GAA+G;AAE/G,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,IAAI,EAAE,OAAO;IACb,WAAW,EAAE,cAAc;IAC3B,SAAS,EAAE,YAAY;CACf,CAAC;AAIX,MAAM,UAAU,cAAc,CAAC,MAAuB,EAAE,EAAU;IAChE,OAAO,GAAG,mBAAmB,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC;AAC/C,CAAC","sourcesContent":["// Typed prefixes for structured relationship-array IDs (e.g. SquareStreetz post `relatedIds`).\n// Structured relationship arrays that mix entity types MUST store typed IDs using these\n// underscore prefixes. See docs/design/work-realm-discovery-system.md and\n// engineering-rules BACKEND-206 (ttt-master-app/docs/engineering-rules/backend/sensitive-writes-and-audit.md).\n\nexport const RELATED_ID_PREFIXES = {\n user: 'user_',\n workProject: 'workProject_',\n workRealm: 'workRealm_',\n} as const;\n\nexport type RelatedIdEntity = keyof typeof RELATED_ID_PREFIXES;\n\nexport function buildRelatedId(entity: RelatedIdEntity, id: string): string {\n return `${RELATED_ID_PREFIXES[entity]}${id}`;\n}\n"]}
1
+ {"version":3,"file":"related-ids.js","sourceRoot":"","sources":["../../src/paths/related-ids.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,wFAAwF;AACxF,mFAAmF;AACnF,+GAA+G;AAE/G,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,IAAI,EAAE,OAAO;IACb,WAAW,EAAE,cAAc;IAC3B,SAAS,EAAE,YAAY;CACf,CAAC;AAIX,MAAM,UAAU,cAAc,CAAC,MAAuB,EAAE,EAAU;IAChE,OAAO,GAAG,mBAAmB,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,CAAC;AAC/C,CAAC","sourcesContent":["// Typed prefixes for structured relationship-array IDs (e.g. SquareStreetz post `relatedIds`).\n// Structured relationship arrays that mix entity types MUST store typed IDs using these\n// underscore prefixes. See ttt-prod docs/design/work-realm-discovery-system.md and\n// engineering-rules BACKEND-206 (ttt-master-app/docs/engineering-rules/backend/sensitive-writes-and-audit.md).\n\nexport const RELATED_ID_PREFIXES = {\n user: 'user_',\n workProject: 'workProject_',\n workRealm: 'workRealm_',\n} as const;\n\nexport type RelatedIdEntity = keyof typeof RELATED_ID_PREFIXES;\n\nexport function buildRelatedId(entity: RelatedIdEntity, id: string): string {\n return `${RELATED_ID_PREFIXES[entity]}${id}`;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ncii-intake-derivations.d.ts","sourceRoot":"","sources":["../../src/safety/ncii-intake-derivations.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EACV,mBAAmB,EACnB,uBAAuB,EACvB,eAAe,EACf,sBAAsB,EACvB,MAAM,yBAAyB,CAAC;AAEjC;;;;;GAKG;AACH,eAAO,MAAM,SAAS,wBAAkB,CAAC;AAczC;;8EAE8E;AAC9E,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CA4CpE;AAED;0EAC0E;AAC1E,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAUxD;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,cAAc,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAExF;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEhE;AAMD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC3C,aAAa,EAAE,uBAAuB,CAAC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACpD,GAAG,MAAM,CAKT;AAMD,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAyChE;AAED;oFACoF;AACpF,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,eAAe,EACxB,iBAAiB,EAAE,OAAO,GACzB,sBAAsB,CAMxB;AAmBD,gFAAgF;AAChF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAEpE"}
1
+ {"version":3,"file":"ncii-intake-derivations.d.ts","sourceRoot":"","sources":["../../src/safety/ncii-intake-derivations.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EACV,mBAAmB,EACnB,uBAAuB,EACvB,eAAe,EACf,sBAAsB,EACvB,MAAM,yBAAyB,CAAC;AAEjC;;;;;GAKG;AACH,eAAO,MAAM,SAAS,wBAAkB,CAAC;AAczC;;8EAE8E;AAC9E,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CA4CpE;AAED;0EAC0E;AAC1E,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAUxD;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,cAAc,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAExF;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEhE;AAMD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE;IAC3C,aAAa,EAAE,uBAAuB,CAAC;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACpD,GAAG,MAAM,CAKT;AAMD,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAyChE;AAED;oFACoF;AACpF,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,eAAe,EACxB,iBAAiB,EAAE,OAAO,GACzB,sBAAsB,CAMxB;AAmBD,gFAAgF;AAChF,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAEpE"}
@@ -1,5 +1,7 @@
1
- // Shared NCII / TAKE IT DOWN intake derivations (Trust & Safety IMPLEMENTATION_PLAN
2
- // Phase NCII-2/3/4, Appendix A §A11). Pure, deterministic id/key/summary derivations
1
+ // Shared NCII / TAKE IT DOWN intake derivations (frozen Trust & Safety spec,
2
+ // Appendix A §A11; durable design owner: ttt-prod
3
+ // docs/design/nonconsensual-intimate-imagery-and-take-it-down.md).
4
+ // Pure, deterministic id/key/summary derivations
3
5
  // used by BOTH the public Next.js intake route and the Cloud Functions deadline/scan
4
6
  // workers. These used to be hand-mirrored in two app TS projects (the Cloud Functions
5
7
  // graph AND the App Hosting route graph, which cannot cross-import). This is now the ONE