@ttt-productions/q-core 0.1.0 → 0.1.2

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 (178) hide show
  1. package/dist/constants/business.d.ts +12 -0
  2. package/dist/constants/business.d.ts.map +1 -1
  3. package/dist/constants/business.js +24 -0
  4. package/dist/constants/business.js.map +1 -1
  5. package/dist/constants/media.d.ts +1 -0
  6. package/dist/constants/media.d.ts.map +1 -1
  7. package/dist/constants/media.js +5 -0
  8. package/dist/constants/media.js.map +1 -1
  9. package/dist/constants/sports.js.map +1 -1
  10. package/dist/constants/storage-keys.js.map +1 -1
  11. package/dist/doc-schemas/admin-notifications.d.ts +1 -0
  12. package/dist/doc-schemas/admin-notifications.d.ts.map +1 -1
  13. package/dist/doc-schemas/admin-notifications.js +4 -0
  14. package/dist/doc-schemas/admin-notifications.js.map +1 -1
  15. package/dist/doc-schemas/atoms.d.ts +2 -0
  16. package/dist/doc-schemas/atoms.d.ts.map +1 -1
  17. package/dist/doc-schemas/audit-event.d.ts +2 -0
  18. package/dist/doc-schemas/audit-event.d.ts.map +1 -1
  19. package/dist/doc-schemas/catalogs.js.map +1 -1
  20. package/dist/doc-schemas/gallery.d.ts +1 -0
  21. package/dist/doc-schemas/gallery.d.ts.map +1 -1
  22. package/dist/doc-schemas/gallery.js +3 -0
  23. package/dist/doc-schemas/gallery.js.map +1 -1
  24. package/dist/doc-schemas/game-location.js.map +1 -1
  25. package/dist/doc-schemas/game-stats.js.map +1 -1
  26. package/dist/doc-schemas/league-team.js.map +1 -1
  27. package/dist/doc-schemas/migration-console.d.ts +2 -0
  28. package/dist/doc-schemas/migration-console.d.ts.map +1 -1
  29. package/dist/doc-schemas/migration-console.js +5 -0
  30. package/dist/doc-schemas/migration-console.js.map +1 -1
  31. package/dist/doc-schemas/pending-media.d.ts +1 -0
  32. package/dist/doc-schemas/pending-media.d.ts.map +1 -1
  33. package/dist/doc-schemas/pending-media.js +8 -0
  34. package/dist/doc-schemas/pending-media.js.map +1 -1
  35. package/dist/doc-schemas/registry.d.ts +12 -0
  36. package/dist/doc-schemas/registry.d.ts.map +1 -1
  37. package/dist/doc-schemas/registry.js.map +1 -1
  38. package/dist/doc-schemas/sport-game.js.map +1 -1
  39. package/dist/doc-schemas/stats-operation.d.ts.map +1 -1
  40. package/dist/doc-schemas/stats-operation.js +6 -11
  41. package/dist/doc-schemas/stats-operation.js.map +1 -1
  42. package/dist/doc-schemas/system.d.ts +7 -0
  43. package/dist/doc-schemas/system.d.ts.map +1 -1
  44. package/dist/doc-schemas/system.js +4 -1
  45. package/dist/doc-schemas/system.js.map +1 -1
  46. package/dist/doc-schemas/user-profile.d.ts +1 -0
  47. package/dist/doc-schemas/user-profile.d.ts.map +1 -1
  48. package/dist/doc-schemas/user-profile.js +5 -0
  49. package/dist/doc-schemas/user-profile.js.map +1 -1
  50. package/dist/doc-schemas/waiver-template.d.ts +1 -0
  51. package/dist/doc-schemas/waiver-template.d.ts.map +1 -1
  52. package/dist/doc-schemas/waiver-template.js +10 -1
  53. package/dist/doc-schemas/waiver-template.js.map +1 -1
  54. package/dist/doc-schemas/waivers-and-hardware.d.ts +1 -0
  55. package/dist/doc-schemas/waivers-and-hardware.d.ts.map +1 -1
  56. package/dist/doc-schemas/waivers-and-hardware.js +17 -9
  57. package/dist/doc-schemas/waivers-and-hardware.js.map +1 -1
  58. package/dist/ids/index.js.map +1 -1
  59. package/dist/ids/minted-ids.d.ts +1 -0
  60. package/dist/ids/minted-ids.d.ts.map +1 -1
  61. package/dist/ids/minted-ids.js +6 -0
  62. package/dist/ids/minted-ids.js.map +1 -1
  63. package/dist/ids/stats-operation-ids.js.map +1 -1
  64. package/dist/index.js.map +1 -1
  65. package/dist/input-formats/index.d.ts +2 -2
  66. package/dist/input-formats/index.d.ts.map +1 -1
  67. package/dist/input-formats/index.js +2 -2
  68. package/dist/input-formats/index.js.map +1 -1
  69. package/dist/media/file-origins.js.map +1 -1
  70. package/dist/notifications/archive-all.d.ts +2 -0
  71. package/dist/notifications/archive-all.d.ts.map +1 -0
  72. package/dist/notifications/archive-all.js +6 -0
  73. package/dist/notifications/archive-all.js.map +1 -0
  74. package/dist/notifications/index.d.ts +1 -0
  75. package/dist/notifications/index.d.ts.map +1 -1
  76. package/dist/notifications/index.js +1 -0
  77. package/dist/notifications/index.js.map +1 -1
  78. package/dist/paths/collection-refs.js.map +1 -1
  79. package/dist/paths/collections.js.map +1 -1
  80. package/dist/paths/path-builders.js.map +1 -1
  81. package/dist/paths/utils.js.map +1 -1
  82. package/dist/schemas/account-settings.js.map +1 -1
  83. package/dist/schemas/admin-notifications.d.ts +1 -0
  84. package/dist/schemas/admin-notifications.d.ts.map +1 -1
  85. package/dist/schemas/admin-notifications.js +4 -2
  86. package/dist/schemas/admin-notifications.js.map +1 -1
  87. package/dist/schemas/app-config.d.ts +2 -2
  88. package/dist/schemas/app-config.d.ts.map +1 -1
  89. package/dist/schemas/app-config.js +9 -5
  90. package/dist/schemas/app-config.js.map +1 -1
  91. package/dist/schemas/atoms.js.map +1 -1
  92. package/dist/schemas/awards.d.ts +16 -4
  93. package/dist/schemas/awards.d.ts.map +1 -1
  94. package/dist/schemas/awards.js +10 -6
  95. package/dist/schemas/awards.js.map +1 -1
  96. package/dist/schemas/game-locations.d.ts +4 -4
  97. package/dist/schemas/game-locations.d.ts.map +1 -1
  98. package/dist/schemas/game-locations.js +11 -3
  99. package/dist/schemas/game-locations.js.map +1 -1
  100. package/dist/schemas/hardware-loan-contracts.js.map +1 -1
  101. package/dist/schemas/migration-console.d.ts +1 -0
  102. package/dist/schemas/migration-console.d.ts.map +1 -1
  103. package/dist/schemas/pictures.d.ts +3 -0
  104. package/dist/schemas/pictures.d.ts.map +1 -1
  105. package/dist/schemas/schedules.js.map +1 -1
  106. package/dist/schemas/scoring.js.map +1 -1
  107. package/dist/schemas/stats.d.ts +2 -0
  108. package/dist/schemas/stats.d.ts.map +1 -1
  109. package/dist/schemas/stats.js.map +1 -1
  110. package/dist/schemas/team-joining.js.map +1 -1
  111. package/dist/schemas/teams.d.ts +3 -2
  112. package/dist/schemas/teams.d.ts.map +1 -1
  113. package/dist/schemas/teams.js +19 -9
  114. package/dist/schemas/teams.js.map +1 -1
  115. package/dist/schemas/uploads.js.map +1 -1
  116. package/dist/schemas/users.d.ts +7 -3
  117. package/dist/schemas/users.d.ts.map +1 -1
  118. package/dist/schemas/users.js +10 -3
  119. package/dist/schemas/users.js.map +1 -1
  120. package/dist/schemas/waiver-templates.d.ts +1 -0
  121. package/dist/schemas/waiver-templates.d.ts.map +1 -1
  122. package/dist/schemas/waiver-templates.js +4 -1
  123. package/dist/schemas/waiver-templates.js.map +1 -1
  124. package/dist/sports/basketball-scoring.js.map +1 -1
  125. package/dist/sports/basketball.js.map +1 -1
  126. package/dist/sports/bulk-entry.js.map +1 -1
  127. package/dist/sports/contribution.js.map +1 -1
  128. package/dist/sports/curling-scoring.js.map +1 -1
  129. package/dist/sports/finalized-record.js.map +1 -1
  130. package/dist/sports/football-scoring.js.map +1 -1
  131. package/dist/sports/index.d.ts +1 -0
  132. package/dist/sports/index.d.ts.map +1 -1
  133. package/dist/sports/index.js +1 -0
  134. package/dist/sports/index.js.map +1 -1
  135. package/dist/sports/ledger-continuity.d.ts +13 -0
  136. package/dist/sports/ledger-continuity.d.ts.map +1 -0
  137. package/dist/sports/ledger-continuity.js +19 -0
  138. package/dist/sports/ledger-continuity.js.map +1 -0
  139. package/dist/sports/rankings.js.map +1 -1
  140. package/dist/sports/rollup-check.js.map +1 -1
  141. package/dist/sports/scoring.js.map +1 -1
  142. package/dist/sports/store-driver.js.map +1 -1
  143. package/dist/types/audit.d.ts +1 -1
  144. package/dist/types/audit.d.ts.map +1 -1
  145. package/dist/types/audit.js +5 -2
  146. package/dist/types/audit.js.map +1 -1
  147. package/dist/types/documents.js.map +1 -1
  148. package/dist/types/notifications.js.map +1 -1
  149. package/dist/types/picture-owners.js.map +1 -1
  150. package/dist/types/sports.js.map +1 -1
  151. package/dist/types/stats.js.map +1 -1
  152. package/dist/types/unions.d.ts +4 -2
  153. package/dist/types/unions.d.ts.map +1 -1
  154. package/dist/types/unions.js +6 -0
  155. package/dist/types/unions.js.map +1 -1
  156. package/dist/upload-variables/index.d.ts +3 -0
  157. package/dist/upload-variables/index.d.ts.map +1 -0
  158. package/dist/upload-variables/index.js +3 -0
  159. package/dist/upload-variables/index.js.map +1 -0
  160. package/dist/upload-variables/on-progress.d.ts +4 -0
  161. package/dist/upload-variables/on-progress.d.ts.map +1 -0
  162. package/dist/upload-variables/on-progress.js +10 -0
  163. package/dist/upload-variables/on-progress.js.map +1 -0
  164. package/dist/upload-variables/picture-upload-variables.d.ts +32 -0
  165. package/dist/upload-variables/picture-upload-variables.d.ts.map +1 -0
  166. package/dist/upload-variables/picture-upload-variables.js +21 -0
  167. package/dist/upload-variables/picture-upload-variables.js.map +1 -0
  168. package/dist/utils/account-status.js.map +1 -1
  169. package/dist/utils/app-config.d.ts +17 -3
  170. package/dist/utils/app-config.d.ts.map +1 -1
  171. package/dist/utils/app-config.js +21 -14
  172. package/dist/utils/app-config.js.map +1 -1
  173. package/dist/utils/app-routes.js.map +1 -1
  174. package/dist/utils/index.js.map +1 -1
  175. package/dist/utils/league-calendar.js.map +1 -1
  176. package/dist/utils/league-mode.js.map +1 -1
  177. package/dist/utils/team-member-actions.js.map +1 -1
  178. package/package.json +94 -90
@@ -1 +1 @@
1
- {"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/system.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA2BxB,eAAO,MAAM,eAAe;;;;;;iBAS1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAIxD,eAAO,MAAM,uBAAuB;;;;;;;;;iBAKlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAMxE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;iBAM5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAK5D,eAAO,MAAM,eAAe;;;iBAG1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAMxD,eAAO,MAAM,8BAA8B,2IAMzC,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;kBAUjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,eAAO,MAAM,0BAA0B;;;kBAE8E,CAAC;AACtH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E,eAAO,MAAM,4BAA4B;;;;;;kBAMvC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAElF,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAYtC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC"}
1
+ {"version":3,"file":"system.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/system.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA4BxB,eAAO,MAAM,eAAe;;;;;;iBAS1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAIxD,eAAO,MAAM,uBAAuB;;;;;;;;;iBAKlC,CAAC;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAMxE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;iBAS5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAK5D,eAAO,MAAM,eAAe;;;iBAG1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAMxD,eAAO,MAAM,8BAA8B,2IAMzC,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;kBAUjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,eAAO,MAAM,0BAA0B;;;kBAE8E,CAAC;AACtH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E,eAAO,MAAM,4BAA4B;;;;;;kBAMvC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAElF,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAYtC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC"}
@@ -4,7 +4,7 @@ import { z } from 'zod';
4
4
  import { MAX_ANNOUNCEMENT_MESSAGE_LENGTH, MAX_APP_VERSION_LENGTH, MAX_LANDING_ABOUT_TEXT_LENGTH, MAX_LANDING_HERO_TITLE_LENGTH, MAX_MAINTENANCE_MESSAGE_LENGTH, } from '../constants/business.js';
5
5
  import { MAX_STATS_VALIDATION_DISCREPANCIES } from '../constants/sports.js';
6
6
  import { GallerySummarySchema } from './gallery.js';
7
- import { countSchema, epochMsSchema, gameIdSchema, leagueIdSchema, statsBeaconActionSchema, statsDiscrepancyKindSchema, statsOperationIdSchema, teamIdSchema, userIdSchema, } from './atoms.js';
7
+ import { countSchema, documentIdSegmentSchema, epochMsSchema, gameIdSchema, leagueIdSchema, statsBeaconActionSchema, statsDiscrepancyKindSchema, statsOperationIdSchema, teamIdSchema, userIdSchema, } from './atoms.js';
8
8
  // `_appConfig/app` — the app-wide operational levers, set through the audited updateAppConfig
9
9
  // callable. `appVersion` is what a live client compares itself against to force a refresh. It is
10
10
  // written whole through `mergeAppConfigUpdate` and read one lever at a time through
