@mohasinac/appkit 4.52.5 → 4.53.0

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 (630) hide show
  1. package/dist/.build-stamp.json +4 -4
  2. package/dist/_internal/client/features/sticker-trace/canvas-codec.d.ts +2 -0
  3. package/dist/_internal/client/features/sticker-trace/canvas-codec.js +148 -0
  4. package/dist/_internal/server/features/auctions/actions.js +1 -1
  5. package/dist/_internal/server/features/categories/data.js +23 -7
  6. package/dist/_internal/server/features/checkout/actions.js +10 -3
  7. package/dist/_internal/server/features/checkout/data.d.ts +15 -0
  8. package/dist/_internal/server/features/checkout/data.js +20 -3
  9. package/dist/_internal/server/features/lottery/actions.js +9 -1
  10. package/dist/_internal/server/features/lottery/og.d.ts +40 -0
  11. package/dist/_internal/server/features/lottery/og.js +79 -0
  12. package/dist/_internal/server/features/messages/actions.js +4 -0
  13. package/dist/_internal/server/features/offers/adapters.js +17 -3
  14. package/dist/_internal/server/features/orders/actions.js +7 -2
  15. package/dist/_internal/server/features/raffle/actions.d.ts +19 -0
  16. package/dist/_internal/server/features/raffle/actions.js +25 -0
  17. package/dist/_internal/server/features/reviews/actions.js +1 -1
  18. package/dist/_internal/server/features/reviews/data.d.ts +1 -1
  19. package/dist/_internal/server/features/search/index-build/artifact-store.d.ts +89 -0
  20. package/dist/_internal/server/features/search/index-build/artifact-store.js +208 -0
  21. package/dist/_internal/server/features/search/index-build/build.d.ts +57 -0
  22. package/dist/_internal/server/features/search/index-build/build.js +285 -0
  23. package/dist/_internal/server/features/search/index-build/sources.d.ts +53 -0
  24. package/dist/_internal/server/features/search/index-build/sources.js +385 -0
  25. package/dist/_internal/server/features/search/search-sources.d.ts +0 -15
  26. package/dist/_internal/server/features/search/search-sources.js +142 -7
  27. package/dist/_internal/server/features/seo/robots.js +21 -1
  28. package/dist/_internal/server/features/seo/sitemap.js +1 -1
  29. package/dist/_internal/server/features/shared/listing-data-factory.js +16 -4
  30. package/dist/_internal/server/features/site-settings/adapters.d.ts +1 -1
  31. package/dist/_internal/server/features/site-settings/adapters.js +26 -0
  32. package/dist/_internal/server/features/sticker-trace/actions.d.ts +109 -0
  33. package/dist/_internal/server/features/sticker-trace/actions.js +172 -0
  34. package/dist/_internal/server/features/sticker-trace/adapters.d.ts +80 -0
  35. package/dist/_internal/server/features/sticker-trace/adapters.js +174 -0
  36. package/dist/_internal/server/features/sticker-trace/build-cut-file.d.ts +26 -0
  37. package/dist/_internal/server/features/sticker-trace/build-cut-file.js +127 -0
  38. package/dist/_internal/server/features/sticker-trace/coordinator.d.ts +27 -0
  39. package/dist/_internal/server/features/sticker-trace/coordinator.js +169 -0
  40. package/dist/_internal/server/features/sticker-trace/fanout.d.ts +43 -0
  41. package/dist/_internal/server/features/sticker-trace/fanout.js +180 -0
  42. package/dist/_internal/server/features/sticker-trace/finalizer.d.ts +25 -0
  43. package/dist/_internal/server/features/sticker-trace/finalizer.js +123 -0
  44. package/dist/_internal/server/features/sticker-trace/mosaic-inputs.d.ts +30 -0
  45. package/dist/_internal/server/features/sticker-trace/mosaic-inputs.js +112 -0
  46. package/dist/_internal/server/features/sticker-trace/progress.d.ts +81 -0
  47. package/dist/_internal/server/features/sticker-trace/progress.js +198 -0
  48. package/dist/_internal/server/features/sticker-trace/promote.d.ts +23 -0
  49. package/dist/_internal/server/features/sticker-trace/promote.js +193 -0
  50. package/dist/_internal/server/features/sticker-trace/shard.d.ts +50 -0
  51. package/dist/_internal/server/features/sticker-trace/shard.js +174 -0
  52. package/dist/_internal/server/features/sticker-trace/sheet-actions.d.ts +141 -0
  53. package/dist/_internal/server/features/sticker-trace/sheet-actions.js +279 -0
  54. package/dist/_internal/server/features/sticker-trace/storage.d.ts +135 -0
  55. package/dist/_internal/server/features/sticker-trace/storage.js +282 -0
  56. package/dist/_internal/server/functions/scheduled.d.ts +2 -1
  57. package/dist/_internal/server/functions/scheduled.js +25 -1
  58. package/dist/_internal/server/jobs/core/_event-ref.d.ts +51 -0
  59. package/dist/_internal/server/jobs/core/_event-ref.js +63 -0
  60. package/dist/_internal/server/jobs/core/assignSpinPrize.d.ts +18 -0
  61. package/dist/_internal/server/jobs/core/assignSpinPrize.js +77 -16
  62. package/dist/_internal/server/jobs/core/auctionSettlement.js +13 -4
  63. package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +44 -15
  64. package/dist/_internal/server/jobs/core/bundleStockSync.js +3 -4
  65. package/dist/_internal/server/jobs/core/cleanupRtdbEvents.js +44 -0
  66. package/dist/_internal/server/jobs/core/event-draw-reasons.d.ts +78 -0
  67. package/dist/_internal/server/jobs/core/event-draw-reasons.js +133 -0
  68. package/dist/_internal/server/jobs/core/listingProcessor.js +28 -8
  69. package/dist/_internal/server/jobs/core/onOrderCreate.js +12 -1
  70. package/dist/_internal/server/jobs/core/onScamReportCreate.js +13 -2
  71. package/dist/_internal/server/jobs/core/onScamReportRejected.js +8 -2
  72. package/dist/_internal/server/jobs/core/onScamReportVerified.js +8 -2
  73. package/dist/_internal/server/jobs/core/onStoreWrite.js +11 -4
  74. package/dist/_internal/server/jobs/core/prizeDrawAssignWinner.js +5 -4
  75. package/dist/_internal/server/jobs/core/prizeDrawExpiryReveal.js +1 -4
  76. package/dist/_internal/server/jobs/core/prizeDrawSoldOutReveal.js +1 -2
  77. package/dist/_internal/server/jobs/core/promotions.js +7 -4
  78. package/dist/_internal/server/jobs/core/searchIndexBuild.d.ts +7 -0
  79. package/dist/_internal/server/jobs/core/searchIndexBuild.js +211 -0
  80. package/dist/_internal/server/jobs/core/triggerEventRaffle.d.ts +35 -0
  81. package/dist/_internal/server/jobs/core/triggerEventRaffle.js +213 -31
  82. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +20 -14
  83. package/dist/_internal/server/jobs/handlers/assignSpinPrize.d.ts +8 -0
  84. package/dist/_internal/server/jobs/handlers/assignSpinPrize.js +15 -15
  85. package/dist/_internal/server/jobs/handlers/index.d.ts +1 -0
  86. package/dist/_internal/server/jobs/handlers/index.js +1 -0
  87. package/dist/_internal/server/jobs/handlers/onCategoryWrite.js +18 -0
  88. package/dist/_internal/server/jobs/handlers/onProductWrite.js +18 -0
  89. package/dist/_internal/server/jobs/handlers/onReviewWrite.js +18 -0
  90. package/dist/_internal/server/jobs/handlers/onScamReportUpdate.js +18 -0
  91. package/dist/_internal/server/jobs/handlers/onStoreWrite.js +18 -0
  92. package/dist/_internal/server/jobs/handlers/searchIndexBuild.d.ts +2 -0
  93. package/dist/_internal/server/jobs/handlers/searchIndexBuild.js +2 -0
  94. package/dist/_internal/server/jobs/handlers/triggerEventRaffle.d.ts +8 -0
  95. package/dist/_internal/server/jobs/handlers/triggerEventRaffle.js +15 -6
  96. package/dist/_internal/shared/actions/action-registry.js +29 -0
  97. package/dist/_internal/shared/cache/revalidate-targets.d.ts +0 -1
  98. package/dist/_internal/shared/cache/revalidate-targets.js +10 -8
  99. package/dist/_internal/shared/features/events/config.d.ts +14 -0
  100. package/dist/_internal/shared/features/events/config.js +14 -0
  101. package/dist/_internal/shared/features/notifications/action-url.js +8 -0
  102. package/dist/_internal/shared/features/site-settings/types.d.ts +11 -0
  103. package/dist/_internal/shared/features/sticker-trace/codec.d.ts +81 -0
  104. package/dist/_internal/shared/features/sticker-trace/codec.js +30 -0
  105. package/dist/_internal/shared/features/sticker-trace/config.d.ts +81 -0
  106. package/dist/_internal/shared/features/sticker-trace/config.js +177 -0
  107. package/dist/_internal/shared/features/sticker-trace/cut-contour.d.ts +20 -0
  108. package/dist/_internal/shared/features/sticker-trace/cut-contour.js +60 -0
  109. package/dist/_internal/shared/features/sticker-trace/export/build-export-set.d.ts +65 -0
  110. package/dist/_internal/shared/features/sticker-trace/export/build-export-set.js +176 -0
  111. package/dist/_internal/shared/features/sticker-trace/export/cut-svg.d.ts +56 -0
  112. package/dist/_internal/shared/features/sticker-trace/export/cut-svg.js +120 -0
  113. package/dist/_internal/shared/features/sticker-trace/export/machine-profiles.d.ts +92 -0
  114. package/dist/_internal/shared/features/sticker-trace/export/machine-profiles.js +153 -0
  115. package/dist/_internal/shared/features/sticker-trace/export/nesting.d.ts +51 -0
  116. package/dist/_internal/shared/features/sticker-trace/export/nesting.js +110 -0
  117. package/dist/_internal/shared/features/sticker-trace/export/page-sizes.d.ts +68 -0
  118. package/dist/_internal/shared/features/sticker-trace/export/page-sizes.js +223 -0
  119. package/dist/_internal/shared/features/sticker-trace/export/part-tiling.d.ts +51 -0
  120. package/dist/_internal/shared/features/sticker-trace/export/part-tiling.js +178 -0
  121. package/dist/_internal/shared/features/sticker-trace/export/simplify-budget.d.ts +26 -0
  122. package/dist/_internal/shared/features/sticker-trace/export/simplify-budget.js +134 -0
  123. package/dist/_internal/shared/features/sticker-trace/export/vectorise-art.d.ts +40 -0
  124. package/dist/_internal/shared/features/sticker-trace/export/vectorise-art.js +195 -0
  125. package/dist/_internal/shared/features/sticker-trace/index.d.ts +2 -0
  126. package/dist/_internal/shared/features/sticker-trace/index.js +59 -0
  127. package/dist/_internal/shared/features/sticker-trace/math/catmull-rom.d.ts +11 -0
  128. package/dist/_internal/shared/features/sticker-trace/math/catmull-rom.js +66 -0
  129. package/dist/_internal/shared/features/sticker-trace/math/edt.d.ts +27 -0
  130. package/dist/_internal/shared/features/sticker-trace/math/edt.js +165 -0
  131. package/dist/_internal/shared/features/sticker-trace/math/label.d.ts +15 -0
  132. package/dist/_internal/shared/features/sticker-trace/math/label.js +156 -0
  133. package/dist/_internal/shared/features/sticker-trace/math/marching-squares.d.ts +16 -0
  134. package/dist/_internal/shared/features/sticker-trace/math/marching-squares.js +242 -0
  135. package/dist/_internal/shared/features/sticker-trace/math/morphology.d.ts +46 -0
  136. package/dist/_internal/shared/features/sticker-trace/math/morphology.js +168 -0
  137. package/dist/_internal/shared/features/sticker-trace/math/rasterize-path.d.ts +88 -0
  138. package/dist/_internal/shared/features/sticker-trace/math/rasterize-path.js +286 -0
  139. package/dist/_internal/shared/features/sticker-trace/math/rdp.d.ts +10 -0
  140. package/dist/_internal/shared/features/sticker-trace/math/rdp.js +74 -0
  141. package/dist/_internal/shared/features/sticker-trace/resume.d.ts +50 -0
  142. package/dist/_internal/shared/features/sticker-trace/resume.js +160 -0
  143. package/dist/_internal/shared/features/sticker-trace/trace/cluster.d.ts +20 -0
  144. package/dist/_internal/shared/features/sticker-trace/trace/cluster.js +132 -0
  145. package/dist/_internal/shared/features/sticker-trace/trace/cross-profile.d.ts +28 -0
  146. package/dist/_internal/shared/features/sticker-trace/trace/cross-profile.js +120 -0
  147. package/dist/_internal/shared/features/sticker-trace/trace/flood.d.ts +21 -0
  148. package/dist/_internal/shared/features/sticker-trace/trace/flood.js +104 -0
  149. package/dist/_internal/shared/features/sticker-trace/trace/geometry.d.ts +3 -0
  150. package/dist/_internal/shared/features/sticker-trace/trace/geometry.js +140 -0
  151. package/dist/_internal/shared/features/sticker-trace/trace/line-filter.d.ts +15 -0
  152. package/dist/_internal/shared/features/sticker-trace/trace/line-filter.js +138 -0
  153. package/dist/_internal/shared/features/sticker-trace/trace/merge.d.ts +27 -0
  154. package/dist/_internal/shared/features/sticker-trace/trace/merge.js +187 -0
  155. package/dist/_internal/shared/features/sticker-trace/trace/paper.d.ts +32 -0
  156. package/dist/_internal/shared/features/sticker-trace/trace/paper.js +147 -0
  157. package/dist/_internal/shared/features/sticker-trace/trace/prefilter.d.ts +30 -0
  158. package/dist/_internal/shared/features/sticker-trace/trace/prefilter.js +125 -0
  159. package/dist/_internal/shared/features/sticker-trace/trace/quantise.d.ts +10 -0
  160. package/dist/_internal/shared/features/sticker-trace/trace/quantise.js +153 -0
  161. package/dist/_internal/shared/features/sticker-trace/trace/ridge.d.ts +88 -0
  162. package/dist/_internal/shared/features/sticker-trace/trace/ridge.js +344 -0
  163. package/dist/_internal/shared/features/sticker-trace/trace/segment.d.ts +10 -0
  164. package/dist/_internal/shared/features/sticker-trace/trace/segment.js +251 -0
  165. package/dist/_internal/shared/features/sticker-trace/types.d.ts +197 -0
  166. package/dist/_internal/shared/features/sticker-trace/types.js +49 -0
  167. package/dist/_internal/shared/listing-types/_registry.d.ts +11 -0
  168. package/dist/_internal/shared/listing-types/art/config.d.ts +1 -0
  169. package/dist/_internal/shared/listing-types/art/config.js +1 -0
  170. package/dist/_internal/shared/listing-types/auction/config.d.ts +1 -0
  171. package/dist/_internal/shared/listing-types/auction/config.js +1 -0
  172. package/dist/_internal/shared/listing-types/classified/config.d.ts +1 -0
  173. package/dist/_internal/shared/listing-types/classified/config.js +1 -0
  174. package/dist/_internal/shared/listing-types/digital-code/config.d.ts +1 -0
  175. package/dist/_internal/shared/listing-types/digital-code/config.js +1 -0
  176. package/dist/_internal/shared/listing-types/feature-flags.d.ts +7 -0
  177. package/dist/_internal/shared/listing-types/feature-flags.js +9 -0
  178. package/dist/_internal/shared/listing-types/live/config.d.ts +1 -0
  179. package/dist/_internal/shared/listing-types/live/config.js +1 -0
  180. package/dist/_internal/shared/listing-types/pre-order/config.d.ts +1 -0
  181. package/dist/_internal/shared/listing-types/pre-order/config.js +1 -0
  182. package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +1 -0
  183. package/dist/_internal/shared/listing-types/prize-draw/config.js +1 -0
  184. package/dist/_internal/shared/listing-types/standard/config.d.ts +1 -0
  185. package/dist/_internal/shared/listing-types/standard/config.js +1 -0
  186. package/dist/_internal/shared/listing-types/stickers/config.d.ts +1 -0
  187. package/dist/_internal/shared/listing-types/stickers/config.js +1 -0
  188. package/dist/_internal/shared/media/limits.d.ts +12 -2
  189. package/dist/_internal/shared/media/limits.js +12 -2
  190. package/dist/_internal/shared/search/artifact-url.d.ts +35 -0
  191. package/dist/_internal/shared/search/artifact-url.js +119 -0
  192. package/dist/_internal/shared/search/index-record.d.ts +68 -0
  193. package/dist/_internal/shared/search/index-record.js +96 -0
  194. package/dist/_internal/shared/search/match.d.ts +65 -0
  195. package/dist/_internal/shared/search/match.js +263 -0
  196. package/dist/client.d.ts +8 -7
  197. package/dist/client.js +12 -5
  198. package/dist/configs/eslint.js +22 -2
  199. package/dist/constants/api-endpoints.d.ts +68 -0
  200. package/dist/constants/api-endpoints.js +32 -0
  201. package/dist/constants/field-names.d.ts +7 -1
  202. package/dist/constants/field-names.js +36 -1
  203. package/dist/contracts/repository.d.ts +8 -7
  204. package/dist/contracts/search.d.ts +2 -2
  205. package/dist/contracts/table.d.ts +3 -3
  206. package/dist/contracts/table.js +3 -3
  207. package/dist/core/contact-submissions.repository.js +2 -2
  208. package/dist/core/integration-keys.js +7 -1
  209. package/dist/core/newsletter.repository.js +2 -2
  210. package/dist/core/site-config.js +1 -1
  211. package/dist/errors/error-codes.d.ts +30 -0
  212. package/dist/errors/error-codes.js +30 -0
  213. package/dist/errors/error-display-map.js +40 -1
  214. package/dist/features/account/api/[userId]/addresses/route.js +1 -1
  215. package/dist/features/account/components/UserBidsView.js +1 -1
  216. package/dist/features/account/components/index.d.ts +0 -8
  217. package/dist/features/account/components/index.js +0 -4
  218. package/dist/features/addresses/repository/addresses.repository.d.ts +17 -6
  219. package/dist/features/addresses/repository/addresses.repository.js +65 -9
  220. package/dist/features/addresses/schemas/firestore.d.ts +17 -6
  221. package/dist/features/admin/actions/notification-actions.js +15 -6
  222. package/dist/features/admin/api/bids/route.js +1 -1
  223. package/dist/features/admin/api/coupons/route.js +1 -1
  224. package/dist/features/admin/api/products/route.js +1 -1
  225. package/dist/features/admin/api/reviews/route.js +1 -1
  226. package/dist/features/admin/components/AdminAdEditorView.js +19 -5
  227. package/dist/features/admin/components/AdminAuditLogView.js +1 -1
  228. package/dist/features/admin/components/AdminBlogEditorView.js +0 -1
  229. package/dist/features/admin/components/AdminBlogView.js +1 -1
  230. package/dist/features/admin/components/AdminBrandsView.js +17 -1
  231. package/dist/features/admin/components/AdminCategoryEditorView.js +0 -1
  232. package/dist/features/admin/components/AdminContactView.js +1 -1
  233. package/dist/features/admin/components/AdminEmployeeEditorView.js +1 -3
  234. package/dist/features/admin/components/AdminNewsletterView.js +1 -1
  235. package/dist/features/admin/components/AdminOrdersView.js +9 -2
  236. package/dist/features/admin/components/AdminPayoutsView.js +1 -1
  237. package/dist/features/admin/components/AdminPrizeDrawsView.js +11 -0
  238. package/dist/features/admin/components/AdminProductEditorView.d.ts +10 -1
  239. package/dist/features/admin/components/AdminProductEditorView.js +24 -37
  240. package/dist/features/admin/components/AdminProductsView.js +10 -3
  241. package/dist/features/admin/components/AdminScammersView.js +1 -1
  242. package/dist/features/admin/components/AdminSectionsView.js +21 -5
  243. package/dist/features/admin/components/AdminSessionsView.js +1 -1
  244. package/dist/features/admin/components/AdminSublistingCategoriesView.js +22 -1
  245. package/dist/features/admin/components/AdminTeamView.js +1 -1
  246. package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +0 -1
  247. package/dist/features/admin/components/AdminUsersView.js +1 -1
  248. package/dist/features/admin/components/DataListingView.d.ts +2 -1
  249. package/dist/features/admin/components/DataListingView.js +9 -4
  250. package/dist/features/admin/components/analytics/AdminPageViewsReportView.js +0 -2
  251. package/dist/features/admin/hooks/useAdminListing.d.ts +1 -1
  252. package/dist/features/admin/repository/site-settings.repository.js +8 -3
  253. package/dist/features/admin/schemas/firestore.d.ts +62 -1
  254. package/dist/features/admin/schemas/firestore.js +32 -0
  255. package/dist/features/admin/types/index.d.ts +1 -1
  256. package/dist/features/auctions/actions/bid-actions.d.ts +2 -2
  257. package/dist/features/auctions/actions/bid-actions.js +16 -4
  258. package/dist/features/auctions/api/route.js +1 -1
  259. package/dist/features/auctions/components/AuctionBottomActions.js +4 -0
  260. package/dist/features/auctions/repository/bid.repository.d.ts +46 -4
  261. package/dist/features/auctions/repository/bid.repository.js +114 -13
  262. package/dist/features/auctions/schemas/firestore.d.ts +24 -4
  263. package/dist/features/auctions/schemas/firestore.js +1 -0
  264. package/dist/features/auth/actions/profile-actions.js +30 -4
  265. package/dist/features/auth/components/index.d.ts +0 -1
  266. package/dist/features/auth/components/index.js +0 -1
  267. package/dist/features/auth/repository/session.repository.d.ts +17 -3
  268. package/dist/features/auth/repository/session.repository.js +46 -5
  269. package/dist/features/auth/repository/token.repository.d.ts +27 -4
  270. package/dist/features/auth/repository/token.repository.js +65 -11
  271. package/dist/features/auth/repository/user.repository.d.ts +33 -7
  272. package/dist/features/auth/repository/user.repository.js +100 -15
  273. package/dist/features/auth/schemas/firestore.d.ts +63 -12
  274. package/dist/features/auth/schemas/firestore.js +11 -0
  275. package/dist/features/before-after/api/route.js +1 -1
  276. package/dist/features/blog/components/BlogListView.js +16 -3
  277. package/dist/features/blog/components/BlogPostView.js +1 -1
  278. package/dist/features/blog/schemas/index.d.ts +2 -2
  279. package/dist/features/cart/api/route.js +1 -1
  280. package/dist/features/catalogue/repository/catalogue.repository.d.ts +7 -7
  281. package/dist/features/catalogue/repository/catalogue.repository.js +28 -10
  282. package/dist/features/catalogue/schemas/firestore.d.ts +11 -0
  283. package/dist/features/categories/api/route.js +10 -10
  284. package/dist/features/categories/components/CategoryDetailPageView.js +35 -5
  285. package/dist/features/categories/components/CategorySelectorCreate.js +0 -1
  286. package/dist/features/categories/components/index.d.ts +0 -2
  287. package/dist/features/categories/components/index.js +0 -1
  288. package/dist/features/categories/repository/categories.repository.d.ts +1 -0
  289. package/dist/features/categories/repository/categories.repository.js +31 -1
  290. package/dist/features/categories/schemas/index.d.ts +2 -2
  291. package/dist/features/categories/utils/taxonomy-visual.d.ts +21 -0
  292. package/dist/features/categories/utils/taxonomy-visual.js +58 -0
  293. package/dist/features/checkout/actions/checkout-value-otp-actions.js +8 -1
  294. package/dist/features/collections/api/[slug]/route.js +3 -3
  295. package/dist/features/collections/api/route.js +1 -1
  296. package/dist/features/consultation/api/route.js +1 -1
  297. package/dist/features/consultation/repository/consultations.repository.js +1 -1
  298. package/dist/features/consultation/types/index.d.ts +1 -1
  299. package/dist/features/contact/components/ContactForm.js +1 -3
  300. package/dist/features/corporate/api/route.js +1 -1
  301. package/dist/features/corporate/repository/corporate.repository.js +1 -1
  302. package/dist/features/corporate/types/index.d.ts +1 -1
  303. package/dist/features/cron/jobs/auction-expiry.job.js +1 -1
  304. package/dist/features/cron/jobs/preorder-reminder.job.js +1 -1
  305. package/dist/features/events/actions/event-actions.d.ts +14 -0
  306. package/dist/features/events/actions/event-actions.js +82 -3
  307. package/dist/features/events/api/[id]/route.js +2 -2
  308. package/dist/features/events/components/AdminEventEditorView.js +22 -3
  309. package/dist/features/events/components/AdminEventsView.js +32 -8
  310. package/dist/features/events/components/EventRafflesSection.d.ts +34 -1
  311. package/dist/features/events/components/EventRafflesSection.js +52 -3
  312. package/dist/features/events/components/SpinWheelView.d.ts +2 -2
  313. package/dist/features/events/components/SpinWheelView.js +41 -4
  314. package/dist/features/events/repository/event-entry.repository.d.ts +14 -2
  315. package/dist/features/events/repository/event-entry.repository.js +41 -7
  316. package/dist/features/events/schemas/firestore.d.ts +17 -4
  317. package/dist/features/events/types/index.d.ts +37 -0
  318. package/dist/features/faq/repository/faqs.repository.js +1 -1
  319. package/dist/features/faq/schemas/index.d.ts +5 -2
  320. package/dist/features/faq/schemas/index.js +6 -0
  321. package/dist/features/faq/types/index.d.ts +0 -1
  322. package/dist/features/grouped/components/GroupedListingEditorView.js +17 -2
  323. package/dist/features/homepage/api/carousel/[id]/route.js +1 -1
  324. package/dist/features/homepage/api/carousel/route.js +4 -4
  325. package/dist/features/homepage/api/route.js +2 -2
  326. package/dist/features/homepage/api/sections/route.js +1 -1
  327. package/dist/features/homepage/components/AnnouncementBar.d.ts +1 -9
  328. package/dist/features/homepage/components/AnnouncementBar.js +13 -19
  329. package/dist/features/homepage/components/MarketplaceHomepageView.js +6 -1
  330. package/dist/features/homepage/components/index.d.ts +0 -2
  331. package/dist/features/homepage/components/index.js +0 -1
  332. package/dist/features/homepage/repository/homepage.repository.js +1 -1
  333. package/dist/features/homepage/schemas/firestore.d.ts +6 -0
  334. package/dist/features/homepage/schemas/index.d.ts +10 -10
  335. package/dist/features/layout/AppLayoutShell.d.ts +11 -0
  336. package/dist/features/layout/AppLayoutShell.js +64 -12
  337. package/dist/features/layout/BottomActionsContext.d.ts +16 -0
  338. package/dist/features/layout/BottomActionsContext.js +5 -0
  339. package/dist/features/layout/BottomChrome.js +48 -9
  340. package/dist/features/layout/BottomNavbar.d.ts +14 -0
  341. package/dist/features/layout/BottomNavbar.js +43 -3
  342. package/dist/features/layout/MainNavbar.d.ts +11 -0
  343. package/dist/features/layout/NavbarLayout.d.ts +3 -0
  344. package/dist/features/layout/NavbarLayout.js +88 -11
  345. package/dist/features/layout/SideActionDock.d.ts +1 -0
  346. package/dist/features/layout/SideActionDock.js +219 -0
  347. package/dist/features/layout/TitleBarLayout.js +1 -1
  348. package/dist/features/layout/cta-anchor.d.ts +31 -0
  349. package/dist/features/layout/cta-anchor.js +31 -0
  350. package/dist/features/layout/hooks/useBottomActions.d.ts +7 -0
  351. package/dist/features/layout/hooks/useBottomActions.js +6 -1
  352. package/dist/features/layout/index.d.ts +9 -1
  353. package/dist/features/layout/index.js +9 -1
  354. package/dist/features/layout/useCtaReveal.d.ts +24 -0
  355. package/dist/features/layout/useCtaReveal.js +82 -0
  356. package/dist/features/layout/useHoldToOpen.d.ts +41 -0
  357. package/dist/features/layout/useHoldToOpen.js +84 -0
  358. package/dist/features/lottery/repository/lottery-entry.repository.d.ts +18 -3
  359. package/dist/features/lottery/repository/lottery-entry.repository.js +48 -6
  360. package/dist/features/lottery/schemas/firestore.d.ts +33 -5
  361. package/dist/features/loyalty/api/balance/route.js +1 -1
  362. package/dist/features/loyalty/api/history/route.js +1 -1
  363. package/dist/features/media/MediaImage.js +0 -1
  364. package/dist/features/media/MediaPickerModal.js +7 -1
  365. package/dist/features/media/modals/ImageEditor.js +5 -1
  366. package/dist/features/media/modals/VideoThumbnailSelector.js +17 -1
  367. package/dist/features/media/repository/media-assets.repository.d.ts +19 -0
  368. package/dist/features/media/upload/CameraCapture.js +16 -1
  369. package/dist/features/media/upload/ImageUpload.js +42 -4
  370. package/dist/features/media/upload/MediaUploadField.js +69 -13
  371. package/dist/features/media/upload/downscale-image.d.ts +56 -0
  372. package/dist/features/media/upload/downscale-image.js +150 -0
  373. package/dist/features/messages/components/ConversationThreadView.js +45 -2
  374. package/dist/features/messages/components/MessageSellerButton.d.ts +15 -1
  375. package/dist/features/messages/components/MessageSellerButton.js +10 -2
  376. package/dist/features/messages/schemas/firestore.d.ts +15 -0
  377. package/dist/features/orders/hooks/useOrders.js +4 -2
  378. package/dist/features/orders/repository/orders.repository.d.ts +15 -4
  379. package/dist/features/orders/repository/orders.repository.js +52 -20
  380. package/dist/features/orders/schemas/firestore.d.ts +15 -4
  381. package/dist/features/orders/schemas/index.d.ts +8 -8
  382. package/dist/features/orders/types/index.d.ts +2 -2
  383. package/dist/features/payments/repository/payments.repository.js +2 -2
  384. package/dist/features/payments/repository/payout.repository.d.ts +23 -6
  385. package/dist/features/payments/repository/payout.repository.js +63 -23
  386. package/dist/features/payments/repository/saved-payment-methods.repository.d.ts +17 -6
  387. package/dist/features/payments/repository/saved-payment-methods.repository.js +59 -11
  388. package/dist/features/payments/schemas/firestore.d.ts +14 -3
  389. package/dist/features/payments/schemas/saved-methods-firestore.d.ts +12 -1
  390. package/dist/features/pre-orders/api/[slug]/route.js +1 -1
  391. package/dist/features/pre-orders/api/admin/route.js +1 -1
  392. package/dist/features/pre-orders/api/route.js +1 -1
  393. package/dist/features/pre-orders/repository/pre-orders.repository.d.ts +3 -3
  394. package/dist/features/pre-orders/repository/pre-orders.repository.js +6 -6
  395. package/dist/features/products/api/[id]/route.js +1 -1
  396. package/dist/features/products/components/ListingBottomActions.js +4 -0
  397. package/dist/features/products/components/ProductDetailPageView.js +2 -1
  398. package/dist/features/products/components/ProductGalleryClient.js +2 -2
  399. package/dist/features/products/components/ProductGrid.js +12 -1
  400. package/dist/features/products/components/index.d.ts +0 -2
  401. package/dist/features/products/components/index.js +0 -1
  402. package/dist/features/products/config/listing-type-listing-config.d.ts +0 -3
  403. package/dist/features/products/config/listing-type-listing-config.js +27 -2
  404. package/dist/features/products/constants/listing-tabs.d.ts +9 -0
  405. package/dist/features/products/constants/listing-tabs.js +3 -2
  406. package/dist/features/products/hooks/useProducts.js +2 -2
  407. package/dist/features/products/repository/products.repository.js +13 -1
  408. package/dist/features/products/schemas/index.d.ts +2 -2
  409. package/dist/features/products/types/index.d.ts +1 -1
  410. package/dist/features/promotions/api/route.js +1 -1
  411. package/dist/features/reviews/actions/review-actions.d.ts +6 -6
  412. package/dist/features/reviews/actions/review-actions.js +22 -8
  413. package/dist/features/reviews/components/ReviewDetailPageView.js +13 -1
  414. package/dist/features/reviews/components/ReviewsIndexPageView.js +21 -4
  415. package/dist/features/reviews/repository/reviews.repository.d.ts +19 -7
  416. package/dist/features/reviews/repository/reviews.repository.js +63 -12
  417. package/dist/features/reviews/schemas/firestore.d.ts +13 -2
  418. package/dist/features/reviews/schemas/index.d.ts +2 -2
  419. package/dist/features/scams/actions/scam-actions.js +16 -4
  420. package/dist/features/search/components/SearchResultsPageView.js +2 -1
  421. package/dist/features/search/hooks/useSearchIndex.d.ts +34 -0
  422. package/dist/features/search/hooks/useSearchIndex.js +172 -0
  423. package/dist/features/search/repository/search.repository.js +2 -2
  424. package/dist/features/seller/actions/offer-actions.d.ts +5 -5
  425. package/dist/features/seller/actions/offer-actions.js +38 -8
  426. package/dist/features/seller/actions/seller-actions.js +34 -7
  427. package/dist/features/seller/api/coupons/route.js +1 -1
  428. package/dist/features/seller/api/products/route.js +1 -1
  429. package/dist/features/seller/api/store/route.js +1 -1
  430. package/dist/features/seller/components/SellerBidsView.js +1 -1
  431. package/dist/features/seller/components/SellerCouponsView.js +1 -1
  432. package/dist/features/seller/components/SellerListingTypeView.js +9 -1
  433. package/dist/features/seller/components/SellerOrdersView.js +1 -1
  434. package/dist/features/seller/components/SellerPayoutSettingsView.js +0 -1
  435. package/dist/features/seller/components/SellerPayoutsView.js +1 -1
  436. package/dist/features/seller/components/SellerProductShell.js +0 -1
  437. package/dist/features/seller/components/SellerProductsView.js +1 -1
  438. package/dist/features/seller/components/SellerShippingView.js +0 -1
  439. package/dist/features/seller/components/SellerStorefrontView.js +0 -1
  440. package/dist/features/seller/components/index.d.ts +0 -4
  441. package/dist/features/seller/components/index.js +0 -2
  442. package/dist/features/seller/repository/offer.repository.d.ts +15 -3
  443. package/dist/features/seller/repository/offer.repository.js +43 -7
  444. package/dist/features/seller/schemas/firestore.d.ts +14 -3
  445. package/dist/features/seller/schemas/index.d.ts +4 -4
  446. package/dist/features/seller/schemas/order-forms.d.ts +39 -0
  447. package/dist/features/seller/schemas/order-forms.js +37 -0
  448. package/dist/features/shell/FormShell.js +6 -2
  449. package/dist/features/shell/QuickFormDrawer.js +15 -1
  450. package/dist/features/shipments/components/AdminShipmentEditorView.js +0 -1
  451. package/dist/features/shipments/components/AdminShipmentsView.js +1 -1
  452. package/dist/features/sticker-trace/components/StickerCommitPanel.d.ts +30 -0
  453. package/dist/features/sticker-trace/components/StickerCommitPanel.js +93 -0
  454. package/dist/features/sticker-trace/components/StickerPrintPanel.d.ts +33 -0
  455. package/dist/features/sticker-trace/components/StickerPrintPanel.js +104 -0
  456. package/dist/features/sticker-trace/components/StickerRetryPanel.d.ts +20 -0
  457. package/dist/features/sticker-trace/components/StickerRetryPanel.js +128 -0
  458. package/dist/features/sticker-trace/components/StickerRunHistoryPanel.d.ts +45 -0
  459. package/dist/features/sticker-trace/components/StickerRunHistoryPanel.js +84 -0
  460. package/dist/features/sticker-trace/components/StickerTraceStudio.d.ts +27 -0
  461. package/dist/features/sticker-trace/components/StickerTraceStudio.js +171 -0
  462. package/dist/features/sticker-trace/constants/help-content.d.ts +23 -0
  463. package/dist/features/sticker-trace/constants/help-content.js +172 -0
  464. package/dist/features/sticker-trace/hooks/useLiveTrace.d.ts +27 -0
  465. package/dist/features/sticker-trace/hooks/useLiveTrace.js +160 -0
  466. package/dist/features/sticker-trace/hooks/useStickerTraceProgress.d.ts +22 -0
  467. package/dist/features/sticker-trace/hooks/useStickerTraceProgress.js +106 -0
  468. package/dist/features/sticker-trace/repository/sticker-sheets.repository.d.ts +113 -0
  469. package/dist/features/sticker-trace/repository/sticker-sheets.repository.js +146 -0
  470. package/dist/features/sticker-trace/repository/sticker-trace-runs.repository.d.ts +132 -0
  471. package/dist/features/sticker-trace/repository/sticker-trace-runs.repository.js +174 -0
  472. package/dist/features/sticker-trace/schemas/firestore.d.ts +248 -0
  473. package/dist/features/sticker-trace/schemas/firestore.js +79 -0
  474. package/dist/features/sticker-trace/server.d.ts +8 -0
  475. package/dist/features/sticker-trace/server.js +51 -0
  476. package/dist/features/stores/actions/store-query-actions.d.ts +2 -2
  477. package/dist/features/stores/actions/store-query-actions.js +7 -2
  478. package/dist/features/stores/api/[storeSlug]/auctions/route.js +3 -3
  479. package/dist/features/stores/api/[storeSlug]/products/route.js +3 -3
  480. package/dist/features/stores/api/[storeSlug]/reviews/route.js +1 -1
  481. package/dist/features/stores/api/[storeSlug]/route.js +1 -1
  482. package/dist/features/stores/components/StoreNavTabs.js +17 -2
  483. package/dist/features/stores/manifest.js +8 -4
  484. package/dist/features/support/repository/support.repository.d.ts +14 -3
  485. package/dist/features/support/repository/support.repository.js +93 -13
  486. package/dist/features/support/schemas/firestore.d.ts +16 -5
  487. package/dist/features/tester/seed-data/authored/admin__events-raffles-spin.js +61 -19
  488. package/dist/features/tester/seed-data/authored/buying__browsing-search.js +19 -3
  489. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.d.ts +2 -0
  490. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.js +243 -0
  491. package/dist/features/tester/seed-data/authored/content-discovery__events.js +36 -10
  492. package/dist/features/tester/seed-data/authored/content-discovery__overflowing-pill-rows.d.ts +2 -0
  493. package/dist/features/tester/seed-data/authored/content-discovery__overflowing-pill-rows.js +209 -0
  494. package/dist/features/tester/seed-data/authored/design-ux__header-brand-mark-centring.d.ts +2 -0
  495. package/dist/features/tester/seed-data/authored/design-ux__header-brand-mark-centring.js +90 -0
  496. package/dist/features/tester/seed-data/authored/index.js +8 -0
  497. package/dist/features/tester/seed-data/authored/selling__media-limits.js +19 -17
  498. package/dist/features/tester/seed-data/authored/selling__product-upload-details.js +10 -5
  499. package/dist/features/tester/seed-data/authored/tools__sticker-tracer.d.ts +2 -0
  500. package/dist/features/tester/seed-data/authored/tools__sticker-tracer.js +283 -0
  501. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +192 -22
  502. package/dist/index.d.ts +10 -23
  503. package/dist/index.js +27 -19
  504. package/dist/next/api/routeHandler.js +9 -0
  505. package/dist/next/routing/require-record.d.ts +13 -0
  506. package/dist/next/routing/require-record.js +62 -0
  507. package/dist/next/routing/route-map.d.ts +4 -4
  508. package/dist/next/routing/route-map.js +25 -3
  509. package/dist/providers/db-firebase/base.d.ts +4 -2
  510. package/dist/providers/db-firebase/base.js +21 -5
  511. package/dist/providers/db-firebase/base.repository.d.ts +11 -9
  512. package/dist/providers/db-firebase/base.repository.js +19 -0
  513. package/dist/providers/db-firebase/rtdb-paths.d.ts +12 -0
  514. package/dist/providers/db-firebase/rtdb-paths.js +12 -0
  515. package/dist/react/ErrorBoundary.js +6 -1
  516. package/dist/react/hooks/realtime-event-constants.d.ts +1 -0
  517. package/dist/react/hooks/realtime-event-constants.js +8 -0
  518. package/dist/react/hooks/useEntityDelete.js +5 -1
  519. package/dist/react/hooks/useMessage.js +5 -1
  520. package/dist/repositories/index.d.ts +2 -2
  521. package/dist/repositories/index.js +6 -1
  522. package/dist/schemas/registry.d.ts +13 -20
  523. package/dist/schemas/registry.js +31 -14
  524. package/dist/schemas/webhooks/google-oauth.d.ts +2 -2
  525. package/dist/security/encrypted.d.ts +117 -0
  526. package/dist/security/encrypted.js +100 -0
  527. package/dist/security/index.d.ts +5 -2
  528. package/dist/security/index.js +16 -2
  529. package/dist/security/pii-accessors.d.ts +71 -0
  530. package/dist/security/pii-accessors.js +150 -0
  531. package/dist/security/pii-encrypt.d.ts +0 -8
  532. package/dist/security/pii-encrypt.js +22 -15
  533. package/dist/security/pii-mask.d.ts +18 -0
  534. package/dist/security/pii-mask.js +27 -0
  535. package/dist/seed/_helpers/search-txt-wrappers.d.ts +6 -6
  536. package/dist/seed/_helpers/search-txt-wrappers.js +22 -0
  537. package/dist/seed/addresses-seed-data.d.ts +2 -2
  538. package/dist/seed/authenticity-knowledge-seed-data.d.ts +34 -0
  539. package/dist/seed/authenticity-knowledge-seed-data.js +1277 -0
  540. package/dist/seed/bids-seed-data.d.ts +2 -2
  541. package/dist/seed/bids-seed-data.js +23 -2
  542. package/dist/seed/events-seed-data.d.ts +2 -2
  543. package/dist/seed/events-seed-data.js +5 -0
  544. package/dist/seed/faq-seed-data.js +175 -5
  545. package/dist/seed/homepage-sections-seed-data.js +39 -23
  546. package/dist/seed/index.d.ts +1 -0
  547. package/dist/seed/index.js +1 -0
  548. package/dist/seed/lottery-entries-seed-data.d.ts +2 -2
  549. package/dist/seed/offers-seed-data.d.ts +2 -2
  550. package/dist/seed/offers-seed-data.js +1 -1
  551. package/dist/seed/orders-seed-data.d.ts +2 -2
  552. package/dist/seed/payouts-seed-data.d.ts +2 -2
  553. package/dist/seed/payouts-seed-data.js +1 -1
  554. package/dist/seed/reviews-seed-data.d.ts +1 -2
  555. package/dist/seed/seed-purpose.js +7 -0
  556. package/dist/seed/sessions-seed-data.d.ts +2 -2
  557. package/dist/seed/sessions-seed-data.js +5 -0
  558. package/dist/seed/site-settings-seed-data.js +1 -1
  559. package/dist/seed/support-tickets-seed-data.d.ts +2 -2
  560. package/dist/seed/support-tickets-seed-data.js +1 -1
  561. package/dist/seed/users-seed-data.d.ts +2 -2
  562. package/dist/seed/users-seed-data.js +1 -1
  563. package/dist/seo/json-ld.js +5 -1
  564. package/dist/server.d.ts +18 -3
  565. package/dist/server.js +59 -3
  566. package/dist/styles.css +237 -1
  567. package/dist/tailwind-utilities.css +1 -1
  568. package/dist/ui/components/Button.js +7 -1
  569. package/dist/ui/components/FilterChipGroup.d.ts +11 -0
  570. package/dist/ui/components/FilterChipGroup.js +1 -1
  571. package/dist/ui/components/ImageGallery.js +6 -1
  572. package/dist/ui/components/ListingLayout.js +14 -8
  573. package/dist/ui/components/OverflowRow.d.ts +92 -0
  574. package/dist/ui/components/OverflowRow.js +203 -0
  575. package/dist/ui/components/OverflowRow.style.css +235 -0
  576. package/dist/ui/components/RecordDetailModal.js +14 -1
  577. package/dist/ui/components/RowActionMenu.js +5 -1
  578. package/dist/ui/components/SideDrawer.js +5 -1
  579. package/dist/ui/components/SideModal.js +9 -1
  580. package/dist/ui/components/TabBarShell.d.ts +12 -1
  581. package/dist/ui/components/TabBarShell.js +3 -2
  582. package/dist/ui/components/Tabs.js +36 -24
  583. package/dist/ui/components/Toast.d.ts +3 -24
  584. package/dist/ui/components/Toast.js +2 -19
  585. package/dist/ui/components/TopBannerPortal.d.ts +15 -0
  586. package/dist/ui/components/TopBannerPortal.js +19 -0
  587. package/dist/ui/components/UnsavedChangesModal.js +5 -1
  588. package/dist/ui/components/index.style.css +1 -0
  589. package/dist/ui/components/row-collapse.d.ts +15 -0
  590. package/dist/ui/components/row-collapse.js +127 -0
  591. package/dist/ui/components/toast-context.d.ts +63 -0
  592. package/dist/ui/components/toast-context.js +48 -0
  593. package/dist/ui/components/top-banner-slot.d.ts +37 -0
  594. package/dist/ui/components/top-banner-slot.js +45 -0
  595. package/dist/ui/icons/icon-registry.d.ts +6 -0
  596. package/dist/ui/icons/icon-registry.js +17 -1
  597. package/dist/ui/index.d.ts +2 -0
  598. package/dist/ui/index.js +1 -0
  599. package/dist/utils/array.helper.d.ts +2 -2
  600. package/dist/utils/array.helper.js +5 -5
  601. package/dist/utils/id-generators.d.ts +6 -0
  602. package/dist/utils/id-generators.js +10 -0
  603. package/dist/utils/media-url.js +0 -2
  604. package/dist/utils/search-txt-builders.d.ts +28 -4
  605. package/dist/utils/search-txt-builders.js +41 -1
  606. package/dist/validation/schemas.d.ts +8 -8
  607. package/package.json +6 -2
  608. package/scripts/seed-cli.mjs +3 -0
  609. package/dist/features/account/components/UserAddressesView.d.ts +0 -13
  610. package/dist/features/account/components/UserAddressesView.js +0 -5
  611. package/dist/features/account/components/UserNotificationsView.d.ts +0 -15
  612. package/dist/features/account/components/UserNotificationsView.js +0 -12
  613. package/dist/features/account/components/UserSettingsView.d.ts +0 -16
  614. package/dist/features/account/components/UserSettingsView.js +0 -13
  615. package/dist/features/account/components/UserSupportView.d.ts +0 -3
  616. package/dist/features/account/components/UserSupportView.js +0 -166
  617. package/dist/features/admin/components/DemoSeedView.d.ts +0 -11
  618. package/dist/features/admin/components/DemoSeedView.js +0 -5
  619. package/dist/features/auth/components/AuthStatusPanel.d.ts +0 -10
  620. package/dist/features/auth/components/AuthStatusPanel.js +0 -22
  621. package/dist/features/categories/components/CategoryProductsView.d.ts +0 -45
  622. package/dist/features/categories/components/CategoryProductsView.js +0 -21
  623. package/dist/features/homepage/components/HowItWorksInfoView.d.ts +0 -36
  624. package/dist/features/homepage/components/HowItWorksInfoView.js +0 -10
  625. package/dist/features/layout/BottomActions.d.ts +0 -1
  626. package/dist/features/layout/BottomActions.js +0 -311
  627. package/dist/features/products/components/ProductsView.d.ts +0 -6
  628. package/dist/features/products/components/ProductsView.js +0 -5
  629. package/dist/features/seller/components/SellerStoreView.d.ts +0 -8
  630. package/dist/features/seller/components/SellerStoreView.js +0 -8
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "stampVersion": 1,
3
- "version": "4.52.5",
4
- "head": "7b24e76346651ca12f0a941e0d1ca87bb173a242",
3
+ "version": "4.53.0",
4
+ "head": "78e72eb24243b0ee3afea21614fbbadee45d2b51",
5
5
  "branch": "main",
6
- "dirty": true,
7
- "builtAt": "2026-10-16T16:23:26.992Z"
6
+ "dirty": false,
7
+ "builtAt": "2026-10-19T12:44:44.499Z"
8
8
  }
@@ -0,0 +1,2 @@
1
+ import type { ImageCodec } from "../../../shared/features/sticker-trace/codec";
2
+ export declare const canvasCodec: ImageCodec;
@@ -0,0 +1,148 @@
1
+ "use client";
2
+ /*
3
+ * One message, three throw sites. A 2d context is only ever null when the
4
+ * browser refuses the canvas outright (memory pressure, or a hardened
5
+ * environment), so all three mean the same thing and should read the same.
6
+ */
7
+ const NO_CONTEXT = "OffscreenCanvas 2d context unavailable";
8
+ /** RGBA out of a canvas, in exactly the layout DecodedRaster promises. */
9
+ function toRaster(bitmap, dpi) {
10
+ const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
11
+ const ctx = canvas.getContext("2d", { willReadFrequently: true });
12
+ if (!ctx)
13
+ throw new Error(NO_CONTEXT);
14
+ ctx.drawImage(bitmap, 0, 0);
15
+ const data = ctx.getImageData(0, 0, bitmap.width, bitmap.height).data;
16
+ bitmap.close();
17
+ return {
18
+ width: canvas.width,
19
+ height: canvas.height,
20
+ data: new Uint8Array(data.buffer),
21
+ ...(dpi !== undefined ? { dpi } : {}),
22
+ };
23
+ }
24
+ async function encode(canvas, format) {
25
+ const type = format === "webp" ? "image/webp" : "image/png";
26
+ const blob = await canvas.convertToBlob({ type, ...(format === "webp" ? { quality: 0.82 } : {}) });
27
+ return { bytes: new Uint8Array(await blob.arrayBuffer()), contentType: type };
28
+ }
29
+ function canvasOf(raster) {
30
+ const canvas = new OffscreenCanvas(raster.width, raster.height);
31
+ const ctx = canvas.getContext("2d");
32
+ if (!ctx)
33
+ throw new Error(NO_CONTEXT);
34
+ ctx.putImageData(new ImageData(new Uint8ClampedArray(raster.data), raster.width, raster.height), 0, 0);
35
+ return canvas;
36
+ }
37
+ export const canvasCodec = {
38
+ /**
39
+ * 🛑 `declaredDpi` is ALWAYS absent here, and that is the one real asymmetry
40
+ * with the sharp codec.
41
+ *
42
+ * sharp reads the file's density header; a browser exposes no such API, and
43
+ * parsing EXIF/pHYs by hand would be a second metadata implementation whose
44
+ * disagreements with sharp nobody would notice. So the browser reports
45
+ * dimensions only — which costs nothing, because the operator confirms dpi
46
+ * anyway (five of the nine reference scans declare 72 or 96, an encoder
47
+ * default rather than a measurement) and a sheet with no trustworthy dpi
48
+ * already renders `bboxMm: null` rather than a fabricated figure.
49
+ *
50
+ * Also NOT header-only, unlike sharp's: `createImageBitmap` decodes. A
51
+ * browser cannot read a header without decoding, so this is dimensions at
52
+ * the cost of a decode — acceptable for one file the user just picked, and
53
+ * the reason the server probe exists for the upload path.
54
+ */
55
+ async probe(source) {
56
+ const bitmap = await createImageBitmap(new Blob([source]));
57
+ const result = { width: bitmap.width, height: bitmap.height };
58
+ bitmap.close();
59
+ return result;
60
+ },
61
+ async decode(source, opts) {
62
+ const blob = new Blob([source]);
63
+ // Probe dimensions first so the resize preserves aspect ratio and never
64
+ // ENLARGES — upscaling would invent sub-pixel detail the ridge detector
65
+ // would then find cut lines in.
66
+ const probe = await createImageBitmap(blob);
67
+ const longEdge = Math.max(probe.width, probe.height);
68
+ probe.close();
69
+ if (longEdge <= opts.maxLongEdge) {
70
+ return toRaster(await createImageBitmap(blob));
71
+ }
72
+ const k = opts.maxLongEdge / longEdge;
73
+ return toRaster(await createImageBitmap(blob, {
74
+ resizeWidth: Math.max(1, Math.round(probe.width * k)),
75
+ resizeHeight: Math.max(1, Math.round(probe.height * k)),
76
+ resizeQuality: "high",
77
+ }));
78
+ },
79
+ /**
80
+ * No resize — a tile is already bounded by the caller, and the `max` tier
81
+ * tiles precisely so it can read native pixels.
82
+ */
83
+ async decodeTile(source, tile) {
84
+ return toRaster(await createImageBitmap(new Blob([source]), {
85
+ sx: tile.x,
86
+ sy: tile.y,
87
+ sw: tile.width,
88
+ sh: tile.height,
89
+ }));
90
+ },
91
+ async encodePng(raster) {
92
+ return encode(canvasOf(raster), "png");
93
+ },
94
+ async encodePngRegion(source, region, alpha) {
95
+ const expected = region.width * region.height;
96
+ if (alpha.length !== expected) {
97
+ // Loud, matching the sharp codec: a silent mismatch yields a part with a
98
+ // plausible outline and the wrong transparency, invisible until it is cut.
99
+ throw new Error(`alpha mask is ${alpha.length} px, expected ${expected} for ${region.width}x${region.height}`);
100
+ }
101
+ const raster = await this.decodeTile(source, region);
102
+ const px = raster.data;
103
+ for (let i = 0; i < expected; i++)
104
+ px[i * 4 + 3] = alpha[i];
105
+ return encode(canvasOf({ width: region.width, height: region.height, data: px }), "png");
106
+ },
107
+ async encodePreview(source, opts) {
108
+ const raster = await this.decode(source, { maxLongEdge: opts.maxLongEdge });
109
+ return encode(canvasOf(raster), opts.format);
110
+ },
111
+ /**
112
+ * Uniform-cell grid, identical in layout to the sharp codec's — the frames
113
+ * map is a contract the review UI reads, so the two must agree on geometry
114
+ * even though they agree on nothing about how they draw.
115
+ */
116
+ async encodeAtlas(tiles, opts) {
117
+ if (tiles.length === 0) {
118
+ // A zero-part run is a real outcome; a valid 1x1 beats throwing.
119
+ return {
120
+ image: await encode(new OffscreenCanvas(1, 1), "png"),
121
+ frames: {},
122
+ };
123
+ }
124
+ const cols = Math.ceil(Math.sqrt(tiles.length));
125
+ const rows = Math.ceil(tiles.length / cols);
126
+ const cell = Math.max(1, Math.min(Math.floor(opts.maxLongEdge / cols), ...tiles.map((t) => Math.max(t.raster.width, t.raster.height))));
127
+ const canvas = new OffscreenCanvas(cols * cell, rows * cell);
128
+ const ctx = canvas.getContext("2d");
129
+ if (!ctx)
130
+ throw new Error(NO_CONTEXT);
131
+ const frames = {};
132
+ for (let i = 0; i < tiles.length; i++) {
133
+ const t = tiles[i];
134
+ const left = (i % cols) * cell;
135
+ const top = Math.floor(i / cols) * cell;
136
+ // `fit: inside` equivalent — preserve aspect, never enlarge.
137
+ const k = Math.min(cell / t.raster.width, cell / t.raster.height, 1);
138
+ const w = Math.max(1, Math.round(t.raster.width * k));
139
+ const h = Math.max(1, Math.round(t.raster.height * k));
140
+ ctx.drawImage(canvasOf(t.raster), left, top, w, h);
141
+ // The frame is the tile's ACTUAL size, not the cell: a wide sticker does
142
+ // not fill a square cell, and a client slicing by `cell` would include
143
+ // its neighbours' padding.
144
+ frames[t.ordinal] = { x: left, y: top, width: w, height: h };
145
+ }
146
+ return { image: await encode(canvas, "png"), frames };
147
+ },
148
+ };
@@ -31,7 +31,7 @@ export async function placeBidAction(input) {
31
31
  // marking included. It cost a full-collection query and an exception per
32
32
  // bid placed, and the real `setWinningBid(bid.id, …)` below already marks
33
33
  // every other bid for this product as outbid.)
34
- const bid = await bidRepository.create({
34
+ const bid = await bidRepository.createBid({
35
35
  productId: auctionId,
36
36
  productTitle: product.title ?? auctionId,
37
37
  userId: user.uid,
@@ -63,11 +63,27 @@ export const getCategoryTree = cache(async (rootId) => {
63
63
  });
64
64
  /** Flat category list for sitemap generation. */
65
65
  export const listSitemapCategories = cache(async () => {
66
- return categoriesRepository
67
- .list({ filters: "isActive==true", sorts: "-updatedAt", page: 1, pageSize: CATEGORIES_SITEMAP_LIMIT })
68
- .then((r) => {
69
- const docs = r.data ?? [];
70
- return docs.map(({ slug, updatedAt }) => ({ slug, updatedAt }));
71
- })
72
- .catch(() => []);
66
+ /*
67
+ * 🛑 `safeRead`, not `.catch(() => [])`. This function feeds the SITEMAP,
68
+ * so a swallowed Firestore failure publishes an empty category sitemap to
69
+ * crawlers and nothing anywhere says why — the single worst place in the
70
+ * app for a failure that reads as "there is no data". Root Cause #81 is
71
+ * what a quietly wrong sitemap costs.
72
+ *
73
+ * The fallback is still `[]` (a sitemap must render), but the degradation
74
+ * is now a `DEGRADED_READ` row instead of silence. The file already used
75
+ * `safeRead` a few lines up; this site was simply missed.
76
+ */
77
+ const r = await safeRead(() => categoriesRepository.list({
78
+ filters: "isActive==true",
79
+ sorts: "-updatedAt",
80
+ page: 1,
81
+ pageSize: CATEGORIES_SITEMAP_LIMIT,
82
+ }), {
83
+ route: "sitemap",
84
+ key: "categories.listSitemapCategories",
85
+ fallback: null,
86
+ });
87
+ const docs = r?.data ?? [];
88
+ return docs.map(({ slug, updatedAt }) => ({ slug, updatedAt }));
73
89
  });
@@ -618,7 +618,7 @@ async function createOrderForGroup(group, orderType, ctx) {
618
618
  // create-vs-create axis of Root Cause #39, and these two functions have
619
619
  // already drifted once before (add-on fees, Root Cause #65).
620
620
  const sourceContext = await buildOrderSourceContext(firstItem, firstProduct, orderType);
621
- const order = await unitOfWork.orders.create({
621
+ const order = await unitOfWork.orders.createOrder({
622
622
  productId: firstItem.productId,
623
623
  productTitle: firstItem.productTitle,
624
624
  userId: uid,
@@ -1478,7 +1478,7 @@ async function createPhonePeGroupOrder(group, orderType, ctx) {
1478
1478
  // create-vs-create axis of Root Cause #39, and these two functions have
1479
1479
  // already drifted once before (add-on fees, Root Cause #65).
1480
1480
  const sourceContext = await buildOrderSourceContext(firstItem, group[0].product, orderType);
1481
- const order = await unitOfWork.orders.create({
1481
+ const order = await unitOfWork.orders.createOrder({
1482
1482
  productId: firstItem.productId,
1483
1483
  productTitle: firstItem.productTitle,
1484
1484
  userId: uid,
@@ -1654,8 +1654,15 @@ export async function verifyAndPlacePhonePeOrderAction(input) {
1654
1654
  let userEmail = input.userEmail;
1655
1655
  if (userName === undefined || userEmail === undefined) {
1656
1656
  const userDoc = await userRepository.findById(uid);
1657
+ /*
1658
+ * 🛑 Revealed: `createOrder` encrypts `userEmail`, so handing it the
1659
+ * ciphertext this read returns would double-encrypt it and make the
1660
+ * buyer's address on the order undecryptable. `displayName` is not PII and
1661
+ * needs no reveal.
1662
+ */
1663
+ const userPlain = userDoc ? userRepository.revealUser(userDoc) : null;
1657
1664
  userName = userName ?? userDoc?.displayName ?? "Customer";
1658
- userEmail = userEmail ?? userDoc?.email ?? "";
1665
+ userEmail = userEmail ?? userPlain?.email ?? "";
1659
1666
  }
1660
1667
  const addressId = input.addressId ?? intent?.addressId;
1661
1668
  const notes = input.notes ?? intent?.notes;
@@ -1,4 +1,19 @@
1
1
  import type { AddressDocument } from "../../../../features/account/schemas/index";
2
+ /**
3
+ * Flatten an address into the one-line string stored on
4
+ * `OrderDocument.shippingAddress` and printed on invoices and labels.
5
+ *
6
+ * 🛑 Reveals INSIDE the function, deliberately, rather than asking its two
7
+ * callers to.
8
+ *
9
+ * `AddressDocument` is ciphertext-by-default, and `shippingAddress` is NOT a
10
+ * PII field — so joining the stored values froze three `enc:v1:` blobs into one
11
+ * string that is no longer a valid envelope and can never be decrypted. It is
12
+ * then printed on every invoice, shipping label and order-confirmation email.
13
+ *
14
+ * Doing it here rather than at `actions.ts:1279` and `:2506` is the point: a
15
+ * third caller gets it right by construction instead of by remembering.
16
+ */
2
17
  export declare function formatShippingAddress(a: AddressDocument): string;
3
18
  export interface CheckoutOrderResult {
4
19
  orderIds: string[];
@@ -1,8 +1,25 @@
1
+ import { ADDRESS_PII_FIELDS, revealPii } from "../../../../security/index.js";
2
+ /**
3
+ * Flatten an address into the one-line string stored on
4
+ * `OrderDocument.shippingAddress` and printed on invoices and labels.
5
+ *
6
+ * 🛑 Reveals INSIDE the function, deliberately, rather than asking its two
7
+ * callers to.
8
+ *
9
+ * `AddressDocument` is ciphertext-by-default, and `shippingAddress` is NOT a
10
+ * PII field — so joining the stored values froze three `enc:v1:` blobs into one
11
+ * string that is no longer a valid envelope and can never be decrypted. It is
12
+ * then printed on every invoice, shipping label and order-confirmation email.
13
+ *
14
+ * Doing it here rather than at `actions.ts:1279` and `:2506` is the point: a
15
+ * third caller gets it right by construction instead of by remembering.
16
+ */
1
17
  export function formatShippingAddress(a) {
18
+ const plain = revealPii(a, ADDRESS_PII_FIELDS);
2
19
  const parts = [
3
- a.fullName,
4
- a.addressLine1,
5
- a.addressLine2,
20
+ plain.fullName,
21
+ plain.addressLine1,
22
+ plain.addressLine2,
6
23
  a.landmark,
7
24
  a.city,
8
25
  a.state,
@@ -117,7 +117,15 @@ export async function submitLotteryPullAction(input) {
117
117
  });
118
118
  return { assignedSlot: chosen, userLotteryNumber: nextNumber };
119
119
  });
120
- // Create the entry document outside the transaction (acceptable — slot is already booked)
120
+ /*
121
+ * Create the entry document outside the transaction (acceptable — slot is
122
+ * already booked).
123
+ *
124
+ * Typed `LotteryEntryPlain`: this is PLAINTEXT from the session and the
125
+ * request body, and `createEntry` encrypts it. The document type now says
126
+ * `Encrypted<string>`, so annotating this `LotteryEntryDocument` is a
127
+ * compile error — correctly, because the values here are not ciphertext.
128
+ */
121
129
  const entryData = {
122
130
  sourceType: data.sourceType,
123
131
  ...(data.sourceType === "event" ? { eventId: sourceId } : { productId: sourceId }),
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Lottery OG image renderer.
3
+ *
4
+ * ## Why this did not exist
5
+ *
6
+ * `lottery/[id]` was the single entry in `verify-og-coverage`'s
7
+ * `OG_KNOWN_GAPS` — the one public dynamic detail page shipping without an
8
+ * `opengraph-image.tsx`, carried as a baseline since 2026-05-23 with the note
9
+ * "OG image follows in a follow-up". Metadata already resolved
10
+ * (`buildLotteryMetadata`), so a shared link rendered a title and whatever the
11
+ * event's cover image happened to be, with none of the branded card every
12
+ * other listing type gets.
13
+ *
14
+ * ## 🛑 No money, and no per-slot prices
15
+ *
16
+ * An OG image is a public image URL with its contents burned into the pixels:
17
+ * no sign-in gate reaches it and no paywall markup describes it, which is why
18
+ * all eight money-bearing renderers were stripped (Root Cause #93). A lottery
19
+ * is the sharpest case in the codebase — `toClientLotteryConfig` is an
20
+ * allow-list that exists specifically to keep `price` and `weight` off every
21
+ * slot — so this renderer takes the CLIENT shape and reads only what that
22
+ * allow-list already permits: the slot count, and how many are still free.
23
+ *
24
+ * "6 of 200 slots left" is a fact about availability rather than a disclosed
25
+ * amount, and it is the half of the card that earns the click — exactly the
26
+ * line `renderPrizeDrawOg` draws for "Free entry".
27
+ */
28
+ import type { ReactElement } from "react";
29
+ import type { LotteryEventClient } from "./data";
30
+ export interface LotteryOgData {
31
+ title: string;
32
+ imageUrl?: string | null;
33
+ slotsLabel?: string | null;
34
+ statusLabel?: string | null;
35
+ }
36
+ export declare function renderLotteryOg(event: LotteryEventClient | null | undefined, opts: {
37
+ siteName: string;
38
+ baseUrl?: string;
39
+ }): ReactElement;
40
+ export declare function renderLotteryOgImage(data: LotteryOgData, siteName: string): ReactElement;
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Lottery OG image renderer.
3
+ *
4
+ * ## Why this did not exist
5
+ *
6
+ * `lottery/[id]` was the single entry in `verify-og-coverage`'s
7
+ * `OG_KNOWN_GAPS` — the one public dynamic detail page shipping without an
8
+ * `opengraph-image.tsx`, carried as a baseline since 2026-05-23 with the note
9
+ * "OG image follows in a follow-up". Metadata already resolved
10
+ * (`buildLotteryMetadata`), so a shared link rendered a title and whatever the
11
+ * event's cover image happened to be, with none of the branded card every
12
+ * other listing type gets.
13
+ *
14
+ * ## 🛑 No money, and no per-slot prices
15
+ *
16
+ * An OG image is a public image URL with its contents burned into the pixels:
17
+ * no sign-in gate reaches it and no paywall markup describes it, which is why
18
+ * all eight money-bearing renderers were stripped (Root Cause #93). A lottery
19
+ * is the sharpest case in the codebase — `toClientLotteryConfig` is an
20
+ * allow-list that exists specifically to keep `price` and `weight` off every
21
+ * slot — so this renderer takes the CLIENT shape and reads only what that
22
+ * allow-list already permits: the slot count, and how many are still free.
23
+ *
24
+ * "6 of 200 slots left" is a fact about availability rather than a disclosed
25
+ * amount, and it is the half of the card that earns the click — exactly the
26
+ * line `renderPrizeDrawOg` draws for "Free entry".
27
+ */
28
+ import { renderOgLayout } from "../seo/og-layout.js";
29
+ import { resolveOgImageUrl } from "../seo/og.js";
30
+ /**
31
+ * The event's own status, as a human badge. `active` is deliberately absent:
32
+ * a live lottery is the default case, so a chip saying so costs a badge slot
33
+ * and tells the reader nothing they would not assume.
34
+ */
35
+ const STATUS_BADGE_TEXT = {
36
+ draft: "Not yet open",
37
+ paused: "Paused",
38
+ ended: "Closed",
39
+ cancelled: "Cancelled",
40
+ };
41
+ export function renderLotteryOg(event, opts) {
42
+ const cfg = event?.lotteryConfig;
43
+ const slots = cfg?.slots ?? [];
44
+ /*
45
+ * Counted from the slot array rather than read from `totalSlots`, which is
46
+ * the mirror the admin write path derives FROM `slots.length` — and a mirror
47
+ * is the field most likely to disagree (Root Cause #42). The array is here
48
+ * either way, so counting it costs nothing.
49
+ */
50
+ const total = slots.length;
51
+ const free = slots.filter((s) => !s.isBooked).length;
52
+ const slotsLabel = total > 0
53
+ ? free > 0
54
+ ? `${free.toLocaleString("en-IN")} of ${total.toLocaleString("en-IN")} slots left`
55
+ : `All ${total.toLocaleString("en-IN")} slots claimed`
56
+ : null;
57
+ const coverUrl = event?.coverImage && typeof event.coverImage.url === "string"
58
+ ? event.coverImage.url
59
+ : (event?.coverImageUrl ?? null);
60
+ return renderLotteryOgImage({
61
+ title: event?.title ?? "Lottery",
62
+ imageUrl: resolveOgImageUrl(coverUrl, opts.baseUrl),
63
+ slotsLabel,
64
+ statusLabel: event?.status ? (STATUS_BADGE_TEXT[event.status] ?? null) : null,
65
+ }, opts.siteName);
66
+ }
67
+ export function renderLotteryOgImage(data, siteName) {
68
+ const badges = [data.statusLabel].filter((s) => Boolean(s));
69
+ return renderOgLayout({
70
+ title: data.title,
71
+ subtitle: data.slotsLabel ?? undefined,
72
+ imageUrl: data.imageUrl,
73
+ siteName: `${siteName} · Lottery`,
74
+ badges: badges.length > 0 ? badges : undefined,
75
+ // Violet, distinct from the prize-draw amber beside it in the nav — the two
76
+ // are different products and a shared accent makes shared links ambiguous.
77
+ theme: { accentColor: "#8b5cf6" },
78
+ });
79
+ }
@@ -12,6 +12,7 @@ import { createMessage, listMessages, softDeleteMessage, deleteAllMessages, list
12
12
  import { finalizeStagedMediaArray } from "../../../../features/media/finalize.js";
13
13
  import { sendNotification } from "../../../../features/admin/actions/notification-actions.js";
14
14
  import { productRepository } from "../../../../features/products/repository/products.repository.js";
15
+ import { normalizeListingType } from "../../../../features/products/utils/listing-type.js";
15
16
  import { siteSettingsRepository } from "../../../../repositories/index.js";
16
17
  const MESSAGE_MAX_LENGTH = 2000;
17
18
  /**
@@ -161,6 +162,9 @@ export async function sendMessage(input) {
161
162
  title: product.title,
162
163
  image: product.images?.[0],
163
164
  price: product.price,
165
+ // Without this the card cannot pick the right detail route — see the
166
+ // field's own comment on `MessageProductRef`.
167
+ listingType: normalizeListingType(product),
164
168
  };
165
169
  }
166
170
  // A missing/deleted product is not an error — the card simply doesn't
@@ -12,7 +12,7 @@
12
12
  */
13
13
  // Display masking only — `pii-mask.ts` is the crypto-FREE half that Root Cause
14
14
  // #24 split out of `pii-encrypt.ts` precisely so it could be imported freely.
15
- import { maskEmail, maskName } from "../../../../security/pii-mask.js";
15
+ import { offerRepository } from "../../../../features/seller/repository/offer.repository.js";
16
16
  function toIsoOrUndefined(value) {
17
17
  return value instanceof Date ? value.toISOString() : undefined;
18
18
  }
@@ -21,11 +21,25 @@ function toIso(value) {
21
21
  }
22
22
  /** The three buyer keys, resolved per `buyerIdentity`. Absent keys stay absent. */
23
23
  function buyerIdentityFields(doc, mode) {
24
+ /*
25
+ * 🛑 Both branches go through the repository's named accessors.
26
+ *
27
+ * `OfferRepository.mapDoc` no longer decrypts, so `doc.buyerName` and
28
+ * `doc.buyerEmail` are CIPHERTEXT here. Before this, `"full"` returned the
29
+ * `enc:v1:` blobs straight to the seller, and `"masked"` handed them to
30
+ * `maskName`/`maskEmail`, which refuse ciphertext by design and answer
31
+ * "Anonymous" / "***@***.***" — so neither mode worked, in opposite ways.
32
+ *
33
+ * `"full"` is the seller's own view of a buyer who made them an offer, which
34
+ * is a legitimate plaintext read; `"masked"` is everything else.
35
+ */
24
36
  if (mode === "full") {
25
- return { buyerUid: doc.buyerUid, buyerName: doc.buyerName, buyerEmail: doc.buyerEmail };
37
+ const plain = offerRepository.revealOffer(doc);
38
+ return { buyerUid: doc.buyerUid, buyerName: plain.buyerName, buyerEmail: plain.buyerEmail };
26
39
  }
27
40
  if (mode === "masked") {
28
- return { buyerName: maskName(doc.buyerName), buyerEmail: maskEmail(doc.buyerEmail) };
41
+ const masked = offerRepository.maskedOffer(doc);
42
+ return { buyerName: masked.buyerName, buyerEmail: masked.buyerEmail };
29
43
  }
30
44
  return {};
31
45
  }
@@ -22,7 +22,7 @@ export async function createOrderAction(input) {
22
22
  const parsed = createOrderSchema.safeParse(input);
23
23
  if (!parsed.success)
24
24
  throw new ValidationError(parsed.error.issues[0]?.message ?? "Invalid order input");
25
- return orderRepository.create({
25
+ return orderRepository.createOrder({
26
26
  ...parsed.data,
27
27
  userId: user.uid,
28
28
  status: "pending",
@@ -211,7 +211,12 @@ export async function attachPaymentProofAction(orderId, proof) {
211
211
  });
212
212
  notifyAdminsOfPaymentProof({
213
213
  id: orderId,
214
- userName: order.userName,
214
+ /*
215
+ * Revealed: this names the buyer to an admin who is about to verify
216
+ * their payment proof, so a mask would defeat the purpose. `order` comes
217
+ * from a repository read, which is ciphertext-by-default.
218
+ */
219
+ userName: orderRepository.revealOrder(order).userName,
215
220
  productTitle: order.productTitle,
216
221
  totalPrice: order.totalPrice,
217
222
  });
@@ -10,3 +10,22 @@ import { type TriggerEventRaffleInput, type TriggerEventRaffleResult } from "../
10
10
  import { type AssignSpinPrizeInput, type AssignSpinPrizeResult } from "../../jobs/core/assignSpinPrize";
11
11
  export declare function triggerEventRaffleAction(input: TriggerEventRaffleInput): Promise<ActionResult<TriggerEventRaffleResult>>;
12
12
  export declare function assignSpinPrizeAction(input: AssignSpinPrizeInput): Promise<ActionResult<AssignSpinPrizeResult>>;
13
+ /**
14
+ * Resolve a slug-or-id to the canonical event DOCUMENT ID.
15
+ *
16
+ * Exists for one caller — `POST /api/events/[id]/spin`, which must hash a
17
+ * guest's identity against a stable key BEFORE calling the spin action.
18
+ *
19
+ * 🛑 Why this is not just a nicety. Public URLs link by slug, so the route
20
+ * received a slug and did `hashGuestIdentity(slug, request)`, while
21
+ * `enterEvent` hashes on the resolved doc id. Two identities for one guest on
22
+ * one event. While the spin core's lookup was broken that was invisible (every
23
+ * spin 404'd); the moment the lookup was fixed it would have become a silent
24
+ * `spinMaxPerUser` bypass — exhaust your spins on `/events/<slug>/participate`
25
+ * and get a fresh allowance on `/events/<docId>/participate`.
26
+ *
27
+ * Returns `null` for an unknown event; the route then lets the spin action
28
+ * produce the single authoritative `event_not_found` rather than guessing at
29
+ * one here.
30
+ */
31
+ export declare function resolveEventIdAction(idOrSlug: string): Promise<ActionResult<string | null>>;
@@ -10,6 +10,7 @@ import { wrapAction } from "@mohasinac/appkit/server";
10
10
  import { getAdminDb } from "../../../../providers/db-firebase/admin.js";
11
11
  import { runTriggerEventRaffle, } from "../../jobs/core/triggerEventRaffle.js";
12
12
  import { runAssignSpinPrize, } from "../../jobs/core/assignSpinPrize.js";
13
+ import { resolveEventRef } from "../../jobs/core/_event-ref.js";
13
14
  function buildContext(job) {
14
15
  const logger = {
15
16
  info: (msg, meta) => console.info(`[${job}] ${msg}`, meta ?? {}),
@@ -30,3 +31,27 @@ export async function triggerEventRaffleAction(input) {
30
31
  export async function assignSpinPrizeAction(input) {
31
32
  return wrapAction(async () => runAssignSpinPrize(input, buildContext("user.assignSpinPrize")));
32
33
  }
34
+ /**
35
+ * Resolve a slug-or-id to the canonical event DOCUMENT ID.
36
+ *
37
+ * Exists for one caller — `POST /api/events/[id]/spin`, which must hash a
38
+ * guest's identity against a stable key BEFORE calling the spin action.
39
+ *
40
+ * 🛑 Why this is not just a nicety. Public URLs link by slug, so the route
41
+ * received a slug and did `hashGuestIdentity(slug, request)`, while
42
+ * `enterEvent` hashes on the resolved doc id. Two identities for one guest on
43
+ * one event. While the spin core's lookup was broken that was invisible (every
44
+ * spin 404'd); the moment the lookup was fixed it would have become a silent
45
+ * `spinMaxPerUser` bypass — exhaust your spins on `/events/<slug>/participate`
46
+ * and get a fresh allowance on `/events/<docId>/participate`.
47
+ *
48
+ * Returns `null` for an unknown event; the route then lets the spin action
49
+ * produce the single authoritative `event_not_found` rather than guessing at
50
+ * one here.
51
+ */
52
+ export async function resolveEventIdAction(idOrSlug) {
53
+ return wrapAction(async () => {
54
+ const resolved = await resolveEventRef(buildContext("user.resolveEventId").db, idOrSlug);
55
+ return resolved?.id ?? null;
56
+ });
57
+ }
@@ -17,7 +17,7 @@ export async function createReviewAction(input) {
17
17
  await assertNotDuplicateReview(productId, user.uid);
18
18
  const product = await productRepository.findById(productId);
19
19
  const profile = await userRepository.findById(user.uid);
20
- return reviewRepository.create({
20
+ return reviewRepository.createReview({
21
21
  productId,
22
22
  productTitle: product?.title ?? productId,
23
23
  storeId: storeId || product?.storeId,
@@ -1,5 +1,5 @@
1
1
  export declare const getReviewsForProduct: (productId: string, limit?: number) => Promise<import("../../../..").ReviewDocument[]>;
2
- export declare const getReviewsForStore: (storeId: string, page?: number, pageSize?: number) => Promise<import("../../../..").FirebaseSieveResult<import("../../../..").ReviewDocument> | {
2
+ export declare const getReviewsForStore: (storeId: string, page?: number, pageSize?: number) => Promise<import("../../../..").FirebaseSieveResult<import("../../../../security/encrypted").Plaintext<import("../../../..").ReviewDocument>> | {
3
3
  items: never[];
4
4
  total: number;
5
5
  page: number;