@@ -34,6 +34,9 @@ export const LandingPageConfigSchema = z.object({
34
34
  // earlier write.
35
35
  export const StatsBeaconSchema = z.object({
36
36
  updatedAt: epochMsSchema,
37
+ // A fresh document id minted by every write, so two commits in the same millisecond still move
38
+ // the beacon. Absent on a beacon stored before writes carried one.
39
+ changeId: documentIdSegmentSchema.optional(),
37
40
  action: statsBeaconActionSchema,
38
41
  leagueId: leagueIdSchema.optional(),
39
42
  gameId: gameIdSchema.optional(),
@@ -1 +1 @@
1
- {"version":3,"file":"system.js","sourceRoot":"","sources":["../../src/doc-schemas/system.ts"],"names":[],"mappings":"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","sourcesContent":["// Fixed-ID system documents in the underscore buckets, plus the derived stat documents. Every one\r\n// is callable-only for writes.\r\n\r\nimport { z } from 'zod';\r\nimport {\r\n MAX_ANNOUNCEMENT_MESSAGE_LENGTH,\r\n MAX_APP_VERSION_LENGTH,\r\n MAX_LANDING_ABOUT_TEXT_LENGTH,\r\n MAX_LANDING_HERO_TITLE_LENGTH,\r\n MAX_MAINTENANCE_MESSAGE_LENGTH,\r\n} from '../constants/business.js';\r\nimport { MAX_STATS_VALIDATION_DISCREPANCIES } from '../constants/sports.js';\r\nimport { GallerySummarySchema } from './gallery.js';\r\nimport {\r\n countSchema,\r\n epochMsSchema,\r\n gameIdSchema,\r\n leagueIdSchema,\r\n statsBeaconActionSchema,\r\n statsDiscrepancyKindSchema,\r\n statsOperationIdSchema,\r\n teamIdSchema,\r\n userIdSchema,\r\n} from './atoms.js';\r\n\r\n// `_appConfig/app` — the app-wide operational levers, set through the audited updateAppConfig\r\n// callable. `appVersion` is what a live client compares itself against to force a refresh. It is\r\n// written whole through `mergeAppConfigUpdate` and read one lever at a time through\r\n// `readAppConfigLever` (../utils/app-config.ts). Every text lever carries the same cap as its\r\n// updateAppConfig input field, so no writer can store a value the input would refuse.\r\nexport const AppConfigSchema = z.object({\r\n // `''` is valid here — no version published yet; only the update input requires a value.\r\n appVersion: z.string().max(MAX_APP_VERSION_LENGTH),\r\n maintenanceMode: z.boolean(),\r\n maintenanceMessage: z.string().max(MAX_MAINTENANCE_MESSAGE_LENGTH).optional(),\r\n registrationEnabled: z.boolean(),\r\n // Empty means no banner — there is no separate on/off flag. Non-empty is the band above every\r\n // page.\r\n announcementMessage: z.string().max(MAX_ANNOUNCEMENT_MESSAGE_LENGTH).optional(),\r\n});\r\nexport type AppConfig = z.infer<typeof AppConfigSchema>;\r\n\r\n// `_appConfig/landingPage` — admin-authored landing page copy, written by adminUpdateLandingPage,\r\n// plus the landing gallery's summary, which only the picture core writes.\r\nexport const LandingPageConfigSchema = z.object({\r\n heroTitle: z.string().max(MAX_LANDING_HERO_TITLE_LENGTH),\r\n aboutCompany: z.string().max(MAX_LANDING_ABOUT_TEXT_LENGTH),\r\n pictures: GallerySummarySchema.optional(),\r\n updatedAt: epochMsSchema,\r\n});\r\nexport type LandingPageConfig = z.infer<typeof LandingPageConfigSchema>;\r\n\r\n// `_appConfig/statsBeacon` — the signal watching clients refresh their stats on, replaced whole by\r\n// every write. The scope ids say what changed; an action that spans more than one game or league\r\n// omits them, and because every write replaces the document, an omitted id never survives from an\r\n// earlier write.\r\nexport const StatsBeaconSchema = z.object({\r\n updatedAt: epochMsSchema,\r\n action: statsBeaconActionSchema,\r\n leagueId: leagueIdSchema.optional(),\r\n gameId: gameIdSchema.optional(),\r\n teamIds: z.array(teamIdSchema).optional(),\r\n});\r\nexport type StatsBeacon = z.infer<typeof StatsBeaconSchema>;\r\n\r\n// `_systemData/adminList` — the admin and referee rosters. The source of truth the `admin` and\r\n// `referee` custom claims are minted from, written only by the audited updateAdminList callable;\r\n// the first admin of a fresh environment is seeded in the console.\r\nexport const AdminListSchema = z.object({\r\n admins: z.array(userIdSchema),\r\n referees: z.array(userIdSchema),\r\n});\r\nexport type AdminList = z.infer<typeof AdminListSchema>;\r\n\r\n// `statsValidationReports/{reportId}` — one stats check: every place a game's stored numbers, or a\r\n// derived aggregate, disagree with what the game's events and the completed games say they should\r\n// be. Its id is the check's operation id, which the admin's browser mints, so two checks never share\r\n// a report. Written only by the check, page by page; `complete` turns true with its last page.\r\nexport const STATS_DISCREPANCY_VALUE_SCHEMA = z.union([\r\n z.number(),\r\n z.string(),\r\n z.array(z.number().nullable()),\r\n z.record(z.string(), z.number()),\r\n z.null(),\r\n]);\r\n\r\nexport const StatsDiscrepancySchema = z.strictObject({\r\n kind: statsDiscrepancyKindSchema,\r\n gameId: gameIdSchema.optional(),\r\n // The slash path of the document the finding is about.\r\n path: z.string().min(1),\r\n // The line or entry within it — a team id, a roster-entry id, a user id — when there is one.\r\n key: z.string().min(1).optional(),\r\n field: z.string().min(1).optional(),\r\n expected: STATS_DISCREPANCY_VALUE_SCHEMA.optional(),\r\n actual: STATS_DISCREPANCY_VALUE_SCHEMA.optional(),\r\n});\r\nexport type StatsDiscrepancy = z.infer<typeof StatsDiscrepancySchema>;\r\n\r\nexport const StatsValidationScopeSchema = z\r\n .strictObject({ gameId: gameIdSchema.optional(), leagueId: leagueIdSchema.optional() })\r\n .refine((scope) => scope.gameId === undefined || scope.leagueId === undefined, 'One game or one league, not both.');\r\nexport type StatsValidationScope = z.infer<typeof StatsValidationScopeSchema>;\r\n\r\nexport const StatsValidationSummarySchema = z.strictObject({\r\n totalGamesChecked: countSchema,\r\n totalUsersChecked: countSchema,\r\n totalTeamsChecked: countSchema,\r\n totalLeaguesChecked: countSchema,\r\n discrepanciesFound: countSchema,\r\n});\r\nexport type StatsValidationSummary = z.infer<typeof StatsValidationSummarySchema>;\r\n\r\nexport const StatsValidationReportSchema = z.strictObject({\r\n reportId: z.string().min(1),\r\n operationId: statsOperationIdSchema,\r\n ranAt: epochMsSchema,\r\n ranByUserId: userIdSchema,\r\n scope: StatsValidationScopeSchema,\r\n complete: z.boolean(),\r\n // Game-tier findings first, then aggregate ones, at most MAX_STATS_VALIDATION_DISCREPANCIES.\r\n discrepancies: z.array(StatsDiscrepancySchema).max(MAX_STATS_VALIDATION_DISCREPANCIES),\r\n // Every finding, kept or not, counted by kind.\r\n discrepancyCounts: z.partialRecord(statsDiscrepancyKindSchema, countSchema),\r\n summary: StatsValidationSummarySchema,\r\n});\r\nexport type StatsValidationReport = z.infer<typeof StatsValidationReportSchema>;\r\n"]}
1
+ {"version":3,"file":"system.js","sourceRoot":"","sources":["../../src/doc-schemas/system.ts"],"names":[],"mappings":"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","sourcesContent":["// Fixed-ID system documents in the underscore buckets, plus the derived stat documents. Every one\n// is callable-only for writes.\n\nimport { z } from 'zod';\nimport {\n MAX_ANNOUNCEMENT_MESSAGE_LENGTH,\n MAX_APP_VERSION_LENGTH,\n MAX_LANDING_ABOUT_TEXT_LENGTH,\n MAX_LANDING_HERO_TITLE_LENGTH,\n MAX_MAINTENANCE_MESSAGE_LENGTH,\n} from '../constants/business.js';\nimport { MAX_STATS_VALIDATION_DISCREPANCIES } from '../constants/sports.js';\nimport { GallerySummarySchema } from './gallery.js';\nimport {\n countSchema,\n documentIdSegmentSchema,\n epochMsSchema,\n gameIdSchema,\n leagueIdSchema,\n statsBeaconActionSchema,\n statsDiscrepancyKindSchema,\n statsOperationIdSchema,\n teamIdSchema,\n userIdSchema,\n} from './atoms.js';\n\n// `_appConfig/app` — the app-wide operational levers, set through the audited updateAppConfig\n// callable. `appVersion` is what a live client compares itself against to force a refresh. It is\n// written whole through `mergeAppConfigUpdate` and read one lever at a time through\n// `readAppConfigLever` (../utils/app-config.ts). Every text lever carries the same cap as its\n// updateAppConfig input field, so no writer can store a value the input would refuse.\nexport const AppConfigSchema = z.object({\n // `''` is valid here — no version published yet; only the update input requires a value.\n appVersion: z.string().max(MAX_APP_VERSION_LENGTH),\n maintenanceMode: z.boolean(),\n maintenanceMessage: z.string().max(MAX_MAINTENANCE_MESSAGE_LENGTH).optional(),\n registrationEnabled: z.boolean(),\n // Empty means no banner — there is no separate on/off flag. Non-empty is the band above every\n // page.\n announcementMessage: z.string().max(MAX_ANNOUNCEMENT_MESSAGE_LENGTH).optional(),\n});\nexport type AppConfig = z.infer<typeof AppConfigSchema>;\n\n// `_appConfig/landingPage` — admin-authored landing page copy, written by adminUpdateLandingPage,\n// plus the landing gallery's summary, which only the picture core writes.\nexport const LandingPageConfigSchema = z.object({\n heroTitle: z.string().max(MAX_LANDING_HERO_TITLE_LENGTH),\n aboutCompany: z.string().max(MAX_LANDING_ABOUT_TEXT_LENGTH),\n pictures: GallerySummarySchema.optional(),\n updatedAt: epochMsSchema,\n});\nexport type LandingPageConfig = z.infer<typeof LandingPageConfigSchema>;\n\n// `_appConfig/statsBeacon` — the signal watching clients refresh their stats on, replaced whole by\n// every write. The scope ids say what changed; an action that spans more than one game or league\n// omits them, and because every write replaces the document, an omitted id never survives from an\n// earlier write.\nexport const StatsBeaconSchema = z.object({\n updatedAt: epochMsSchema,\n // A fresh document id minted by every write, so two commits in the same millisecond still move\n // the beacon. Absent on a beacon stored before writes carried one.\n changeId: documentIdSegmentSchema.optional(),\n action: statsBeaconActionSchema,\n leagueId: leagueIdSchema.optional(),\n gameId: gameIdSchema.optional(),\n teamIds: z.array(teamIdSchema).optional(),\n});\nexport type StatsBeacon = z.infer<typeof StatsBeaconSchema>;\n\n// `_systemData/adminList` — the admin and referee rosters. The source of truth the `admin` and\n// `referee` custom claims are minted from, written only by the audited updateAdminList callable;\n// the first admin of a fresh environment is seeded in the console.\nexport const AdminListSchema = z.object({\n admins: z.array(userIdSchema),\n referees: z.array(userIdSchema),\n});\nexport type AdminList = z.infer<typeof AdminListSchema>;\n\n// `statsValidationReports/{reportId}` — one stats check: every place a game's stored numbers, or a\n// derived aggregate, disagree with what the game's events and the completed games say they should\n// be. Its id is the check's operation id, which the admin's browser mints, so two checks never share\n// a report. Written only by the check, page by page; `complete` turns true with its last page.\nexport const STATS_DISCREPANCY_VALUE_SCHEMA = z.union([\n z.number(),\n z.string(),\n z.array(z.number().nullable()),\n z.record(z.string(), z.number()),\n z.null(),\n]);\n\nexport const StatsDiscrepancySchema = z.strictObject({\n kind: statsDiscrepancyKindSchema,\n gameId: gameIdSchema.optional(),\n // The slash path of the document the finding is about.\n path: z.string().min(1),\n // The line or entry within it — a team id, a roster-entry id, a user id — when there is one.\n key: z.string().min(1).optional(),\n field: z.string().min(1).optional(),\n expected: STATS_DISCREPANCY_VALUE_SCHEMA.optional(),\n actual: STATS_DISCREPANCY_VALUE_SCHEMA.optional(),\n});\nexport type StatsDiscrepancy = z.infer<typeof StatsDiscrepancySchema>;\n\nexport const StatsValidationScopeSchema = z\n .strictObject({ gameId: gameIdSchema.optional(), leagueId: leagueIdSchema.optional() })\n .refine((scope) => scope.gameId === undefined || scope.leagueId === undefined, 'One game or one league, not both.');\nexport type StatsValidationScope = z.infer<typeof StatsValidationScopeSchema>;\n\nexport const StatsValidationSummarySchema = z.strictObject({\n totalGamesChecked: countSchema,\n totalUsersChecked: countSchema,\n totalTeamsChecked: countSchema,\n totalLeaguesChecked: countSchema,\n discrepanciesFound: countSchema,\n});\nexport type StatsValidationSummary = z.infer<typeof StatsValidationSummarySchema>;\n\nexport const StatsValidationReportSchema = z.strictObject({\n reportId: z.string().min(1),\n operationId: statsOperationIdSchema,\n ranAt: epochMsSchema,\n ranByUserId: userIdSchema,\n scope: StatsValidationScopeSchema,\n complete: z.boolean(),\n // Game-tier findings first, then aggregate ones, at most MAX_STATS_VALIDATION_DISCREPANCIES.\n discrepancies: z.array(StatsDiscrepancySchema).max(MAX_STATS_VALIDATION_DISCREPANCIES),\n // Every finding, kept or not, counted by kind.\n discrepancyCounts: z.partialRecord(statsDiscrepancyKindSchema, countSchema),\n summary: StatsValidationSummarySchema,\n});\nexport type StatsValidationReport = z.infer<typeof StatsValidationReportSchema>;\n"]}
@@ -44,6 +44,7 @@ export type UserProfile = z.infer<typeof UserProfileSchema>;
44
44
  export declare const UserPrivateDataSchema: z.ZodObject<{
45
45
  email: z.ZodString;
46
46
  registrationStartedAt: z.ZodOptional<z.ZodNumber>;
47
+ orphanDeletionClaimedAt: z.ZodOptional<z.ZodNumber>;
47
48
  defaultContactPhone: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
48
49
  theme: z.ZodOptional<z.ZodEnum<{
49
50
  light: "light";
@@ -1 +1 @@
1
- {"version":3,"file":"user-profile.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/user-profile.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB,eAAO,MAAM,eAAe;;;;EAAsB,CAAC;AAGnD,eAAO,MAAM,kBAAkB;;;iBAG7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAc5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAI5D,eAAO,MAAM,qBAAqB;;;;;;;;;;;iBAYhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAMpE,eAAO,MAAM,qBAAqB;;;;;kBAA6D,CAAC;AAChG,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAWpE,8DAA8D;AAC9D,eAAO,MAAM,oBAAoB,EAAyC,SAAS,CAAC,MAAM,eAAe,CAAC,EAAE,CAAC"}
1
+ {"version":3,"file":"user-profile.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/user-profile.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB,eAAO,MAAM,eAAe;;;;EAAsB,CAAC;AAGnD,eAAO,MAAM,kBAAkB;;;iBAG7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAc5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAI5D,eAAO,MAAM,qBAAqB;;;;;;;;;;;;iBAiBhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAMpE,eAAO,MAAM,qBAAqB;;;;;kBAA6D,CAAC;AAChG,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAWpE,8DAA8D;AAC9D,eAAO,MAAM,oBAAoB,EAAyC,SAAS,CAAC,MAAM,eAAe,CAAC,EAAE,CAAC"}
@@ -37,6 +37,11 @@ export const UserPrivateDataSchema = z.object({
37
37
  // When this login's registration started (`createRegistrationStart`); `registerUser` refuses
38
38
  // without it. Absent on an account copied from V1, which registered before the step existed.
39
39
  registrationStartedAt: epochMsSchema.optional(),
40
+ // When the orphan-registration cleanup decided to delete this uid's login. Written in the
41
+ // cleanup's eligibility transaction BEFORE the Auth delete, and both registration steps answer
42
+ // `registrationExpired` in their own transactions while it is present, so no registration
43
+ // completes into a login that is about to be deleted. Backend-only.
44
+ orphanDeletionClaimedAt: epochMsSchema.optional(),
40
45
  // Pre-fills the contact phone when this user creates a team.
41
46
  defaultContactPhone: textFieldSchema(CONTACT_PHONE_INPUT_FORMAT).optional(),
42
47
  // The account's copy of the viewer's settings, synced with the device's. Absent means the
@@ -1 +1 @@
1
- {"version":3,"file":"user-profile.js","sourceRoot":"","sources":["../../src/doc-schemas/user-profile.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,6FAA6F;AAC7F,kGAAkG;AAClG,uDAAuD;AAEvD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,4BAA4B,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC7F,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,kGAAkG;AAClG,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AAEnD,6FAA6F;AAC7F,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,OAAO,EAAE,aAAa;IACtB,SAAS,EAAE,aAAa;CACzB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,qBAAqB,EAAE,CAAC,CAAC,MAAM,EAAE;IACjC,oFAAoF;IACpF,UAAU,EAAE,gBAAgB;IAC5B,+FAA+F;IAC/F,yBAAyB;IACzB,aAAa,EAAE,uBAAuB,CAAC,QAAQ,EAAE;IACjD,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,QAAQ,EAAE;IACrD,mEAAmE;IACnE,cAAc,EAAE,aAAa,CAAC,QAAQ,EAAE;IACxC,gBAAgB,EAAE,aAAa,CAAC,QAAQ,EAAE;IAC1C,SAAS,EAAE,aAAa;IACxB,SAAS,EAAE,aAAa;CACzB,CAAC,CAAC;AAGH,mGAAmG;AACnG,gBAAgB;AAChB,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,6FAA6F;IAC7F,6FAA6F;IAC7F,qBAAqB,EAAE,aAAa,CAAC,QAAQ,EAAE;IAC/C,6DAA6D;IAC7D,mBAAmB,EAAE,eAAe,CAAC,0BAA0B,CAAC,CAAC,QAAQ,EAAE;IAC3E,0FAA0F;IAC1F,gEAAgE;IAChE,KAAK,EAAE,eAAe,CAAC,QAAQ,EAAE;IACjC,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACrC,SAAS,EAAE,aAAa;CACzB,CAAC,CAAC;AAGH,mGAAmG;AACnG,sGAAsG;AACtG,+FAA+F;AAC/F,yCAAyC;AACzC,MAAM,CAAC,MAAM,qBAAqB,GAAG,4BAA4B,CAAC,IAAI,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;AAGhG,sGAAsG;AACtG,8BAA8B;AAC9B,MAAM,qBAAqB,GAAwC;IACjE,WAAW,EAAE,IAAI;IACjB,MAAM,EAAE,IAAI;IACZ,QAAQ,EAAE,IAAI;IACd,OAAO,EAAE,IAAI;CACd,CAAC;AAEF,8DAA8D;AAC9D,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAuC,CAAC","sourcesContent":["// `userProfiles/{userId}` — the account's profile, one per Firebase Auth uid. Ghosts have none.\r\n// It is publicly readable (a profile page renders signed out), so it holds nothing personal:\r\n// email and contact details live in its owner-only `privateData/{userId}` document (BACKEND-105).\r\n// Plus its `historicalStats/{sportKey}` subcollection.\r\n\r\nimport { z } from 'zod';\r\nimport { THEME_NAMES } from '@ttt-productions/theme-core';\r\nimport { CONTACT_PHONE_INPUT_FORMAT } from '../input-formats/index.js';\r\nimport { BasketballPlayerTotalsSchema, UserLifetimeStatsSchema } from './aggregate-stats.js';\r\nimport { epochMsSchema, textFieldSchema, userStatusSchema } from './atoms.js';\r\nimport { awardIdSchema } from './catalogs.js';\r\n\r\n// A saved theme, typed by theme-core's theme set — the one declaration its provider renders from.\r\nexport const themeNameSchema = z.enum(THEME_NAMES);\r\n\r\n// An award granted to this user. Name and imagery resolve from `awardDefinitions/{awardId}`.\r\nexport const GrantedAwardSchema = z.object({\r\n awardId: awardIdSchema,\r\n grantedAt: epochMsSchema,\r\n});\r\nexport type GrantedAward = z.infer<typeof GrantedAwardSchema>;\r\n\r\nexport const UserProfileSchema = z.object({\r\n displayName: z.string(),\r\n displayName_lowercase: z.string(),\r\n // Written `active` at registration and by the profile copy; nothing else writes it.\r\n userStatus: userStatusSchema,\r\n // Per sport, the career line; career games played is the sum of their games played, derived at\r\n // read and never stored.\r\n lifetimeStats: UserLifetimeStatsSchema.optional(),\r\n grantedAwards: z.array(GrantedAwardSchema).optional(),\r\n // The awards the account shows beside its name, each one it holds.\r\n primaryAwardId: awardIdSchema.optional(),\r\n secondaryAwardId: awardIdSchema.optional(),\r\n createdAt: epochMsSchema,\r\n updatedAt: epochMsSchema,\r\n});\r\nexport type UserProfile = z.infer<typeof UserProfileSchema>;\r\n\r\n// `userProfiles/{userId}/privateData/{userId}` — readable by its owner and by admins; written only\r\n// by callables.\r\nexport const UserPrivateDataSchema = z.object({\r\n email: z.string(),\r\n // When this login's registration started (`createRegistrationStart`); `registerUser` refuses\r\n // without it. Absent on an account copied from V1, which registered before the step existed.\r\n registrationStartedAt: epochMsSchema.optional(),\r\n // Pre-fills the contact phone when this user creates a team.\r\n defaultContactPhone: textFieldSchema(CONTACT_PHONE_INPUT_FORMAT).optional(),\r\n // The account's copy of the viewer's settings, synced with the device's. Absent means the\r\n // account has saved nothing and the device's own choice stands.\r\n theme: themeNameSchema.optional(),\r\n reducedMotion: z.boolean().optional(),\r\n updatedAt: epochMsSchema,\r\n});\r\nexport type UserPrivateData = z.infer<typeof UserPrivateDataSchema>;\r\n\r\n// `userProfiles/{userId}/historicalStats/{sportKey}` — pre-Q-Sports career totals an admin enters,\r\n// folded into lifetime and hall-of-fame recalculation. Absolute totals, not increments. Basketball is\r\n// the sport with a baseline, so it is the basketball totals line without FP, which the rebuild\r\n// derives when it folds the baseline in.\r\nexport const HistoricalStatsSchema = BasketballPlayerTotalsSchema.omit({ fantasyPoints: true });\r\nexport type HistoricalStats = z.infer<typeof HistoricalStatsSchema>;\n\n// Every field of a baseline, keyed so the record cannot miss one or name one the schema lacks, in the\n// order an admin enters them.\nconst HISTORICAL_STAT_ENTRY: Record<keyof HistoricalStats, true> = {\n gamesPlayed: true,\n points: true,\n rebounds: true,\n assists: true,\n};\n\n/** A baseline's totals, in the order an admin enters them. */\nexport const HISTORICAL_STAT_KEYS = Object.keys(HISTORICAL_STAT_ENTRY) as readonly (keyof HistoricalStats)[];\r\n"]}
1
+ {"version":3,"file":"user-profile.js","sourceRoot":"","sources":["../../src/doc-schemas/user-profile.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,6FAA6F;AAC7F,kGAAkG;AAClG,uDAAuD;AAEvD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AACvE,OAAO,EAAE,4BAA4B,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC7F,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,kGAAkG;AAClG,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AAEnD,6FAA6F;AAC7F,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,OAAO,EAAE,aAAa;IACtB,SAAS,EAAE,aAAa;CACzB,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,qBAAqB,EAAE,CAAC,CAAC,MAAM,EAAE;IACjC,oFAAoF;IACpF,UAAU,EAAE,gBAAgB;IAC5B,+FAA+F;IAC/F,yBAAyB;IACzB,aAAa,EAAE,uBAAuB,CAAC,QAAQ,EAAE;IACjD,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,QAAQ,EAAE;IACrD,mEAAmE;IACnE,cAAc,EAAE,aAAa,CAAC,QAAQ,EAAE;IACxC,gBAAgB,EAAE,aAAa,CAAC,QAAQ,EAAE;IAC1C,SAAS,EAAE,aAAa;IACxB,SAAS,EAAE,aAAa;CACzB,CAAC,CAAC;AAGH,mGAAmG;AACnG,gBAAgB;AAChB,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,6FAA6F;IAC7F,6FAA6F;IAC7F,qBAAqB,EAAE,aAAa,CAAC,QAAQ,EAAE;IAC/C,0FAA0F;IAC1F,+FAA+F;IAC/F,0FAA0F;IAC1F,oEAAoE;IACpE,uBAAuB,EAAE,aAAa,CAAC,QAAQ,EAAE;IACjD,6DAA6D;IAC7D,mBAAmB,EAAE,eAAe,CAAC,0BAA0B,CAAC,CAAC,QAAQ,EAAE;IAC3E,0FAA0F;IAC1F,gEAAgE;IAChE,KAAK,EAAE,eAAe,CAAC,QAAQ,EAAE;IACjC,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACrC,SAAS,EAAE,aAAa;CACzB,CAAC,CAAC;AAGH,mGAAmG;AACnG,sGAAsG;AACtG,+FAA+F;AAC/F,yCAAyC;AACzC,MAAM,CAAC,MAAM,qBAAqB,GAAG,4BAA4B,CAAC,IAAI,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;AAGhG,sGAAsG;AACtG,8BAA8B;AAC9B,MAAM,qBAAqB,GAAwC;IACjE,WAAW,EAAE,IAAI;IACjB,MAAM,EAAE,IAAI;IACZ,QAAQ,EAAE,IAAI;IACd,OAAO,EAAE,IAAI;CACd,CAAC;AAEF,8DAA8D;AAC9D,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAuC,CAAC","sourcesContent":["// `userProfiles/{userId}` — the account's profile, one per Firebase Auth uid. Ghosts have none.\n// It is publicly readable (a profile page renders signed out), so it holds nothing personal:\n// email and contact details live in its owner-only `privateData/{userId}` document (BACKEND-105).\n// Plus its `historicalStats/{sportKey}` subcollection.\n\nimport { z } from 'zod';\nimport { THEME_NAMES } from '@ttt-productions/theme-core';\nimport { CONTACT_PHONE_INPUT_FORMAT } from '../input-formats/index.js';\nimport { BasketballPlayerTotalsSchema, UserLifetimeStatsSchema } from './aggregate-stats.js';\nimport { epochMsSchema, textFieldSchema, userStatusSchema } from './atoms.js';\nimport { awardIdSchema } from './catalogs.js';\n\n// A saved theme, typed by theme-core's theme set — the one declaration its provider renders from.\nexport const themeNameSchema = z.enum(THEME_NAMES);\n\n// An award granted to this user. Name and imagery resolve from `awardDefinitions/{awardId}`.\nexport const GrantedAwardSchema = z.object({\n awardId: awardIdSchema,\n grantedAt: epochMsSchema,\n});\nexport type GrantedAward = z.infer<typeof GrantedAwardSchema>;\n\nexport const UserProfileSchema = z.object({\n displayName: z.string(),\n displayName_lowercase: z.string(),\n // Written `active` at registration and by the profile copy; nothing else writes it.\n userStatus: userStatusSchema,\n // Per sport, the career line; career games played is the sum of their games played, derived at\n // read and never stored.\n lifetimeStats: UserLifetimeStatsSchema.optional(),\n grantedAwards: z.array(GrantedAwardSchema).optional(),\n // The awards the account shows beside its name, each one it holds.\n primaryAwardId: awardIdSchema.optional(),\n secondaryAwardId: awardIdSchema.optional(),\n createdAt: epochMsSchema,\n updatedAt: epochMsSchema,\n});\nexport type UserProfile = z.infer<typeof UserProfileSchema>;\n\n// `userProfiles/{userId}/privateData/{userId}` — readable by its owner and by admins; written only\n// by callables.\nexport const UserPrivateDataSchema = z.object({\n email: z.string(),\n // When this login's registration started (`createRegistrationStart`); `registerUser` refuses\n // without it. Absent on an account copied from V1, which registered before the step existed.\n registrationStartedAt: epochMsSchema.optional(),\n // When the orphan-registration cleanup decided to delete this uid's login. Written in the\n // cleanup's eligibility transaction BEFORE the Auth delete, and both registration steps answer\n // `registrationExpired` in their own transactions while it is present, so no registration\n // completes into a login that is about to be deleted. Backend-only.\n orphanDeletionClaimedAt: epochMsSchema.optional(),\n // Pre-fills the contact phone when this user creates a team.\n defaultContactPhone: textFieldSchema(CONTACT_PHONE_INPUT_FORMAT).optional(),\n // The account's copy of the viewer's settings, synced with the device's. Absent means the\n // account has saved nothing and the device's own choice stands.\n theme: themeNameSchema.optional(),\n reducedMotion: z.boolean().optional(),\n updatedAt: epochMsSchema,\n});\nexport type UserPrivateData = z.infer<typeof UserPrivateDataSchema>;\n\n// `userProfiles/{userId}/historicalStats/{sportKey}` — pre-Q-Sports career totals an admin enters,\n// folded into lifetime and hall-of-fame recalculation. Absolute totals, not increments. Basketball is\n// the sport with a baseline, so it is the basketball totals line without FP, which the rebuild\n// derives when it folds the baseline in.\nexport const HistoricalStatsSchema = BasketballPlayerTotalsSchema.omit({ fantasyPoints: true });\nexport type HistoricalStats = z.infer<typeof HistoricalStatsSchema>;\n\n// Every field of a baseline, keyed so the record cannot miss one or name one the schema lacks, in the\n// order an admin enters them.\nconst HISTORICAL_STAT_ENTRY: Record<keyof HistoricalStats, true> = {\n gamesPlayed: true,\n points: true,\n rebounds: true,\n assists: true,\n};\n\n/** A baseline's totals, in the order an admin enters them. */\nexport const HISTORICAL_STAT_KEYS = Object.keys(HISTORICAL_STAT_ENTRY) as readonly (keyof HistoricalStats)[];\n"]}
@@ -7,6 +7,7 @@ export declare const WaiverTemplateSchema: z.ZodObject<{
7
7
  version: z.ZodNumber;
8
8
  createdAt: z.ZodNumber;
9
9
  updatedAt: z.ZodNumber;
10
+ retired: z.ZodBoolean;
10
11
  retiredAt: z.ZodOptional<z.ZodNumber>;
11
12
  lastChosenAt: z.ZodOptional<z.ZodNumber>;
12
13
  }, z.core.$strip>;
@@ -1 +1 @@
1
- {"version":3,"file":"waiver-template.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/waiver-template.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,sBAAsB,aAA0B,CAAC;AAC9D,eAAO,MAAM,iCAAiC,aAA0B,CAAC;AAIzE,eAAO,MAAM,oBAAoB;;;;;;;;iBAc/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAIlE,eAAO,MAAM,2BAA2B;;;;;;iBAOtC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC"}
1
+ {"version":3,"file":"waiver-template.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/waiver-template.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,sBAAsB,aAA0B,CAAC;AAC9D,eAAO,MAAM,iCAAiC,aAA0B,CAAC;AAIzE,eAAO,MAAM,oBAAoB;;;;;;;;;iBAuB7B,CAAC;AACL,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAIlE,eAAO,MAAM,2BAA2B;;;;;;iBAOtC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC"}
@@ -10,12 +10,17 @@ export const waiverTemplateIdSchema = documentIdSegmentSchema;
10
10
  export const waiverTemplateVersionNumberSchema = z.number().int().min(1);
11
11
  // `waiverTemplates/{waiverTemplateId}` — the template as it reads now: its latest published
12
12
  // version's wording and number.
13
- export const WaiverTemplateSchema = z.object({
13
+ export const WaiverTemplateSchema = z
14
+ .object({
14
15
  title: z.string(),
15
16
  waiverText: z.string(),
16
17
  version: waiverTemplateVersionNumberSchema,
17
18
  createdAt: epochMsSchema,
18
19
  updatedAt: epochMsSchema,
20
+ // Whether the template is retired, so the templates offered to a league are one query filter
21
+ // (`retired == false`) rather than a download of every template ever kept. True exactly when
22
+ // `retiredAt` is set.
23
+ retired: z.boolean(),
19
24
  // Set when an admin deletes a template a signature or a closed league still names, or one with
20
25
  // more versions than a delete removes: it is kept for them and offered to no league again. A
21
26
  // template nothing names is deleted outright instead.
@@ -24,6 +29,10 @@ export const WaiverTemplateSchema = z.object({
24
29
  // its own transaction so a delete's read of this document conflicts with that save; it is its own
25
30
  // field so `updatedAt` keeps meaning the template itself changed.
26
31
  lastChosenAt: epochMsSchema.optional(),
32
+ })
33
+ .refine((template) => template.retired === (template.retiredAt !== undefined), {
34
+ message: 'A template is retired exactly when it records when it was retired.',
35
+ path: ['retired'],
27
36
  });
28
37
  // `waiverTemplates/{waiverTemplateId}/waiverTemplateVersions/{versionId}` — one published version,
29
38
  // created once and never changed.
@@ -1 +1 @@
1
- {"version":3,"file":"waiver-template.js","sourceRoot":"","sources":["../../src/doc-schemas/waiver-template.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,EAAE;AACF,mGAAmG;AACnG,+FAA+F;AAC/F,+FAA+F;AAC/F,sDAAsD;AAEtD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAElF,MAAM,CAAC,MAAM,sBAAsB,GAAG,uBAAuB,CAAC;AAC9D,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAEzE,4FAA4F;AAC5F,gCAAgC;AAChC,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,OAAO,EAAE,iCAAiC;IAC1C,SAAS,EAAE,aAAa;IACxB,SAAS,EAAE,aAAa;IACxB,+FAA+F;IAC/F,6FAA6F;IAC7F,sDAAsD;IACtD,SAAS,EAAE,aAAa,CAAC,QAAQ,EAAE;IACnC,kGAAkG;IAClG,kGAAkG;IAClG,kEAAkE;IAClE,YAAY,EAAE,aAAa,CAAC,QAAQ,EAAE;CACvC,CAAC,CAAC;AAGH,mGAAmG;AACnG,kCAAkC;AAClC,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,MAAM,CAAC;IAClD,OAAO,EAAE,iCAAiC;IAC1C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,uDAAuD;IACvD,iBAAiB,EAAE,YAAY,CAAC,QAAQ,EAAE;IAC1C,WAAW,EAAE,aAAa;CAC3B,CAAC,CAAC","sourcesContent":["// Waiver templates: the wording an admin authors for a league's players to sign.\r\n//\r\n// The wording is versioned. Every save that changes it publishes a new version, and each published\r\n// version is its own immutable document — so the exact wording in force when any signature was\r\n// captured still exists however the template has changed since. A signature also keeps its own\r\n// copy of what the signer saw (`SignedWaiverSchema`).\r\n\r\nimport { z } from 'zod';\r\nimport { documentIdSegmentSchema, epochMsSchema, userIdSchema } from './atoms.js';\r\n\r\nexport const waiverTemplateIdSchema = documentIdSegmentSchema;\r\nexport const waiverTemplateVersionNumberSchema = z.number().int().min(1);\r\n\r\n// `waiverTemplates/{waiverTemplateId}` — the template as it reads now: its latest published\r\n// version's wording and number.\r\nexport const WaiverTemplateSchema = z.object({\r\n title: z.string(),\r\n waiverText: z.string(),\r\n version: waiverTemplateVersionNumberSchema,\r\n createdAt: epochMsSchema,\r\n updatedAt: epochMsSchema,\r\n // Set when an admin deletes a template a signature or a closed league still names, or one with\r\n // more versions than a delete removes: it is kept for them and offered to no league again. A\r\n // template nothing names is deleted outright instead.\r\n retiredAt: epochMsSchema.optional(),\r\n // When a league last came to require the template. The league save that chooses it writes this in\r\n // its own transaction so a delete's read of this document conflicts with that save; it is its own\r\n // field so `updatedAt` keeps meaning the template itself changed.\r\n lastChosenAt: epochMsSchema.optional(),\r\n});\r\nexport type WaiverTemplate = z.infer<typeof WaiverTemplateSchema>;\r\n\r\n// `waiverTemplates/{waiverTemplateId}/waiverTemplateVersions/{versionId}` — one published version,\r\n// created once and never changed.\r\nexport const WaiverTemplateVersionSchema = z.object({\r\n version: waiverTemplateVersionNumberSchema,\r\n title: z.string(),\r\n waiverText: z.string(),\r\n // Absent on a version whose author was never recorded.\r\n publishedByUserId: userIdSchema.optional(),\r\n publishedAt: epochMsSchema,\r\n});\r\nexport type WaiverTemplateVersion = z.infer<typeof WaiverTemplateVersionSchema>;\r\n"]}
1
+ {"version":3,"file":"waiver-template.js","sourceRoot":"","sources":["../../src/doc-schemas/waiver-template.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,EAAE;AACF,mGAAmG;AACnG,+FAA+F;AAC/F,+FAA+F;AAC/F,sDAAsD;AAEtD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,uBAAuB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAElF,MAAM,CAAC,MAAM,sBAAsB,GAAG,uBAAuB,CAAC;AAC9D,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAEzE,4FAA4F;AAC5F,gCAAgC;AAChC,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC;KAClC,MAAM,CAAC;IACN,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,OAAO,EAAE,iCAAiC;IAC1C,SAAS,EAAE,aAAa;IACxB,SAAS,EAAE,aAAa;IACxB,6FAA6F;IAC7F,6FAA6F;IAC7F,sBAAsB;IACtB,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;IACpB,+FAA+F;IAC/F,6FAA6F;IAC7F,sDAAsD;IACtD,SAAS,EAAE,aAAa,CAAC,QAAQ,EAAE;IACnC,kGAAkG;IAClG,kGAAkG;IAClG,kEAAkE;IAClE,YAAY,EAAE,aAAa,CAAC,QAAQ,EAAE;CACvC,CAAC;KACD,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,KAAK,CAAC,QAAQ,CAAC,SAAS,KAAK,SAAS,CAAC,EAAE;IAC7E,OAAO,EAAE,oEAAoE;IAC7E,IAAI,EAAE,CAAC,SAAS,CAAC;CAClB,CAAC,CAAC;AAGL,mGAAmG;AACnG,kCAAkC;AAClC,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,MAAM,CAAC;IAClD,OAAO,EAAE,iCAAiC;IAC1C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,uDAAuD;IACvD,iBAAiB,EAAE,YAAY,CAAC,QAAQ,EAAE;IAC1C,WAAW,EAAE,aAAa;CAC3B,CAAC,CAAC","sourcesContent":["// Waiver templates: the wording an admin authors for a league's players to sign.\n//\n// The wording is versioned. Every save that changes it publishes a new version, and each published\n// version is its own immutable document — so the exact wording in force when any signature was\n// captured still exists however the template has changed since. A signature also keeps its own\n// copy of what the signer saw (`SignedWaiverSchema`).\n\nimport { z } from 'zod';\nimport { documentIdSegmentSchema, epochMsSchema, userIdSchema } from './atoms.js';\n\nexport const waiverTemplateIdSchema = documentIdSegmentSchema;\nexport const waiverTemplateVersionNumberSchema = z.number().int().min(1);\n\n// `waiverTemplates/{waiverTemplateId}` — the template as it reads now: its latest published\n// version's wording and number.\nexport const WaiverTemplateSchema = z\n .object({\n title: z.string(),\n waiverText: z.string(),\n version: waiverTemplateVersionNumberSchema,\n createdAt: epochMsSchema,\n updatedAt: epochMsSchema,\n // Whether the template is retired, so the templates offered to a league are one query filter\n // (`retired == false`) rather than a download of every template ever kept. True exactly when\n // `retiredAt` is set.\n retired: z.boolean(),\n // Set when an admin deletes a template a signature or a closed league still names, or one with\n // more versions than a delete removes: it is kept for them and offered to no league again. A\n // template nothing names is deleted outright instead.\n retiredAt: epochMsSchema.optional(),\n // When a league last came to require the template. The league save that chooses it writes this in\n // its own transaction so a delete's read of this document conflicts with that save; it is its own\n // field so `updatedAt` keeps meaning the template itself changed.\n lastChosenAt: epochMsSchema.optional(),\n })\n .refine((template) => template.retired === (template.retiredAt !== undefined), {\n message: 'A template is retired exactly when it records when it was retired.',\n path: ['retired'],\n });\nexport type WaiverTemplate = z.infer<typeof WaiverTemplateSchema>;\n\n// `waiverTemplates/{waiverTemplateId}/waiverTemplateVersions/{versionId}` — one published version,\n// created once and never changed.\nexport const WaiverTemplateVersionSchema = z.object({\n version: waiverTemplateVersionNumberSchema,\n title: z.string(),\n waiverText: z.string(),\n // Absent on a version whose author was never recorded.\n publishedByUserId: userIdSchema.optional(),\n publishedAt: epochMsSchema,\n});\nexport type WaiverTemplateVersion = z.infer<typeof WaiverTemplateVersionSchema>;\n"]}
@@ -20,6 +20,7 @@ export declare const SignedWaiverSchema: z.ZodObject<{
20
20
  coCaptain: "coCaptain";
21
21
  }>>;
22
22
  subjectDisplayNameSnapshot: z.ZodOptional<z.ZodString>;
23
+ witnessDisplayNameSnapshot: z.ZodOptional<z.ZodString>;
23
24
  }, z.core.$strip>;
24
25
  export type SignedWaiver = z.infer<typeof SignedWaiverSchema>;
25
26
  export declare const HardwareItemSchema: z.ZodObject<{
@@ -1 +1 @@
1
- {"version":3,"file":"waivers-and-hardware.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/waivers-and-hardware.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAkBxB,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;iBAiC5B,CAAC;AACJ,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAI9D,eAAO,MAAM,kBAAkB;;;kBAG7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAM9D,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;kBAsBpC,CAAC;AACJ,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC"}
1
+ {"version":3,"file":"waivers-and-hardware.d.ts","sourceRoot":"","sources":["../../src/doc-schemas/waivers-and-hardware.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAkBxB,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;iBA0C5B,CAAC;AACJ,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAI9D,eAAO,MAAM,kBAAkB;;;kBAG7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAM9D,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;kBAsBpC,CAAC;AACJ,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC"}
@@ -28,17 +28,25 @@ export const SignedWaiverSchema = z
28
28
  witnessUserId: userIdSchema.optional(),
29
29
  witnessAuthority: waiverWitnessAuthoritySchema.optional(),
30
30
  subjectDisplayNameSnapshot: z.string().optional(),
31
+ // A V1 witnessed waiver recorded the witness's name as it was at signing, and never the authority
32
+ // or the ghost's name; the copy keeps that name as a named snapshot (ARCH-103) and guesses neither.
33
+ witnessDisplayNameSnapshot: z.string().optional(),
31
34
  })
32
35
  .refine((waiver) => {
33
- const witnessFields = [
34
- waiver.teamId,
35
- waiver.witnessUserId,
36
- waiver.witnessAuthority,
37
- waiver.subjectDisplayNameSnapshot,
38
- ];
39
- const present = witnessFields.filter((field) => field !== undefined).length;
40
- return present === 0 || present === witnessFields.length;
41
- }, { message: "A ghost's waiver carries its team, witness, authority, and name together, or none of them.", path: ['witnessUserId'] });
36
+ const full = [waiver.teamId, waiver.witnessUserId, waiver.witnessAuthority, waiver.subjectDisplayNameSnapshot];
37
+ const legacy = [waiver.teamId, waiver.witnessUserId, waiver.witnessDisplayNameSnapshot];
38
+ const present = (fields) => fields.filter((field) => field !== undefined).length;
39
+ if (present([...full, waiver.witnessDisplayNameSnapshot]) === 0)
40
+ return true;
41
+ if (present(full) === full.length)
42
+ return waiver.witnessDisplayNameSnapshot === undefined;
43
+ return (present(legacy) === legacy.length &&
44
+ waiver.witnessAuthority === undefined &&
45
+ waiver.subjectDisplayNameSnapshot === undefined);
46
+ }, {
47
+ message: "A ghost's waiver carries its team, witness, authority, and name together; or, copied from V1, its team, witness, and the witness's recorded name; or none of them.",
48
+ path: ['witnessUserId'],
49
+ });
42
50
  // One loaned item, as the contract was created with it: its catalog id and name. A contract keeps
43
51
  // what it loaned even if the catalog later changes.
44
52
  export const HardwareItemSchema = z.strictObject({
@@ -1 +1 @@
1
- {"version":3,"file":"waivers-and-hardware.js","sourceRoot":"","sources":["../../src/doc-schemas/waivers-and-hardware.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,mGAAmG;AACnG,4BAA4B;AAE5B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,aAAa,EACb,gCAAgC,EAChC,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,4BAA4B,GAC7B,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,qCAAqC,EACrC,sCAAsC,GACvC,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,iCAAiC,EAAE,MAAM,sBAAsB,CAAC;AAEjG,iGAAiG;AACjG,gGAAgG;AAChG,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC;KAChC,MAAM,CAAC;IACN,QAAQ,EAAE,cAAc;IACxB,MAAM,EAAE,YAAY;IACpB,gBAAgB,EAAE,sBAAsB;IACxC,8FAA8F;IAC9F,2DAA2D;IAC3D,qBAAqB,EAAE,iCAAiC,CAAC,QAAQ,EAAE;IACnE,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE;IAC/B,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE;IAC9B,yFAAyF;IACzF,aAAa,EAAE,sBAAsB;IACrC,QAAQ,EAAE,aAAa;IACvB,8FAA8F;IAC9F,8FAA8F;IAC9F,0FAA0F;IAC1F,MAAM,EAAE,YAAY,CAAC,QAAQ,EAAE;IAC/B,aAAa,EAAE,YAAY,CAAC,QAAQ,EAAE;IACtC,gBAAgB,EAAE,4BAA4B,CAAC,QAAQ,EAAE;IACzD,0BAA0B,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAClD,CAAC;KACD,MAAM,CACL,CAAC,MAAM,EAAE,EAAE;IACT,MAAM,aAAa,GAAG;QACpB,MAAM,CAAC,MAAM;QACb,MAAM,CAAC,aAAa;QACpB,MAAM,CAAC,gBAAgB;QACvB,MAAM,CAAC,0BAA0B;KAClC,CAAC;IACF,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;IAC5E,OAAO,OAAO,KAAK,CAAC,IAAI,OAAO,KAAK,aAAa,CAAC,MAAM,CAAC;AAC3D,CAAC,EACD,EAAE,OAAO,EAAE,4FAA4F,EAAE,IAAI,EAAE,CAAC,eAAe,CAAC,EAAE,CACnI,CAAC;AAGJ,kGAAkG;AAClG,oDAAoD;AACpD,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,YAAY,CAAC;IAC/C,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACxB,CAAC,CAAC;AAGH,sGAAsG;AACtG,mGAAmG;AACnG,sGAAsG;AACtG,mGAAmG;AACnG,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC;KACxC,YAAY,CAAC;IACZ,aAAa,EAAE,YAAY;IAC3B,eAAe,EAAE,YAAY;IAC7B,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5C,MAAM,EAAE,gCAAgC;IACxC,0FAA0F;IAC1F,aAAa,EAAE,sBAAsB,CAAC,QAAQ,EAAE;IAChD,SAAS,EAAE,aAAa;IACxB,QAAQ,EAAE,aAAa,CAAC,QAAQ,EAAE;IAClC,UAAU,EAAE,aAAa,CAAC,QAAQ,EAAE;CACrC,CAAC;KACD,MAAM,CACL,CAAC,QAAQ,EAAE,EAAE,CACX,QAAQ,CAAC,MAAM,KAAK,qCAAqC;IACvD,CAAC,CAAC,QAAQ,CAAC,aAAa,KAAK,SAAS,IAAI,QAAQ,CAAC,QAAQ,KAAK,SAAS;IACzE,CAAC,CAAC,QAAQ,CAAC,aAAa,KAAK,SAAS,IAAI,QAAQ,CAAC,QAAQ,KAAK,SAAS,EAC7E,EAAE,OAAO,EAAE,2EAA2E,EAAE,IAAI,EAAE,CAAC,eAAe,CAAC,EAAE,CAClH;KACA,MAAM,CACL,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,sCAAsC,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,KAAK,SAAS,CAAC,EAClH,EAAE,OAAO,EAAE,kEAAkE,EAAE,IAAI,EAAE,CAAC,YAAY,CAAC,EAAE,CACtG,CAAC","sourcesContent":["// Signed waivers and referee hardware contracts. Signatures are legal artifacts: a signed waiver\r\n// carries the exact wording the signer saw, as named snapshots. The templates they are signed from\r\n// are ./waiver-template.ts.\r\n\r\nimport { z } from 'zod';\r\nimport {\r\n epochMsSchema,\r\n hardwareLoanContractStatusSchema,\r\n leagueIdSchema,\r\n teamIdSchema,\r\n userIdSchema,\r\n waiverWitnessAuthoritySchema,\r\n} from './atoms.js';\r\nimport {\r\n PENDING_HARDWARE_LOAN_CONTRACT_STATUS,\r\n RETURNED_HARDWARE_LOAN_CONTRACT_STATUS,\r\n} from '../types/unions.js';\r\nimport { StorageObjectRefSchema } from './pending-media.js';\r\nimport { waiverTemplateIdSchema, waiverTemplateVersionNumberSchema } from './waiver-template.js';\r\n\r\n// `signedWaivers/{leagueId}_{userId}` — one signed waiver per player per league, never replaced,\r\n// moved, or deleted: a ghost's stays under the ghost's id after the ghost is removed or linked.\r\nexport const SignedWaiverSchema = z\r\n .object({\r\n leagueId: leagueIdSchema,\r\n userId: userIdSchema,\r\n waiverTemplateId: waiverTemplateIdSchema,\r\n // The published version of the template the signature was captured under. A record that names\r\n // no version has its wording snapshot as its whole record.\r\n waiverTemplateVersion: waiverTemplateVersionNumberSchema.optional(),\r\n waiverTitleSnapshot: z.string(),\r\n waiverTextSnapshot: z.string(),\r\n // The kept signature image. Read only through the signature-read callable, never by URL.\r\n signatureFile: StorageObjectRefSchema,\r\n signedAt: epochMsSchema,\r\n // A ghost player's waiver is signed by a witness for the ghost's team: the witness's account,\r\n // the authority they signed under, and the ghost's name at signing — a named snapshot, so the\r\n // record still says whom it was for after the ghost's public identity is gone (ARCH-103).\r\n teamId: teamIdSchema.optional(),\r\n witnessUserId: userIdSchema.optional(),\r\n witnessAuthority: waiverWitnessAuthoritySchema.optional(),\r\n subjectDisplayNameSnapshot: z.string().optional(),\r\n })\r\n .refine(\r\n (waiver) => {\r\n const witnessFields = [\r\n waiver.teamId,\r\n waiver.witnessUserId,\r\n waiver.witnessAuthority,\r\n waiver.subjectDisplayNameSnapshot,\r\n ];\r\n const present = witnessFields.filter((field) => field !== undefined).length;\r\n return present === 0 || present === witnessFields.length;\r\n },\r\n { message: \"A ghost's waiver carries its team, witness, authority, and name together, or none of them.\", path: ['witnessUserId'] },\r\n );\r\nexport type SignedWaiver = z.infer<typeof SignedWaiverSchema>;\r\n\r\n// One loaned item, as the contract was created with it: its catalog id and name. A contract keeps\r\n// what it loaned even if the catalog later changes.\r\nexport const HardwareItemSchema = z.strictObject({\r\n id: z.string().min(1),\r\n name: z.string().min(1),\r\n});\r\nexport type HardwareItem = z.infer<typeof HardwareItemSchema>;\r\n\r\n// `hardwareLoanContracts/{contractId}` — equipment loaned to a referee: who holds it, what they hold,\r\n// and their signature on the loan agreement, a legal artifact. Names resolve from `publicUsers` at\r\n// read time (ARCH-103). `pending` until the referee signs; `loaned` from the signing, which keeps the\r\n// signature for good; `returned` once an admin records the equipment back, the signature retained.\r\nexport const HardwareLoanContractSchema = z\r\n .strictObject({\r\n refereeUserId: userIdSchema,\r\n createdByUserId: userIdSchema,\r\n hardware: z.array(HardwareItemSchema).min(1),\r\n status: hardwareLoanContractStatusSchema,\r\n // The kept signature image. Read only through the signature-read callables, never by URL.\r\n signatureFile: StorageObjectRefSchema.optional(),\r\n createdAt: epochMsSchema,\r\n loanedAt: epochMsSchema.optional(),\r\n returnedAt: epochMsSchema.optional(),\r\n })\r\n .refine(\r\n (contract) =>\r\n contract.status === PENDING_HARDWARE_LOAN_CONTRACT_STATUS\r\n ? contract.signatureFile === undefined && contract.loanedAt === undefined\r\n : contract.signatureFile !== undefined && contract.loanedAt !== undefined,\r\n { message: 'A contract carries its signature and loan date exactly once it is signed.', path: ['signatureFile'] },\r\n )\r\n .refine(\r\n (contract) => (contract.status === RETURNED_HARDWARE_LOAN_CONTRACT_STATUS) === (contract.returnedAt !== undefined),\r\n { message: 'A contract carries its return date exactly while it is returned.', path: ['returnedAt'] },\r\n );\r\nexport type HardwareLoanContract = z.infer<typeof HardwareLoanContractSchema>;\r\n"]}
1
+ {"version":3,"file":"waivers-and-hardware.js","sourceRoot":"","sources":["../../src/doc-schemas/waivers-and-hardware.ts"],"names":[],"mappings":"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","sourcesContent":["// Signed waivers and referee hardware contracts. Signatures are legal artifacts: a signed waiver\n// carries the exact wording the signer saw, as named snapshots. The templates they are signed from\n// are ./waiver-template.ts.\n\nimport { z } from 'zod';\nimport {\n epochMsSchema,\n hardwareLoanContractStatusSchema,\n leagueIdSchema,\n teamIdSchema,\n userIdSchema,\n waiverWitnessAuthoritySchema,\n} from './atoms.js';\nimport {\n PENDING_HARDWARE_LOAN_CONTRACT_STATUS,\n RETURNED_HARDWARE_LOAN_CONTRACT_STATUS,\n} from '../types/unions.js';\nimport { StorageObjectRefSchema } from './pending-media.js';\nimport { waiverTemplateIdSchema, waiverTemplateVersionNumberSchema } from './waiver-template.js';\n\n// `signedWaivers/{leagueId}_{userId}` — one signed waiver per player per league, never replaced,\n// moved, or deleted: a ghost's stays under the ghost's id after the ghost is removed or linked.\nexport const SignedWaiverSchema = z\n .object({\n leagueId: leagueIdSchema,\n userId: userIdSchema,\n waiverTemplateId: waiverTemplateIdSchema,\n // The published version of the template the signature was captured under. A record that names\n // no version has its wording snapshot as its whole record.\n waiverTemplateVersion: waiverTemplateVersionNumberSchema.optional(),\n waiverTitleSnapshot: z.string(),\n waiverTextSnapshot: z.string(),\n // The kept signature image. Read only through the signature-read callable, never by URL.\n signatureFile: StorageObjectRefSchema,\n signedAt: epochMsSchema,\n // A ghost player's waiver is signed by a witness for the ghost's team: the witness's account,\n // the authority they signed under, and the ghost's name at signing — a named snapshot, so the\n // record still says whom it was for after the ghost's public identity is gone (ARCH-103).\n teamId: teamIdSchema.optional(),\n witnessUserId: userIdSchema.optional(),\n witnessAuthority: waiverWitnessAuthoritySchema.optional(),\n subjectDisplayNameSnapshot: z.string().optional(),\n // A V1 witnessed waiver recorded the witness's name as it was at signing, and never the authority\n // or the ghost's name; the copy keeps that name as a named snapshot (ARCH-103) and guesses neither.\n witnessDisplayNameSnapshot: z.string().optional(),\n })\n .refine(\n (waiver) => {\n const full = [waiver.teamId, waiver.witnessUserId, waiver.witnessAuthority, waiver.subjectDisplayNameSnapshot];\n const legacy = [waiver.teamId, waiver.witnessUserId, waiver.witnessDisplayNameSnapshot];\n const present = (fields: readonly unknown[]) => fields.filter((field) => field !== undefined).length;\n if (present([...full, waiver.witnessDisplayNameSnapshot]) === 0) return true;\n if (present(full) === full.length) return waiver.witnessDisplayNameSnapshot === undefined;\n return (\n present(legacy) === legacy.length &&\n waiver.witnessAuthority === undefined &&\n waiver.subjectDisplayNameSnapshot === undefined\n );\n },\n {\n message:\n \"A ghost's waiver carries its team, witness, authority, and name together; or, copied from V1, its team, witness, and the witness's recorded name; or none of them.\",\n path: ['witnessUserId'],\n },\n );\nexport type SignedWaiver = z.infer<typeof SignedWaiverSchema>;\n\n// One loaned item, as the contract was created with it: its catalog id and name. A contract keeps\n// what it loaned even if the catalog later changes.\nexport const HardwareItemSchema = z.strictObject({\n id: z.string().min(1),\n name: z.string().min(1),\n});\nexport type HardwareItem = z.infer<typeof HardwareItemSchema>;\n\n// `hardwareLoanContracts/{contractId}` — equipment loaned to a referee: who holds it, what they hold,\n// and their signature on the loan agreement, a legal artifact. Names resolve from `publicUsers` at\n// read time (ARCH-103). `pending` until the referee signs; `loaned` from the signing, which keeps the\n// signature for good; `returned` once an admin records the equipment back, the signature retained.\nexport const HardwareLoanContractSchema = z\n .strictObject({\n refereeUserId: userIdSchema,\n createdByUserId: userIdSchema,\n hardware: z.array(HardwareItemSchema).min(1),\n status: hardwareLoanContractStatusSchema,\n // The kept signature image. Read only through the signature-read callables, never by URL.\n signatureFile: StorageObjectRefSchema.optional(),\n createdAt: epochMsSchema,\n loanedAt: epochMsSchema.optional(),\n returnedAt: epochMsSchema.optional(),\n })\n .refine(\n (contract) =>\n contract.status === PENDING_HARDWARE_LOAN_CONTRACT_STATUS\n ? contract.signatureFile === undefined && contract.loanedAt === undefined\n : contract.signatureFile !== undefined && contract.loanedAt !== undefined,\n { message: 'A contract carries its signature and loan date exactly once it is signed.', path: ['signatureFile'] },\n )\n .refine(\n (contract) => (contract.status === RETURNED_HARDWARE_LOAN_CONTRACT_STATUS) === (contract.returnedAt !== undefined),\n { message: 'A contract carries its return date exactly while it is returned.', path: ['returnedAt'] },\n );\nexport type HardwareLoanContract = z.infer<typeof HardwareLoanContractSchema>;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ids/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC","sourcesContent":["export * from './compound-ids.js';\r\nexport * from './minted-ids.js';\r\nexport * from './stat-event-ids.js';\r\nexport * from './waiver-template-ids.js';\r\nexport * from './picture-ids.js';\r\nexport * from './notification-ids.js';\r\nexport * from './stats-operation-ids.js';\r\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ids/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC","sourcesContent":["export * from './compound-ids.js';\nexport * from './minted-ids.js';\nexport * from './stat-event-ids.js';\nexport * from './waiver-template-ids.js';\nexport * from './picture-ids.js';\nexport * from './notification-ids.js';\nexport * from './stats-operation-ids.js';\n"]}
@@ -1,6 +1,7 @@
1
1
  export declare const GHOST_USER_ID_PREFIX = "ghost_";
2
2
  export declare function isGhostUserId(userId: string): boolean;
3
3
  export declare function buildGhostUserId(nowMs: number, suffix: string): string;
4
+ export declare function buildGhostUserIdForRequest(requestId: string): string;
4
5
  export declare function buildSportGameId(nowMs: number, suffix: string): string;
5
6
  export declare function buildScheduleWeekId(nowMs: number, suffix: string): string;
6
7
  export declare const BYE_TEAM_ID = "bye";
@@ -1 +1 @@
1
- {"version":3,"file":"minted-ids.d.ts","sourceRoot":"","sources":["../../src/ids/minted-ids.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,oBAAoB,WAAW,CAAC;AAE7C,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtE;AAGD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtE;AAKD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEzE;AAGD,eAAO,MAAM,WAAW,QAAQ,CAAC;AAGjC,eAAO,MAAM,cAAc,QAAQ,CAAC;AAEpC,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEnD"}
1
+ {"version":3,"file":"minted-ids.d.ts","sourceRoot":"","sources":["../../src/ids/minted-ids.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,oBAAoB,WAAW,CAAC;AAE7C,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtE;AAKD,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEpE;AAGD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtE;AAKD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAEzE;AAGD,eAAO,MAAM,WAAW,QAAQ,CAAC;AAGjC,eAAO,MAAM,cAAc,QAAQ,CAAC;AAEpC,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEnD"}
@@ -10,6 +10,12 @@ export function isGhostUserId(userId) {
10
10
  export function buildGhostUserId(nowMs, suffix) {
11
11
  return `${GHOST_USER_ID_PREFIX}${nowMs}_${suffix}`;
12
12
  }
13
+ // The ghost a ghost-add request creates: derived from the request id the client mints once per add
14
+ // and re-sends on every retry, so a retry names the same ghost instead of creating a second one. Its
15
+ // `req_` part never reads as a clock reading, so it cannot collide with a `buildGhostUserId` id.
16
+ export function buildGhostUserIdForRequest(requestId) {
17
+ return `${GHOST_USER_ID_PREFIX}req_${requestId}`;
18
+ }
13
19
  // A new game's id, `{timestamp}_{suffix}`. A copied game keeps the id it was stored under.
14
20
  export function buildSportGameId(nowMs, suffix) {
15
21
  return `${nowMs}_${suffix}`;
@@ -1 +1 @@
1
- {"version":3,"file":"minted-ids.js","sourceRoot":"","sources":["../../src/ids/minted-ids.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,EAAE;AACF,mGAAmG;AACnG,gDAAgD;AAEhD,oGAAoG;AACpG,MAAM,CAAC,MAAM,oBAAoB,GAAG,QAAQ,CAAC;AAE7C,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,OAAO,MAAM,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,MAAc;IAC5D,OAAO,GAAG,oBAAoB,GAAG,KAAK,IAAI,MAAM,EAAE,CAAC;AACrD,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,MAAc;IAC5D,OAAO,GAAG,KAAK,IAAI,MAAM,EAAE,CAAC;AAC9B,CAAC;AAED,+FAA+F;AAC/F,qGAAqG;AACrG,yDAAyD;AACzD,MAAM,UAAU,mBAAmB,CAAC,KAAa,EAAE,MAAc;IAC/D,OAAO,QAAQ,KAAK,IAAI,MAAM,EAAE,CAAC;AACnC,CAAC;AAED,4DAA4D;AAC5D,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC;AAEjC,gGAAgG;AAChG,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAC;AAEpC,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO,MAAM,KAAK,WAAW,CAAC;AAChC,CAAC","sourcesContent":["// Minted identifiers and identity sentinels.\r\n//\r\n// Builders take the clock reading and the random suffix as arguments so they stay pure: the caller\r\n// supplies `Date.now()` and its own randomness.\r\n\r\n// A placeholder player carries a `ghost_`-prefixed id and has a publicUsers document (BACKEND-120).\r\nexport const GHOST_USER_ID_PREFIX = 'ghost_';\r\n\r\nexport function isGhostUserId(userId: string): boolean {\r\n return userId.startsWith(GHOST_USER_ID_PREFIX);\r\n}\r\n\r\nexport function buildGhostUserId(nowMs: number, suffix: string): string {\r\n return `${GHOST_USER_ID_PREFIX}${nowMs}_${suffix}`;\r\n}\r\n\r\n// A new game's id, `{timestamp}_{suffix}`. A copied game keeps the id it was stored under.\r\nexport function buildSportGameId(nowMs: number, suffix: string): string {\r\n return `${nowMs}_${suffix}`;\r\n}\r\n\r\n// A new week's `weekId`, minted by the server when the week is saved. Some stored weeks hold a\r\n// date-derived `week-{YYYY-MM-DD}` id; a minted id never takes that form, and never derives from the\r\n// date, so two weeks starting on one day stay two weeks.\r\nexport function buildScheduleWeekId(nowMs: number, suffix: string): string {\r\n return `week_${nowMs}_${suffix}`;\r\n}\r\n\r\n// The team slot of a bye week. Never a real leagueTeams id.\r\nexport const BYE_TEAM_ID = 'bye';\r\n\r\n// How the bye slot reads wherever a game or a week names it — a matchup, a schedule, a refusal.\r\nexport const BYE_TEAM_LABEL = 'Bye';\r\n\r\nexport function isByeTeamId(teamId: string): boolean {\r\n return teamId === BYE_TEAM_ID;\r\n}\r\n"]}
1
+ {"version":3,"file":"minted-ids.js","sourceRoot":"","sources":["../../src/ids/minted-ids.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,EAAE;AACF,mGAAmG;AACnG,gDAAgD;AAEhD,oGAAoG;AACpG,MAAM,CAAC,MAAM,oBAAoB,GAAG,QAAQ,CAAC;AAE7C,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,OAAO,MAAM,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,MAAc;IAC5D,OAAO,GAAG,oBAAoB,GAAG,KAAK,IAAI,MAAM,EAAE,CAAC;AACrD,CAAC;AAED,mGAAmG;AACnG,qGAAqG;AACrG,iGAAiG;AACjG,MAAM,UAAU,0BAA0B,CAAC,SAAiB;IAC1D,OAAO,GAAG,oBAAoB,OAAO,SAAS,EAAE,CAAC;AACnD,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,MAAc;IAC5D,OAAO,GAAG,KAAK,IAAI,MAAM,EAAE,CAAC;AAC9B,CAAC;AAED,+FAA+F;AAC/F,qGAAqG;AACrG,yDAAyD;AACzD,MAAM,UAAU,mBAAmB,CAAC,KAAa,EAAE,MAAc;IAC/D,OAAO,QAAQ,KAAK,IAAI,MAAM,EAAE,CAAC;AACnC,CAAC;AAED,4DAA4D;AAC5D,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC;AAEjC,gGAAgG;AAChG,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAC;AAEpC,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO,MAAM,KAAK,WAAW,CAAC;AAChC,CAAC","sourcesContent":["// Minted identifiers and identity sentinels.\n//\n// Builders take the clock reading and the random suffix as arguments so they stay pure: the caller\n// supplies `Date.now()` and its own randomness.\n\n// A placeholder player carries a `ghost_`-prefixed id and has a publicUsers document (BACKEND-120).\nexport const GHOST_USER_ID_PREFIX = 'ghost_';\n\nexport function isGhostUserId(userId: string): boolean {\n return userId.startsWith(GHOST_USER_ID_PREFIX);\n}\n\nexport function buildGhostUserId(nowMs: number, suffix: string): string {\n return `${GHOST_USER_ID_PREFIX}${nowMs}_${suffix}`;\n}\n\n// The ghost a ghost-add request creates: derived from the request id the client mints once per add\n// and re-sends on every retry, so a retry names the same ghost instead of creating a second one. Its\n// `req_` part never reads as a clock reading, so it cannot collide with a `buildGhostUserId` id.\nexport function buildGhostUserIdForRequest(requestId: string): string {\n return `${GHOST_USER_ID_PREFIX}req_${requestId}`;\n}\n\n// A new game's id, `{timestamp}_{suffix}`. A copied game keeps the id it was stored under.\nexport function buildSportGameId(nowMs: number, suffix: string): string {\n return `${nowMs}_${suffix}`;\n}\n\n// A new week's `weekId`, minted by the server when the week is saved. Some stored weeks hold a\n// date-derived `week-{YYYY-MM-DD}` id; a minted id never takes that form, and never derives from the\n// date, so two weeks starting on one day stay two weeks.\nexport function buildScheduleWeekId(nowMs: number, suffix: string): string {\n return `week_${nowMs}_${suffix}`;\n}\n\n// The team slot of a bye week. Never a real leagueTeams id.\nexport const BYE_TEAM_ID = 'bye';\n\n// How the bye slot reads wherever a game or a week names it — a matchup, a schedule, a refusal.\nexport const BYE_TEAM_LABEL = 'Bye';\n\nexport function isByeTeamId(teamId: string): boolean {\n return teamId === BYE_TEAM_ID;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"stats-operation-ids.js","sourceRoot":"","sources":["../../src/ids/stats-operation-ids.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,+FAA+F;AAE/F,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,MAAM,iCAAiC,GAAG,cAAc,CAAC;AAEzD,mGAAmG;AACnG,gFAAgF;AAChF,MAAM,UAAU,4BAA4B,CAAC,MAAc;IACzD,OAAO,CAAC,iCAAiC,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;AACjF,CAAC;AAED,MAAM,gCAAgC,GAAG,aAAa,CAAC;AAEvD,gGAAgG;AAChG,kGAAkG;AAClG,8FAA8F;AAC9F,MAAM,UAAU,yBAAyB,CAAC,MAAc,EAAE,WAAmB;IAC3E,OAAO,CAAC,gCAAgC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;AAC7F,CAAC","sourcesContent":["// `statsOperations` ids the server derives from what the operation acts on, so a retried call finds\r\n// the operation it started instead of starting a second one, and no client names the document.\r\n\r\nimport { COMPOUND_ID_SEPARATOR } from './compound-ids.js';\r\n\r\nconst GAME_DELETION_OPERATION_ID_PREFIX = 'gameDeletion';\r\n\r\n// A game is deleted at most once, so its id names the one deletion it can have; a client-minted id\r\n// would let a caller address another action's operation document (BACKEND-102).\r\nexport function buildGameDeletionOperationId(gameId: string): string {\r\n return [GAME_DELETION_OPERATION_ID_PREFIX, gameId].join(COMPOUND_ID_SEPARATOR);\r\n}\r\n\r\nconst GHOST_PLAYER_OPERATION_ID_PREFIX = 'ghostPlayer';\r\n\r\n// A ghost has exactly one operation for both of its ways out — a link to a real account, or its\r\n// removal — so two links of one ghost, or a link and a removal, find the same document and refuse\r\n// each other instead of interleaving. The team is part of it because a link acts on one team.\r\nexport function buildGhostLinkOperationId(teamId: string, ghostUserId: string): string {\r\n return [GHOST_PLAYER_OPERATION_ID_PREFIX, teamId, ghostUserId].join(COMPOUND_ID_SEPARATOR);\r\n}\r\n"]}
1
+ {"version":3,"file":"stats-operation-ids.js","sourceRoot":"","sources":["../../src/ids/stats-operation-ids.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,+FAA+F;AAE/F,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,MAAM,iCAAiC,GAAG,cAAc,CAAC;AAEzD,mGAAmG;AACnG,gFAAgF;AAChF,MAAM,UAAU,4BAA4B,CAAC,MAAc;IACzD,OAAO,CAAC,iCAAiC,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;AACjF,CAAC;AAED,MAAM,gCAAgC,GAAG,aAAa,CAAC;AAEvD,gGAAgG;AAChG,kGAAkG;AAClG,8FAA8F;AAC9F,MAAM,UAAU,yBAAyB,CAAC,MAAc,EAAE,WAAmB;IAC3E,OAAO,CAAC,gCAAgC,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;AAC7F,CAAC","sourcesContent":["// `statsOperations` ids the server derives from what the operation acts on, so a retried call finds\n// the operation it started instead of starting a second one, and no client names the document.\n\nimport { COMPOUND_ID_SEPARATOR } from './compound-ids.js';\n\nconst GAME_DELETION_OPERATION_ID_PREFIX = 'gameDeletion';\n\n// A game is deleted at most once, so its id names the one deletion it can have; a client-minted id\n// would let a caller address another action's operation document (BACKEND-102).\nexport function buildGameDeletionOperationId(gameId: string): string {\n return [GAME_DELETION_OPERATION_ID_PREFIX, gameId].join(COMPOUND_ID_SEPARATOR);\n}\n\nconst GHOST_PLAYER_OPERATION_ID_PREFIX = 'ghostPlayer';\n\n// A ghost has exactly one operation for both of its ways out — a link to a real account, or its\n// removal — so two links of one ghost, or a link and a removal, find the same document and refuse\n// each other instead of interleaving. The team is part of it because a link acts on one team.\nexport function buildGhostLinkOperationId(teamId: string, ghostUserId: string): string {\n return [GHOST_PLAYER_OPERATION_ID_PREFIX, teamId, ghostUserId].join(COMPOUND_ID_SEPARATOR);\n}\n"]}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC","sourcesContent":["export * from './types/index.js';\r\nexport * from './paths/index.js';\r\nexport * from './constants/index.js';\r\nexport * from './utils/index.js';\r\nexport * from './media/index.js';\r\nexport * from './ids/index.js';\r\nexport * from './domain-events/index.js';\r\nexport * from './input-formats/index.js';\r\nexport * from './migration-console/index.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,8BAA8B,CAAC","sourcesContent":["export * from './types/index.js';\nexport * from './paths/index.js';\nexport * from './constants/index.js';\nexport * from './utils/index.js';\nexport * from './media/index.js';\nexport * from './ids/index.js';\nexport * from './domain-events/index.js';\nexport * from './input-formats/index.js';\nexport * from './migration-console/index.js';\n"]}
@@ -170,10 +170,10 @@ export declare const WAIVER_TEMPLATE_TEXT_INPUT_FORMAT: import("@ttt-productions
170
170
  readonly max: 20000;
171
171
  readonly keepAsTyped: true;
172
172
  }>;
173
- /** The landing page's hero title: trimmed, one line, required. */
173
+ /** The landing page's hero title: trimmed, one line; blank shows the default heading. */
174
174
  export declare const LANDING_HERO_TITLE_INPUT_FORMAT: import("@ttt-productions/input-format-core").DeclaredInputFormat<{
175
175
  readonly format: "singleLine";
176
- readonly min: 1;
176
+ readonly min: 0;
177
177
  readonly max: 200;
178
178
  }>;
179
179
  /** The landing page's about text: trimmed, line breaks allowed, empty allowed. */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/input-formats/index.ts"],"names":[],"mappings":"AAwCA;;;GAGG;AACH,eAAO,MAAM,0BAA0B;;;;EAIrC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,+BAA+B;;;;EAI1C,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,sCAAsC;;;;EAIjD,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,oCAAoC;;;;EAI/C,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,sBAAsB;;;;EAIjC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,yBAAyB;;;;EAIpC,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,sBAAsB;;;;EAIjC,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,0BAA0B;;;;EAIrC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,mCAAmC;;;;EAI9C,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,uBAAuB;;;;EAIlC,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,yBAAyB;;;;EAIpC,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,+BAA+B;;;;EAI1C,CAAC;AAEH,yGAAyG;AACzG,eAAO,MAAM,+BAA+B;;;;EAI1C,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,yCAAyC;;;;EAIpD,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,uCAAuC;;;;EAIlD,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,+BAA+B;;;;EAI1C,CAAC;AAEH,kGAAkG;AAClG,eAAO,MAAM,gCAAgC;;;;EAI3C,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,kCAAkC;;;;;EAK7C,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,iCAAiC;;;;;EAK5C,CAAC;AAEH,kEAAkE;AAClE,eAAO,MAAM,+BAA+B;;;;EAI1C,CAAC;AAEH,kFAAkF;AAClF,eAAO,MAAM,+BAA+B;;;;EAI1C,CAAC;AAEH,2EAA2E;AAC3E,eAAO,MAAM,gCAAgC;;;;EAI3C,CAAC;AAEH,qDAAqD;AACrD,eAAO,MAAM,iCAAiC;;;;EAI5C,CAAC;AAEH,gFAAgF;AAChF,eAAO,MAAM,wBAAwB;;;;EAInC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/input-formats/index.ts"],"names":[],"mappings":"AAwCA;;;GAGG;AACH,eAAO,MAAM,0BAA0B;;;;EAIrC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,+BAA+B;;;;EAI1C,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,sCAAsC;;;;EAIjD,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,oCAAoC;;;;EAI/C,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,sBAAsB;;;;EAIjC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,yBAAyB;;;;EAIpC,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,sBAAsB;;;;EAIjC,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,0BAA0B;;;;EAIrC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,mCAAmC;;;;EAI9C,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,uBAAuB;;;;EAIlC,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,yBAAyB;;;;EAIpC,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,+BAA+B;;;;EAI1C,CAAC;AAEH,yGAAyG;AACzG,eAAO,MAAM,+BAA+B;;;;EAI1C,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,yCAAyC;;;;EAIpD,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,uCAAuC;;;;EAIlD,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,+BAA+B;;;;EAI1C,CAAC;AAEH,kGAAkG;AAClG,eAAO,MAAM,gCAAgC;;;;EAI3C,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,kCAAkC;;;;;EAK7C,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,iCAAiC;;;;;EAK5C,CAAC;AAEH,yFAAyF;AACzF,eAAO,MAAM,+BAA+B;;;;EAI1C,CAAC;AAEH,kFAAkF;AAClF,eAAO,MAAM,+BAA+B;;;;EAI1C,CAAC;AAEH,2EAA2E;AAC3E,eAAO,MAAM,gCAAgC;;;;EAI3C,CAAC;AAEH,qDAAqD;AACrD,eAAO,MAAM,iCAAiC;;;;EAI5C,CAAC;AAEH,gFAAgF;AAChF,eAAO,MAAM,wBAAwB;;;;EAInC,CAAC"}
@@ -178,10 +178,10 @@ export const WAIVER_TEMPLATE_TEXT_INPUT_FORMAT = defineInputFormat({
178
178
  max: MAX_WAIVER_TEMPLATE_TEXT_LENGTH,
179
179
  keepAsTyped: true,
180
180
  });
181
- /** The landing page's hero title: trimmed, one line, required. */
181
+ /** The landing page's hero title: trimmed, one line; blank shows the default heading. */
182
182
  export const LANDING_HERO_TITLE_INPUT_FORMAT = defineInputFormat({
183
183
  format: 'singleLine',
184
- min: 1,
184
+ min: 0,
185
185
  max: MAX_LANDING_HERO_TITLE_LENGTH,
186
186
  });
187
187
  /** The landing page's about text: trimmed, line breaks allowed, empty allowed. */
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/input-formats/index.ts"],"names":[],"mappings":"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","sourcesContent":["// The declared formats of the free-text fields a form takes, each built from the limits the field\n// enforces (ARCH-102). ui-core's text inputs and `ConsequenceDialog`'s reason field take only a\n// declaration, never a bare bound, and a field's wire schema is built from the same declaration\n// through `textFieldSchema`, so the form and the wire run the one check and accept exactly the same\n// text. `input-format-core` is server-safe and has no dependencies, so the declarations sit in the\n// package root, which both app roots import.\n\nimport { defineInputFormat } from '@ttt-productions/input-format-core';\nimport {\n MAX_ANNOUNCEMENT_MESSAGE_LENGTH,\n MAX_APP_VERSION_LENGTH,\n MAX_AWARD_NAME_LENGTH,\n MAX_CONTACT_PHONE_LENGTH,\n MAX_DISPLAY_NAME_LENGTH,\n MAX_GAME_LOCATION_MEMO_LENGTH,\n MAX_GAME_LOCATION_NAME_LENGTH,\n MAX_GAME_LOCATION_STREET_ADDRESS_LENGTH,\n MAX_GAME_LOCATION_SUB_LOCATION_LENGTH,\n MAX_GAME_MEMO_LENGTH,\n MAX_LANDING_ABOUT_TEXT_LENGTH,\n MAX_LANDING_HERO_TITLE_LENGTH,\n MAX_LEAGUE_DESCRIPTION_LENGTH,\n MAX_LEAGUE_TITLE_LENGTH,\n MAX_MAINTENANCE_MESSAGE_LENGTH,\n MAX_REPAIR_REASON_LENGTH,\n MAX_SCHEDULE_WEEK_TITLE_LENGTH,\n MAX_TEAM_INVITATION_MESSAGE_LENGTH,\n MAX_TEAM_JOIN_REQUEST_MESSAGE_LENGTH,\n MAX_TEAM_NAME_LENGTH,\n MAX_WAIVER_TEMPLATE_TEXT_LENGTH,\n MAX_WAIVER_TEMPLATE_TITLE_LENGTH,\n MIN_AWARD_NAME_LENGTH,\n MIN_DISPLAY_NAME_LENGTH,\n MIN_LEAGUE_DESCRIPTION_LENGTH,\n MIN_LEAGUE_TITLE_LENGTH,\n MIN_REPAIR_REASON_LENGTH,\n MIN_TEAM_JOIN_REQUEST_MESSAGE_LENGTH,\n MIN_TEAM_NAME_LENGTH,\n} from '../constants/business.js';\n\n/**\n * The reason an admin gives for a repair action, as `repairReasonSchema` reads it: trimmed, then\n * bounded by the repair-reason limits, with any character and line breaks allowed.\n */\nexport const REPAIR_REASON_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: MIN_REPAIR_REASON_LENGTH,\n max: MAX_REPAIR_REASON_LENGTH,\n});\n\n/**\n * The evidence an operator records for a cutover step the console cannot see done — an export's\n * operation name, a revocation's console record: trimmed, then bounded by the repair-reason limits,\n * line breaks allowed.\n */\nexport const MIGRATION_EVIDENCE_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: MIN_REPAIR_REASON_LENGTH,\n max: MAX_REPAIR_REASON_LENGTH,\n});\n\n/**\n * A player's message to the team they ask to join, as `teamJoinRequestMessageSchema` reads it:\n * trimmed, then bounded by the join-request message limits, with any character and line breaks\n * allowed.\n */\nexport const TEAM_JOIN_REQUEST_MESSAGE_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: MIN_TEAM_JOIN_REQUEST_MESSAGE_LENGTH,\n max: MAX_TEAM_JOIN_REQUEST_MESSAGE_LENGTH,\n});\n\n/**\n * The optional note a team sends with an invitation, as `teamInvitationMessageSchema` reads it:\n * trimmed, empty allowed, then bounded by the invitation note limit, line breaks allowed.\n */\nexport const TEAM_INVITATION_MESSAGE_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: 0,\n max: MAX_TEAM_INVITATION_MESSAGE_LENGTH,\n});\n\n/**\n * A scorer's note on one person in a live game (\"red shirt\", \"#9\"), as `gameMemoSchema` reads it:\n * trimmed, one line, empty allowed — an empty memo clears the note — then bounded by the memo cap.\n */\nexport const GAME_MEMO_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: 0,\n max: MAX_GAME_MEMO_LENGTH,\n});\n\n/**\n * A person's display name — an account's, or a ghost player's, as both ghost doors and the admin's\n * ghost captain ask for it — as `displayNameSchema` reads it: trimmed, one line, then bounded by the\n * display-name limits.\n */\nexport const DISPLAY_NAME_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: MIN_DISPLAY_NAME_LENGTH,\n max: MAX_DISPLAY_NAME_LENGTH,\n});\n\n/**\n * A team's name, as `teamNameSchema` reads it at creation and at an admin's rename: trimmed, one\n * line, then bounded by the team-name limits.\n */\nexport const TEAM_NAME_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: MIN_TEAM_NAME_LENGTH,\n max: MAX_TEAM_NAME_LENGTH,\n});\n\n/**\n * The number the league reaches a team on, as `contactPhoneSchema` reads it: trimmed, one line,\n * required, and bounded by the contact-phone cap. It is kept as typed — no format is imposed.\n */\nexport const CONTACT_PHONE_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: 1,\n max: MAX_CONTACT_PHONE_LENGTH,\n});\n\n/**\n * The account's optional default contact phone on the settings page: the contact-phone format with\n * empty allowed. Empty means remove the saved number — the form sends it as\n * `UpdateAccountSettingsInput.defaultContactPhone: null` — and any other value is held to\n * `CONTACT_PHONE_INPUT_FORMAT`'s trim, one line, and cap.\n */\nexport const OPTIONAL_CONTACT_PHONE_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: 0,\n max: MAX_CONTACT_PHONE_LENGTH,\n});\n\n/**\n * An award's name in the catalog, as `awardNameSchema` reads it — at creation, sent with the award's\n * first badge: trimmed, one line, then bounded by the award-name limits.\n */\nexport const AWARD_NAME_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: MIN_AWARD_NAME_LENGTH,\n max: MAX_AWARD_NAME_LENGTH,\n});\n\n/**\n * A league's title, as `leagueTitleSchema` reads it at creation and at the settings edit: trimmed,\n * one line, then bounded by the league-title limits.\n */\nexport const LEAGUE_TITLE_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: MIN_LEAGUE_TITLE_LENGTH,\n max: MAX_LEAGUE_TITLE_LENGTH,\n});\n\n/**\n * A league's description, as `leagueDescriptionSchema` reads it at creation and at the settings\n * edit: trimmed, then bounded by the league-description limits, line breaks allowed.\n */\nexport const LEAGUE_DESCRIPTION_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: MIN_LEAGUE_DESCRIPTION_LENGTH,\n max: MAX_LEAGUE_DESCRIPTION_LENGTH,\n});\n\n/** A venue's name, as `gameLocationNameSchema` reads it: trimmed, one line, required, within its cap. */\nexport const GAME_LOCATION_NAME_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: 1,\n max: MAX_GAME_LOCATION_NAME_LENGTH,\n});\n\n/**\n * A venue's street address, as `gameLocationStreetAddressSchema` reads it: trimmed, one line,\n * required, within its cap.\n */\nexport const GAME_LOCATION_STREET_ADDRESS_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: 1,\n max: MAX_GAME_LOCATION_STREET_ADDRESS_LENGTH,\n});\n\n/**\n * One court, sheet, or room of a venue, as `gameLocationSubLocationSchema` reads it: trimmed, one\n * line, required, within its cap.\n */\nexport const GAME_LOCATION_SUB_LOCATION_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: 1,\n max: MAX_GAME_LOCATION_SUB_LOCATION_LENGTH,\n});\n\n/**\n * A venue's memo, as `gameLocationMemoSchema` reads it: trimmed, line breaks allowed, empty allowed —\n * an empty memo means the venue has none — within its cap.\n */\nexport const GAME_LOCATION_MEMO_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: 0,\n max: MAX_GAME_LOCATION_MEMO_LENGTH,\n});\n\n/** A schedule week's name, as `scheduleWeekTitleSchema` reads it: trimmed, one line, required. */\nexport const SCHEDULE_WEEK_TITLE_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: 1,\n max: MAX_SCHEDULE_WEEK_TITLE_LENGTH,\n});\n\n/**\n * A waiver template's title, as `waiverTemplateTitleSchema` reads it. A waiver is a legal artifact a\n * player signs, so its words are kept exactly as typed; it still cannot be blank.\n */\nexport const WAIVER_TEMPLATE_TITLE_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: 1,\n max: MAX_WAIVER_TEMPLATE_TITLE_LENGTH,\n keepAsTyped: true,\n});\n\n/**\n * A waiver template's wording, as `waiverTemplateTextSchema` reads it: the legal text a player signs,\n * kept exactly as typed, line breaks allowed, never blank.\n */\nexport const WAIVER_TEMPLATE_TEXT_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: 1,\n max: MAX_WAIVER_TEMPLATE_TEXT_LENGTH,\n keepAsTyped: true,\n});\n\n/** The landing page's hero title: trimmed, one line, required. */\nexport const LANDING_HERO_TITLE_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: 1,\n max: MAX_LANDING_HERO_TITLE_LENGTH,\n});\n\n/** The landing page's about text: trimmed, line breaks allowed, empty allowed. */\nexport const LANDING_ABOUT_TEXT_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: 0,\n max: MAX_LANDING_ABOUT_TEXT_LENGTH,\n});\n\n/** The message shown while the app is in maintenance; empty shows none. */\nexport const MAINTENANCE_MESSAGE_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: 0,\n max: MAX_MAINTENANCE_MESSAGE_LENGTH,\n});\n\n/** The site announcement banner; empty clears it. */\nexport const ANNOUNCEMENT_MESSAGE_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: 0,\n max: MAX_ANNOUNCEMENT_MESSAGE_LENGTH,\n});\n\n/** The published app version the version gate compares against; never blank. */\nexport const APP_VERSION_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: 1,\n max: MAX_APP_VERSION_LENGTH,\n});\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/input-formats/index.ts"],"names":[],"mappings":"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","sourcesContent":["// The declared formats of the free-text fields a form takes, each built from the limits the field\n// enforces (ARCH-102). ui-core's text inputs and `ConsequenceDialog`'s reason field take only a\n// declaration, never a bare bound, and a field's wire schema is built from the same declaration\n// through `textFieldSchema`, so the form and the wire run the one check and accept exactly the same\n// text. `input-format-core` is server-safe and has no dependencies, so the declarations sit in the\n// package root, which both app roots import.\n\nimport { defineInputFormat } from '@ttt-productions/input-format-core';\nimport {\n MAX_ANNOUNCEMENT_MESSAGE_LENGTH,\n MAX_APP_VERSION_LENGTH,\n MAX_AWARD_NAME_LENGTH,\n MAX_CONTACT_PHONE_LENGTH,\n MAX_DISPLAY_NAME_LENGTH,\n MAX_GAME_LOCATION_MEMO_LENGTH,\n MAX_GAME_LOCATION_NAME_LENGTH,\n MAX_GAME_LOCATION_STREET_ADDRESS_LENGTH,\n MAX_GAME_LOCATION_SUB_LOCATION_LENGTH,\n MAX_GAME_MEMO_LENGTH,\n MAX_LANDING_ABOUT_TEXT_LENGTH,\n MAX_LANDING_HERO_TITLE_LENGTH,\n MAX_LEAGUE_DESCRIPTION_LENGTH,\n MAX_LEAGUE_TITLE_LENGTH,\n MAX_MAINTENANCE_MESSAGE_LENGTH,\n MAX_REPAIR_REASON_LENGTH,\n MAX_SCHEDULE_WEEK_TITLE_LENGTH,\n MAX_TEAM_INVITATION_MESSAGE_LENGTH,\n MAX_TEAM_JOIN_REQUEST_MESSAGE_LENGTH,\n MAX_TEAM_NAME_LENGTH,\n MAX_WAIVER_TEMPLATE_TEXT_LENGTH,\n MAX_WAIVER_TEMPLATE_TITLE_LENGTH,\n MIN_AWARD_NAME_LENGTH,\n MIN_DISPLAY_NAME_LENGTH,\n MIN_LEAGUE_DESCRIPTION_LENGTH,\n MIN_LEAGUE_TITLE_LENGTH,\n MIN_REPAIR_REASON_LENGTH,\n MIN_TEAM_JOIN_REQUEST_MESSAGE_LENGTH,\n MIN_TEAM_NAME_LENGTH,\n} from '../constants/business.js';\n\n/**\n * The reason an admin gives for a repair action, as `repairReasonSchema` reads it: trimmed, then\n * bounded by the repair-reason limits, with any character and line breaks allowed.\n */\nexport const REPAIR_REASON_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: MIN_REPAIR_REASON_LENGTH,\n max: MAX_REPAIR_REASON_LENGTH,\n});\n\n/**\n * The evidence an operator records for a cutover step the console cannot see done — an export's\n * operation name, a revocation's console record: trimmed, then bounded by the repair-reason limits,\n * line breaks allowed.\n */\nexport const MIGRATION_EVIDENCE_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: MIN_REPAIR_REASON_LENGTH,\n max: MAX_REPAIR_REASON_LENGTH,\n});\n\n/**\n * A player's message to the team they ask to join, as `teamJoinRequestMessageSchema` reads it:\n * trimmed, then bounded by the join-request message limits, with any character and line breaks\n * allowed.\n */\nexport const TEAM_JOIN_REQUEST_MESSAGE_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: MIN_TEAM_JOIN_REQUEST_MESSAGE_LENGTH,\n max: MAX_TEAM_JOIN_REQUEST_MESSAGE_LENGTH,\n});\n\n/**\n * The optional note a team sends with an invitation, as `teamInvitationMessageSchema` reads it:\n * trimmed, empty allowed, then bounded by the invitation note limit, line breaks allowed.\n */\nexport const TEAM_INVITATION_MESSAGE_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: 0,\n max: MAX_TEAM_INVITATION_MESSAGE_LENGTH,\n});\n\n/**\n * A scorer's note on one person in a live game (\"red shirt\", \"#9\"), as `gameMemoSchema` reads it:\n * trimmed, one line, empty allowed — an empty memo clears the note — then bounded by the memo cap.\n */\nexport const GAME_MEMO_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: 0,\n max: MAX_GAME_MEMO_LENGTH,\n});\n\n/**\n * A person's display name — an account's, or a ghost player's, as both ghost doors and the admin's\n * ghost captain ask for it — as `displayNameSchema` reads it: trimmed, one line, then bounded by the\n * display-name limits.\n */\nexport const DISPLAY_NAME_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: MIN_DISPLAY_NAME_LENGTH,\n max: MAX_DISPLAY_NAME_LENGTH,\n});\n\n/**\n * A team's name, as `teamNameSchema` reads it at creation and at an admin's rename: trimmed, one\n * line, then bounded by the team-name limits.\n */\nexport const TEAM_NAME_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: MIN_TEAM_NAME_LENGTH,\n max: MAX_TEAM_NAME_LENGTH,\n});\n\n/**\n * The number the league reaches a team on, as `contactPhoneSchema` reads it: trimmed, one line,\n * required, and bounded by the contact-phone cap. It is kept as typed — no format is imposed.\n */\nexport const CONTACT_PHONE_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: 1,\n max: MAX_CONTACT_PHONE_LENGTH,\n});\n\n/**\n * The account's optional default contact phone on the settings page: the contact-phone format with\n * empty allowed. Empty means remove the saved number — the form sends it as\n * `UpdateAccountSettingsInput.defaultContactPhone: null` — and any other value is held to\n * `CONTACT_PHONE_INPUT_FORMAT`'s trim, one line, and cap.\n */\nexport const OPTIONAL_CONTACT_PHONE_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: 0,\n max: MAX_CONTACT_PHONE_LENGTH,\n});\n\n/**\n * An award's name in the catalog, as `awardNameSchema` reads it — at creation, sent with the award's\n * first badge: trimmed, one line, then bounded by the award-name limits.\n */\nexport const AWARD_NAME_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: MIN_AWARD_NAME_LENGTH,\n max: MAX_AWARD_NAME_LENGTH,\n});\n\n/**\n * A league's title, as `leagueTitleSchema` reads it at creation and at the settings edit: trimmed,\n * one line, then bounded by the league-title limits.\n */\nexport const LEAGUE_TITLE_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: MIN_LEAGUE_TITLE_LENGTH,\n max: MAX_LEAGUE_TITLE_LENGTH,\n});\n\n/**\n * A league's description, as `leagueDescriptionSchema` reads it at creation and at the settings\n * edit: trimmed, then bounded by the league-description limits, line breaks allowed.\n */\nexport const LEAGUE_DESCRIPTION_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: MIN_LEAGUE_DESCRIPTION_LENGTH,\n max: MAX_LEAGUE_DESCRIPTION_LENGTH,\n});\n\n/** A venue's name, as `gameLocationNameSchema` reads it: trimmed, one line, required, within its cap. */\nexport const GAME_LOCATION_NAME_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: 1,\n max: MAX_GAME_LOCATION_NAME_LENGTH,\n});\n\n/**\n * A venue's street address, as `gameLocationStreetAddressSchema` reads it: trimmed, one line,\n * required, within its cap.\n */\nexport const GAME_LOCATION_STREET_ADDRESS_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: 1,\n max: MAX_GAME_LOCATION_STREET_ADDRESS_LENGTH,\n});\n\n/**\n * One court, sheet, or room of a venue, as `gameLocationSubLocationSchema` reads it: trimmed, one\n * line, required, within its cap.\n */\nexport const GAME_LOCATION_SUB_LOCATION_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: 1,\n max: MAX_GAME_LOCATION_SUB_LOCATION_LENGTH,\n});\n\n/**\n * A venue's memo, as `gameLocationMemoSchema` reads it: trimmed, line breaks allowed, empty allowed —\n * an empty memo means the venue has none — within its cap.\n */\nexport const GAME_LOCATION_MEMO_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: 0,\n max: MAX_GAME_LOCATION_MEMO_LENGTH,\n});\n\n/** A schedule week's name, as `scheduleWeekTitleSchema` reads it: trimmed, one line, required. */\nexport const SCHEDULE_WEEK_TITLE_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: 1,\n max: MAX_SCHEDULE_WEEK_TITLE_LENGTH,\n});\n\n/**\n * A waiver template's title, as `waiverTemplateTitleSchema` reads it. A waiver is a legal artifact a\n * player signs, so its words are kept exactly as typed; it still cannot be blank.\n */\nexport const WAIVER_TEMPLATE_TITLE_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: 1,\n max: MAX_WAIVER_TEMPLATE_TITLE_LENGTH,\n keepAsTyped: true,\n});\n\n/**\n * A waiver template's wording, as `waiverTemplateTextSchema` reads it: the legal text a player signs,\n * kept exactly as typed, line breaks allowed, never blank.\n */\nexport const WAIVER_TEMPLATE_TEXT_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: 1,\n max: MAX_WAIVER_TEMPLATE_TEXT_LENGTH,\n keepAsTyped: true,\n});\n\n/** The landing page's hero title: trimmed, one line; blank shows the default heading. */\nexport const LANDING_HERO_TITLE_INPUT_FORMAT = defineInputFormat({\n format: 'singleLine',\n min: 0,\n max: MAX_LANDING_HERO_TITLE_LENGTH,\n});\n\n/** The landing page's about text: trimmed, line breaks allowed, empty allowed. */\nexport const LANDING_ABOUT_TEXT_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: 0,\n max: MAX_LANDING_ABOUT_TEXT_LENGTH,\n});\n\n/** The message shown while the app is in maintenance; empty shows none. */\nexport const MAINTENANCE_MESSAGE_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: 0,\n max: MAX_MAINTENANCE_MESSAGE_LENGTH,\n});\n\n/** The site announcement banner; empty clears it. */\nexport const ANNOUNCEMENT_MESSAGE_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: 0,\n max: MAX_ANNOUNCEMENT_MESSAGE_LENGTH,\n});\n\n/** The published app version the version gate compares against; never blank. */\nexport const APP_VERSION_INPUT_FORMAT = defineInputFormat({\n format: 'none',\n min: 1,\n max: MAX_APP_VERSION_LENGTH,\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"file-origins.js","sourceRoot":"","sources":["../../src/media/file-origins.ts"],"names":[],"mappings":"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","sourcesContent":["// The upload origin registry (MEDIA-001, MEDIA-006). One origin value binds everything an\r\n// upload touches: the picker spec, the staging path and its `storage.rules` cap and content type,\r\n// the callable that accepts the upload, and — for a picture — the processing spec and the owner the\r\n// picture is published to. The generic packages treat an origin id as opaque; the policy is here.\r\n//\r\n// Picture origins are processed into their kind's declared sizes and keep no master. Signature\r\n// origins are kept byte-exact (`preserveOriginal`) by the callable that records them and are never\r\n// processed. Adding an origin is one change across this registry, `storage.rules`, the processor\r\n// routing, and their tests; `storage.rules` restates the caps and content types, and a guard pins it\r\n// to this file.\r\n\r\nimport type { MediaAccept, MediaOriginSpec } from '@ttt-productions/media-schemas';\r\nimport { PICTURE_VARIANT_KEYS } from '../types/unions.js';\r\nimport type { PictureVariantKey } from '../types/unions.js';\r\nimport { PICTURE_ASPECT_RATIOS, pictureAspectRatio } from './picture-aspects.js';\r\nimport type { PictureAspect } from './picture-aspects.js';\r\n\r\nexport const PICTURE_ORIGIN_KEYS = [\r\n 'league-picture',\r\n 'team-picture',\r\n 'landing-picture',\r\n 'location-picture',\r\n 'award-badge',\r\n] as const;\r\nexport type PictureOrigin = (typeof PICTURE_ORIGIN_KEYS)[number];\r\n\r\nexport const SIGNATURE_ORIGIN_KEYS = ['waiver-signature', 'hardware-signature'] as const;\r\nexport type SignatureOrigin = (typeof SIGNATURE_ORIGIN_KEYS)[number];\r\n\r\nexport const FILE_ORIGIN_KEYS = [...PICTURE_ORIGIN_KEYS, ...SIGNATURE_ORIGIN_KEYS] as const;\r\nexport type FileOrigin = PictureOrigin | SignatureOrigin;\r\n\r\nconst MB = 1024 * 1024;\r\n\r\n// The raw cap is an abuse bound: the browser uploads a picture already cropped and shrunk to its\r\n// kind's largest size, so a real upload is far below it.\r\nexport const PICTURE_UPLOAD_MAX_BYTES = 25 * MB;\r\n\r\n// A photo's browser crop and every stored size are JPEG at this quality.\r\nexport const PICTURE_JPEG_QUALITY = 85;\r\n\r\n// What a picture kind is stored as: a photo as JPEG, a badge as PNG, which keeps the transparent\r\n// corners of a badge drawn round.\r\nexport const PICTURE_STORED_FORMAT_KEYS = ['jpeg', 'png'] as const;\r\nexport type PictureStoredFormat = (typeof PICTURE_STORED_FORMAT_KEYS)[number];\r\n\r\n// The cropper's mask: a rectangle, or a circle for a badge — which is how a badge is drawn, though\r\n// the stored image is square.\r\nexport const PICTURE_CROP_SHAPE_KEYS = ['rect', 'round'] as const;\r\nexport type PictureCropShape = (typeof PICTURE_CROP_SHAPE_KEYS)[number];\r\n\r\n// Picture formats the server's byte inspection accepts. Scriptable or unproven formats (svg, heic,\r\n// avif) are not accepted.\r\nexport const PICTURE_ACCEPTED_FORMATS = ['jpeg', 'png', 'gif', 'webp', 'bmp', 'tiff'] as const;\r\n\r\nexport const PICTURE_ACCEPT: MediaAccept = {\r\n kinds: ['image'],\r\n formats: [...PICTURE_ACCEPTED_FORMATS],\r\n};\r\n\r\nexport interface PictureSize {\r\n readonly width: number;\r\n readonly height: number;\r\n}\r\n\r\nexport interface PictureKind {\r\n /** The shape the browser crops to, the server re-crops to, and every display frames. */\r\n readonly aspect: PictureAspect;\r\n /** Each stored size, at the kind's shape. `lg` is also the size the browser crops to. */\r\n readonly sizes: Readonly<Record<PictureVariantKey, PictureSize>>;\r\n /** The format of the browser's crop and of every stored size. */\r\n readonly format: PictureStoredFormat;\r\n readonly cropShape: PictureCropShape;\r\n}\r\n\r\nexport const PICTURE_KINDS = {\r\n 'league-picture': {\r\n aspect: 'landscape',\r\n format: 'jpeg',\r\n cropShape: 'rect',\r\n sizes: { sm: { width: 480, height: 270 }, md: { width: 960, height: 540 }, lg: { width: 1920, height: 1080 } },\r\n },\r\n 'team-picture': {\r\n aspect: 'classic',\r\n format: 'jpeg',\r\n cropShape: 'rect',\r\n sizes: { sm: { width: 480, height: 360 }, md: { width: 960, height: 720 }, lg: { width: 1600, height: 1200 } },\r\n },\r\n 'landing-picture': {\r\n aspect: 'banner',\r\n format: 'jpeg',\r\n cropShape: 'rect',\r\n sizes: { sm: { width: 720, height: 240 }, md: { width: 1440, height: 480 }, lg: { width: 2400, height: 800 } },\r\n },\r\n 'location-picture': {\r\n aspect: 'landscape',\r\n format: 'jpeg',\r\n cropShape: 'rect',\r\n sizes: { sm: { width: 480, height: 270 }, md: { width: 960, height: 540 }, lg: { width: 1280, height: 720 } },\r\n },\r\n // A badge is cropped in a round mask and kept square, at the sizes every award has always had.\r\n 'award-badge': {\r\n aspect: 'square',\r\n format: 'png',\r\n cropShape: 'round',\r\n sizes: { sm: { width: 64, height: 64 }, md: { width: 256, height: 256 }, lg: { width: 512, height: 512 } },\r\n },\r\n} as const satisfies Record<PictureOrigin, PictureKind>;\r\n\r\nfunction pictureOriginSpec(kind: PictureKind): MediaOriginSpec {\r\n const ratio = pictureAspectRatio(kind.aspect);\r\n const { width, height } = PICTURE_ASPECT_RATIOS[kind.aspect];\r\n const variants = PICTURE_VARIANT_KEYS.map((key) => ({\r\n key,\r\n crop: { width: kind.sizes[key].width, height: kind.sizes[key].height, gravity: 'center' as const },\r\n format: kind.format,\r\n ...(kind.format === 'jpeg' ? { quality: PICTURE_JPEG_QUALITY } : {}),\r\n }));\r\n return {\r\n kind: 'image',\r\n accept: PICTURE_ACCEPT,\r\n maxBytes: PICTURE_UPLOAD_MAX_BYTES,\r\n imageCrop: {\r\n aspectRatio: ratio,\r\n outputWidth: kind.sizes.lg.width,\r\n outputHeight: kind.sizes.lg.height,\r\n shape: kind.cropShape,\r\n format: kind.format,\r\n ...(kind.format === 'jpeg' ? { quality: PICTURE_JPEG_QUALITY } : {}),\r\n aspectRatioDisplay: `${width}:${height}`,\r\n },\r\n client: {\r\n allowPick: true,\r\n allowCapturePhoto: true,\r\n allowRecordVideo: false,\r\n allowRecordAudio: false,\r\n },\r\n processing: {\r\n // The server trusts nothing the browser did: an upload that bypassed the app's cropper is\r\n // centre-cropped to the kind's shape (`requiredAspectRatio` with `allowAutoFormat`) before\r\n // every size is cut, and a source smaller than a size is never enlarged.\r\n image: {\r\n kind: 'image',\r\n accept: PICTURE_ACCEPT,\r\n maxBytes: PICTURE_UPLOAD_MAX_BYTES,\r\n requiredAspectRatio: ratio,\r\n allowAutoFormat: true,\r\n image: { variants, stripMetadata: true },\r\n },\r\n },\r\n };\r\n}\r\n\r\n// A signature is drawn on a canvas and exported as PNG, so exactly `image/png` is accepted — no\r\n// other image type, and never the neutral octet-stream lane. It is kept byte-exact by the callable\r\n// that records it, and nothing processes it.\r\nexport const SIGNATURE_UPLOAD_MAX_BYTES = 1 * MB;\r\nexport const SIGNATURE_CONTENT_TYPE = 'image/png';\r\n\r\nexport const SIGNATURE_ACCEPT: MediaAccept = {\r\n kinds: ['file'],\r\n mimes: [SIGNATURE_CONTENT_TYPE],\r\n};\r\n\r\nfunction signatureOriginSpec(): MediaOriginSpec {\r\n return {\r\n kind: 'generic',\r\n accept: SIGNATURE_ACCEPT,\r\n maxBytes: SIGNATURE_UPLOAD_MAX_BYTES,\r\n client: {\r\n allowPick: false,\r\n allowCapturePhoto: false,\r\n allowRecordVideo: false,\r\n allowRecordAudio: false,\r\n },\r\n preserveOriginal: true,\r\n };\r\n}\r\n\r\nexport const MEDIA_ORIGIN_SPECS: Readonly<Record<FileOrigin, MediaOriginSpec>> = {\r\n 'league-picture': pictureOriginSpec(PICTURE_KINDS['league-picture']),\r\n 'team-picture': pictureOriginSpec(PICTURE_KINDS['team-picture']),\r\n 'landing-picture': pictureOriginSpec(PICTURE_KINDS['landing-picture']),\r\n 'location-picture': pictureOriginSpec(PICTURE_KINDS['location-picture']),\r\n 'award-badge': pictureOriginSpec(PICTURE_KINDS['award-badge']),\r\n // Promoted to its kept path by the waiver-signing callable.\r\n 'waiver-signature': signatureOriginSpec(),\r\n // Promoted to its kept path by the hardware contract's signing callable.\r\n 'hardware-signature': signatureOriginSpec(),\r\n};\r\n\r\nexport function isFileOrigin(value: string): value is FileOrigin {\r\n return (FILE_ORIGIN_KEYS as readonly string[]).includes(value);\r\n}\r\n\r\nexport function isPictureOrigin(value: string): value is PictureOrigin {\r\n return (PICTURE_ORIGIN_KEYS as readonly string[]).includes(value);\r\n}\r\n\r\nexport function isSignatureOrigin(value: string): value is SignatureOrigin {\r\n return (SIGNATURE_ORIGIN_KEYS as readonly string[]).includes(value);\r\n}\r\n"]}
1
+ {"version":3,"file":"file-origins.js","sourceRoot":"","sources":["../../src/media/file-origins.ts"],"names":[],"mappings":"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","sourcesContent":["// The upload origin registry (MEDIA-001, MEDIA-006). One origin value binds everything an\n// upload touches: the picker spec, the staging path and its `storage.rules` cap and content type,\n// the callable that accepts the upload, and — for a picture — the processing spec and the owner the\n// picture is published to. The generic packages treat an origin id as opaque; the policy is here.\n//\n// Picture origins are processed into their kind's declared sizes and keep no master. Signature\n// origins are kept byte-exact (`preserveOriginal`) by the callable that records them and are never\n// processed. Adding an origin is one change across this registry, `storage.rules`, the processor\n// routing, and their tests; `storage.rules` restates the caps and content types, and a guard pins it\n// to this file.\n\nimport type { MediaAccept, MediaOriginSpec } from '@ttt-productions/media-schemas';\nimport { PICTURE_VARIANT_KEYS } from '../types/unions.js';\nimport type { PictureVariantKey } from '../types/unions.js';\nimport { PICTURE_ASPECT_RATIOS, pictureAspectRatio } from './picture-aspects.js';\nimport type { PictureAspect } from './picture-aspects.js';\n\nexport const PICTURE_ORIGIN_KEYS = [\n 'league-picture',\n 'team-picture',\n 'landing-picture',\n 'location-picture',\n 'award-badge',\n] as const;\nexport type PictureOrigin = (typeof PICTURE_ORIGIN_KEYS)[number];\n\nexport const SIGNATURE_ORIGIN_KEYS = ['waiver-signature', 'hardware-signature'] as const;\nexport type SignatureOrigin = (typeof SIGNATURE_ORIGIN_KEYS)[number];\n\nexport const FILE_ORIGIN_KEYS = [...PICTURE_ORIGIN_KEYS, ...SIGNATURE_ORIGIN_KEYS] as const;\nexport type FileOrigin = PictureOrigin | SignatureOrigin;\n\nconst MB = 1024 * 1024;\n\n// The raw cap is an abuse bound: the browser uploads a picture already cropped and shrunk to its\n// kind's largest size, so a real upload is far below it.\nexport const PICTURE_UPLOAD_MAX_BYTES = 25 * MB;\n\n// A photo's browser crop and every stored size are JPEG at this quality.\nexport const PICTURE_JPEG_QUALITY = 85;\n\n// What a picture kind is stored as: a photo as JPEG, a badge as PNG, which keeps the transparent\n// corners of a badge drawn round.\nexport const PICTURE_STORED_FORMAT_KEYS = ['jpeg', 'png'] as const;\nexport type PictureStoredFormat = (typeof PICTURE_STORED_FORMAT_KEYS)[number];\n\n// The cropper's mask: a rectangle, or a circle for a badge — which is how a badge is drawn, though\n// the stored image is square.\nexport const PICTURE_CROP_SHAPE_KEYS = ['rect', 'round'] as const;\nexport type PictureCropShape = (typeof PICTURE_CROP_SHAPE_KEYS)[number];\n\n// Picture formats the server's byte inspection accepts. Scriptable or unproven formats (svg, heic,\n// avif) are not accepted.\nexport const PICTURE_ACCEPTED_FORMATS = ['jpeg', 'png', 'gif', 'webp', 'bmp', 'tiff'] as const;\n\nexport const PICTURE_ACCEPT: MediaAccept = {\n kinds: ['image'],\n formats: [...PICTURE_ACCEPTED_FORMATS],\n};\n\nexport interface PictureSize {\n readonly width: number;\n readonly height: number;\n}\n\nexport interface PictureKind {\n /** The shape the browser crops to, the server re-crops to, and every display frames. */\n readonly aspect: PictureAspect;\n /** Each stored size, at the kind's shape. `lg` is also the size the browser crops to. */\n readonly sizes: Readonly<Record<PictureVariantKey, PictureSize>>;\n /** The format of the browser's crop and of every stored size. */\n readonly format: PictureStoredFormat;\n readonly cropShape: PictureCropShape;\n}\n\nexport const PICTURE_KINDS = {\n 'league-picture': {\n aspect: 'landscape',\n format: 'jpeg',\n cropShape: 'rect',\n sizes: { sm: { width: 480, height: 270 }, md: { width: 960, height: 540 }, lg: { width: 1920, height: 1080 } },\n },\n 'team-picture': {\n aspect: 'classic',\n format: 'jpeg',\n cropShape: 'rect',\n sizes: { sm: { width: 480, height: 360 }, md: { width: 960, height: 720 }, lg: { width: 1600, height: 1200 } },\n },\n 'landing-picture': {\n aspect: 'banner',\n format: 'jpeg',\n cropShape: 'rect',\n sizes: { sm: { width: 720, height: 240 }, md: { width: 1440, height: 480 }, lg: { width: 2400, height: 800 } },\n },\n 'location-picture': {\n aspect: 'landscape',\n format: 'jpeg',\n cropShape: 'rect',\n sizes: { sm: { width: 480, height: 270 }, md: { width: 960, height: 540 }, lg: { width: 1280, height: 720 } },\n },\n // A badge is cropped in a round mask and kept square, at the sizes every award has always had.\n 'award-badge': {\n aspect: 'square',\n format: 'png',\n cropShape: 'round',\n sizes: { sm: { width: 64, height: 64 }, md: { width: 256, height: 256 }, lg: { width: 512, height: 512 } },\n },\n} as const satisfies Record<PictureOrigin, PictureKind>;\n\nfunction pictureOriginSpec(kind: PictureKind): MediaOriginSpec {\n const ratio = pictureAspectRatio(kind.aspect);\n const { width, height } = PICTURE_ASPECT_RATIOS[kind.aspect];\n const variants = PICTURE_VARIANT_KEYS.map((key) => ({\n key,\n crop: { width: kind.sizes[key].width, height: kind.sizes[key].height, gravity: 'center' as const },\n format: kind.format,\n ...(kind.format === 'jpeg' ? { quality: PICTURE_JPEG_QUALITY } : {}),\n }));\n return {\n kind: 'image',\n accept: PICTURE_ACCEPT,\n maxBytes: PICTURE_UPLOAD_MAX_BYTES,\n imageCrop: {\n aspectRatio: ratio,\n outputWidth: kind.sizes.lg.width,\n outputHeight: kind.sizes.lg.height,\n shape: kind.cropShape,\n format: kind.format,\n ...(kind.format === 'jpeg' ? { quality: PICTURE_JPEG_QUALITY } : {}),\n aspectRatioDisplay: `${width}:${height}`,\n },\n client: {\n allowPick: true,\n allowCapturePhoto: true,\n allowRecordVideo: false,\n allowRecordAudio: false,\n },\n processing: {\n // The server trusts nothing the browser did: an upload that bypassed the app's cropper is\n // centre-cropped to the kind's shape (`requiredAspectRatio` with `allowAutoFormat`) before\n // every size is cut, and a source smaller than a size is never enlarged.\n image: {\n kind: 'image',\n accept: PICTURE_ACCEPT,\n maxBytes: PICTURE_UPLOAD_MAX_BYTES,\n requiredAspectRatio: ratio,\n allowAutoFormat: true,\n image: { variants, stripMetadata: true },\n },\n },\n };\n}\n\n// A signature is drawn on a canvas and exported as PNG, so exactly `image/png` is accepted — no\n// other image type, and never the neutral octet-stream lane. It is kept byte-exact by the callable\n// that records it, and nothing processes it.\nexport const SIGNATURE_UPLOAD_MAX_BYTES = 1 * MB;\nexport const SIGNATURE_CONTENT_TYPE = 'image/png';\n\nexport const SIGNATURE_ACCEPT: MediaAccept = {\n kinds: ['file'],\n mimes: [SIGNATURE_CONTENT_TYPE],\n};\n\nfunction signatureOriginSpec(): MediaOriginSpec {\n return {\n kind: 'generic',\n accept: SIGNATURE_ACCEPT,\n maxBytes: SIGNATURE_UPLOAD_MAX_BYTES,\n client: {\n allowPick: false,\n allowCapturePhoto: false,\n allowRecordVideo: false,\n allowRecordAudio: false,\n },\n preserveOriginal: true,\n };\n}\n\nexport const MEDIA_ORIGIN_SPECS: Readonly<Record<FileOrigin, MediaOriginSpec>> = {\n 'league-picture': pictureOriginSpec(PICTURE_KINDS['league-picture']),\n 'team-picture': pictureOriginSpec(PICTURE_KINDS['team-picture']),\n 'landing-picture': pictureOriginSpec(PICTURE_KINDS['landing-picture']),\n 'location-picture': pictureOriginSpec(PICTURE_KINDS['location-picture']),\n 'award-badge': pictureOriginSpec(PICTURE_KINDS['award-badge']),\n // Promoted to its kept path by the waiver-signing callable.\n 'waiver-signature': signatureOriginSpec(),\n // Promoted to its kept path by the hardware contract's signing callable.\n 'hardware-signature': signatureOriginSpec(),\n};\n\nexport function isFileOrigin(value: string): value is FileOrigin {\n return (FILE_ORIGIN_KEYS as readonly string[]).includes(value);\n}\n\nexport function isPictureOrigin(value: string): value is PictureOrigin {\n return (PICTURE_ORIGIN_KEYS as readonly string[]).includes(value);\n}\n\nexport function isSignatureOrigin(value: string): value is SignatureOrigin {\n return (SIGNATURE_ORIGIN_KEYS as readonly string[]).includes(value);\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export declare function archiveAllPartialOutcomeMessage(archived: number, notArchived: number): string;
2
+ //# sourceMappingURL=archive-all.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive-all.d.ts","sourceRoot":"","sources":["../../src/notifications/archive-all.ts"],"names":[],"mappings":"AAEA,wBAAgB,+BAA+B,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAE7F"}
@@ -0,0 +1,6 @@
1
+ // How a finished Archive all reads when some cards could not be archived: each failed on its own and
2
+ // stays in the list for a one-at-a-time archive.
3
+ export function archiveAllPartialOutcomeMessage(archived, notArchived) {
4
+ return `Archived ${archived}. ${notArchived} couldn't be archived and ${notArchived === 1 ? 'is' : 'are'} still in the list.`;
5
+ }
6
+ //# sourceMappingURL=archive-all.js.map