@mohasinac/appkit 4.52.4 → 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 (633) 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 +12 -3
  336. package/dist/features/layout/AppLayoutShell.js +65 -13
  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.d.ts +1 -3
  348. package/dist/features/layout/TitleBarLayout.js +3 -4
  349. package/dist/features/layout/cta-anchor.d.ts +31 -0
  350. package/dist/features/layout/cta-anchor.js +31 -0
  351. package/dist/features/layout/hooks/useBottomActions.d.ts +7 -0
  352. package/dist/features/layout/hooks/useBottomActions.js +6 -1
  353. package/dist/features/layout/index.d.ts +9 -1
  354. package/dist/features/layout/index.js +9 -1
  355. package/dist/features/layout/useCtaReveal.d.ts +24 -0
  356. package/dist/features/layout/useCtaReveal.js +82 -0
  357. package/dist/features/layout/useHoldToOpen.d.ts +41 -0
  358. package/dist/features/layout/useHoldToOpen.js +84 -0
  359. package/dist/features/lottery/repository/lottery-entry.repository.d.ts +18 -3
  360. package/dist/features/lottery/repository/lottery-entry.repository.js +48 -6
  361. package/dist/features/lottery/schemas/firestore.d.ts +33 -5
  362. package/dist/features/loyalty/api/balance/route.js +1 -1
  363. package/dist/features/loyalty/api/history/route.js +1 -1
  364. package/dist/features/media/MediaImage.js +0 -1
  365. package/dist/features/media/MediaPickerModal.js +7 -1
  366. package/dist/features/media/modals/ImageEditor.js +5 -1
  367. package/dist/features/media/modals/VideoThumbnailSelector.js +17 -1
  368. package/dist/features/media/repository/media-assets.repository.d.ts +19 -0
  369. package/dist/features/media/upload/CameraCapture.js +16 -1
  370. package/dist/features/media/upload/ImageUpload.js +42 -4
  371. package/dist/features/media/upload/MediaUploadField.js +69 -13
  372. package/dist/features/media/upload/downscale-image.d.ts +56 -0
  373. package/dist/features/media/upload/downscale-image.js +150 -0
  374. package/dist/features/messages/components/ConversationThreadView.js +45 -2
  375. package/dist/features/messages/components/MessageSellerButton.d.ts +15 -1
  376. package/dist/features/messages/components/MessageSellerButton.js +10 -2
  377. package/dist/features/messages/schemas/firestore.d.ts +15 -0
  378. package/dist/features/orders/hooks/useOrders.js +4 -2
  379. package/dist/features/orders/repository/orders.repository.d.ts +15 -4
  380. package/dist/features/orders/repository/orders.repository.js +52 -20
  381. package/dist/features/orders/schemas/firestore.d.ts +15 -4
  382. package/dist/features/orders/schemas/index.d.ts +8 -8
  383. package/dist/features/orders/types/index.d.ts +2 -2
  384. package/dist/features/payments/repository/payments.repository.js +2 -2
  385. package/dist/features/payments/repository/payout.repository.d.ts +23 -6
  386. package/dist/features/payments/repository/payout.repository.js +63 -23
  387. package/dist/features/payments/repository/saved-payment-methods.repository.d.ts +17 -6
  388. package/dist/features/payments/repository/saved-payment-methods.repository.js +59 -11
  389. package/dist/features/payments/schemas/firestore.d.ts +14 -3
  390. package/dist/features/payments/schemas/saved-methods-firestore.d.ts +12 -1
  391. package/dist/features/pre-orders/api/[slug]/route.js +1 -1
  392. package/dist/features/pre-orders/api/admin/route.js +1 -1
  393. package/dist/features/pre-orders/api/route.js +1 -1
  394. package/dist/features/pre-orders/repository/pre-orders.repository.d.ts +3 -3
  395. package/dist/features/pre-orders/repository/pre-orders.repository.js +6 -6
  396. package/dist/features/products/api/[id]/route.js +1 -1
  397. package/dist/features/products/components/ListingBottomActions.js +4 -0
  398. package/dist/features/products/components/ProductDetailPageView.js +2 -1
  399. package/dist/features/products/components/ProductGalleryClient.js +2 -2
  400. package/dist/features/products/components/ProductGrid.js +12 -1
  401. package/dist/features/products/components/index.d.ts +0 -2
  402. package/dist/features/products/components/index.js +0 -1
  403. package/dist/features/products/config/listing-type-listing-config.d.ts +0 -3
  404. package/dist/features/products/config/listing-type-listing-config.js +27 -2
  405. package/dist/features/products/constants/listing-tabs.d.ts +9 -0
  406. package/dist/features/products/constants/listing-tabs.js +3 -2
  407. package/dist/features/products/hooks/useProducts.js +2 -2
  408. package/dist/features/products/repository/products.repository.js +13 -1
  409. package/dist/features/products/schemas/index.d.ts +2 -2
  410. package/dist/features/products/types/index.d.ts +1 -1
  411. package/dist/features/promotions/api/route.js +1 -1
  412. package/dist/features/reviews/actions/review-actions.d.ts +6 -6
  413. package/dist/features/reviews/actions/review-actions.js +22 -8
  414. package/dist/features/reviews/components/ReviewDetailPageView.js +13 -1
  415. package/dist/features/reviews/components/ReviewsIndexPageView.js +21 -4
  416. package/dist/features/reviews/repository/reviews.repository.d.ts +19 -7
  417. package/dist/features/reviews/repository/reviews.repository.js +63 -12
  418. package/dist/features/reviews/schemas/firestore.d.ts +13 -2
  419. package/dist/features/reviews/schemas/index.d.ts +2 -2
  420. package/dist/features/scams/actions/scam-actions.js +16 -4
  421. package/dist/features/search/components/SearchResultsPageView.js +2 -1
  422. package/dist/features/search/hooks/useSearchIndex.d.ts +34 -0
  423. package/dist/features/search/hooks/useSearchIndex.js +172 -0
  424. package/dist/features/search/repository/search.repository.js +2 -2
  425. package/dist/features/seller/actions/offer-actions.d.ts +5 -5
  426. package/dist/features/seller/actions/offer-actions.js +38 -8
  427. package/dist/features/seller/actions/seller-actions.js +34 -7
  428. package/dist/features/seller/api/coupons/route.js +1 -1
  429. package/dist/features/seller/api/products/route.js +1 -1
  430. package/dist/features/seller/api/store/route.js +1 -1
  431. package/dist/features/seller/components/SellerBidsView.js +1 -1
  432. package/dist/features/seller/components/SellerCouponsView.js +1 -1
  433. package/dist/features/seller/components/SellerListingTypeView.js +9 -1
  434. package/dist/features/seller/components/SellerOrdersView.js +1 -1
  435. package/dist/features/seller/components/SellerPayoutSettingsView.js +0 -1
  436. package/dist/features/seller/components/SellerPayoutsView.js +1 -1
  437. package/dist/features/seller/components/SellerProductShell.js +0 -1
  438. package/dist/features/seller/components/SellerProductsView.js +1 -1
  439. package/dist/features/seller/components/SellerShippingView.js +0 -1
  440. package/dist/features/seller/components/SellerStorefrontView.js +0 -1
  441. package/dist/features/seller/components/index.d.ts +0 -4
  442. package/dist/features/seller/components/index.js +0 -2
  443. package/dist/features/seller/repository/offer.repository.d.ts +15 -3
  444. package/dist/features/seller/repository/offer.repository.js +43 -7
  445. package/dist/features/seller/schemas/firestore.d.ts +14 -3
  446. package/dist/features/seller/schemas/index.d.ts +4 -4
  447. package/dist/features/seller/schemas/order-forms.d.ts +39 -0
  448. package/dist/features/seller/schemas/order-forms.js +37 -0
  449. package/dist/features/shell/FormShell.js +6 -2
  450. package/dist/features/shell/QuickFormDrawer.js +15 -1
  451. package/dist/features/shipments/components/AdminShipmentEditorView.js +0 -1
  452. package/dist/features/shipments/components/AdminShipmentsView.js +1 -1
  453. package/dist/features/sticker-trace/components/StickerCommitPanel.d.ts +30 -0
  454. package/dist/features/sticker-trace/components/StickerCommitPanel.js +93 -0
  455. package/dist/features/sticker-trace/components/StickerPrintPanel.d.ts +33 -0
  456. package/dist/features/sticker-trace/components/StickerPrintPanel.js +104 -0
  457. package/dist/features/sticker-trace/components/StickerRetryPanel.d.ts +20 -0
  458. package/dist/features/sticker-trace/components/StickerRetryPanel.js +128 -0
  459. package/dist/features/sticker-trace/components/StickerRunHistoryPanel.d.ts +45 -0
  460. package/dist/features/sticker-trace/components/StickerRunHistoryPanel.js +84 -0
  461. package/dist/features/sticker-trace/components/StickerTraceStudio.d.ts +27 -0
  462. package/dist/features/sticker-trace/components/StickerTraceStudio.js +171 -0
  463. package/dist/features/sticker-trace/constants/help-content.d.ts +23 -0
  464. package/dist/features/sticker-trace/constants/help-content.js +172 -0
  465. package/dist/features/sticker-trace/hooks/useLiveTrace.d.ts +27 -0
  466. package/dist/features/sticker-trace/hooks/useLiveTrace.js +160 -0
  467. package/dist/features/sticker-trace/hooks/useStickerTraceProgress.d.ts +22 -0
  468. package/dist/features/sticker-trace/hooks/useStickerTraceProgress.js +106 -0
  469. package/dist/features/sticker-trace/repository/sticker-sheets.repository.d.ts +113 -0
  470. package/dist/features/sticker-trace/repository/sticker-sheets.repository.js +146 -0
  471. package/dist/features/sticker-trace/repository/sticker-trace-runs.repository.d.ts +132 -0
  472. package/dist/features/sticker-trace/repository/sticker-trace-runs.repository.js +174 -0
  473. package/dist/features/sticker-trace/schemas/firestore.d.ts +248 -0
  474. package/dist/features/sticker-trace/schemas/firestore.js +79 -0
  475. package/dist/features/sticker-trace/server.d.ts +8 -0
  476. package/dist/features/sticker-trace/server.js +51 -0
  477. package/dist/features/stores/actions/store-query-actions.d.ts +2 -2
  478. package/dist/features/stores/actions/store-query-actions.js +7 -2
  479. package/dist/features/stores/api/[storeSlug]/auctions/route.js +3 -3
  480. package/dist/features/stores/api/[storeSlug]/products/route.js +3 -3
  481. package/dist/features/stores/api/[storeSlug]/reviews/route.js +1 -1
  482. package/dist/features/stores/api/[storeSlug]/route.js +1 -1
  483. package/dist/features/stores/components/StoreNavTabs.js +17 -2
  484. package/dist/features/stores/manifest.js +8 -4
  485. package/dist/features/support/repository/support.repository.d.ts +14 -3
  486. package/dist/features/support/repository/support.repository.js +93 -13
  487. package/dist/features/support/schemas/firestore.d.ts +16 -5
  488. package/dist/features/tester/seed-data/authored/admin__events-raffles-spin.js +61 -19
  489. package/dist/features/tester/seed-data/authored/buying__browsing-search.js +19 -3
  490. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.d.ts +2 -0
  491. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.js +243 -0
  492. package/dist/features/tester/seed-data/authored/content-discovery__events.js +36 -10
  493. package/dist/features/tester/seed-data/authored/content-discovery__overflowing-pill-rows.d.ts +2 -0
  494. package/dist/features/tester/seed-data/authored/content-discovery__overflowing-pill-rows.js +209 -0
  495. package/dist/features/tester/seed-data/authored/design-ux__header-brand-mark-centring.d.ts +2 -0
  496. package/dist/features/tester/seed-data/authored/design-ux__header-brand-mark-centring.js +90 -0
  497. package/dist/features/tester/seed-data/authored/design-ux__header-controls-and-messages.d.ts +2 -0
  498. package/dist/features/tester/seed-data/authored/design-ux__header-controls-and-messages.js +85 -0
  499. package/dist/features/tester/seed-data/authored/index.js +10 -0
  500. package/dist/features/tester/seed-data/authored/selling__media-limits.js +19 -17
  501. package/dist/features/tester/seed-data/authored/selling__product-upload-details.js +10 -5
  502. package/dist/features/tester/seed-data/authored/tools__sticker-tracer.d.ts +2 -0
  503. package/dist/features/tester/seed-data/authored/tools__sticker-tracer.js +283 -0
  504. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +235 -22
  505. package/dist/index.d.ts +10 -23
  506. package/dist/index.js +27 -19
  507. package/dist/next/api/routeHandler.js +9 -0
  508. package/dist/next/routing/require-record.d.ts +13 -0
  509. package/dist/next/routing/require-record.js +62 -0
  510. package/dist/next/routing/route-map.d.ts +4 -4
  511. package/dist/next/routing/route-map.js +25 -3
  512. package/dist/providers/db-firebase/base.d.ts +4 -2
  513. package/dist/providers/db-firebase/base.js +21 -5
  514. package/dist/providers/db-firebase/base.repository.d.ts +11 -9
  515. package/dist/providers/db-firebase/base.repository.js +19 -0
  516. package/dist/providers/db-firebase/rtdb-paths.d.ts +12 -0
  517. package/dist/providers/db-firebase/rtdb-paths.js +12 -0
  518. package/dist/react/ErrorBoundary.js +6 -1
  519. package/dist/react/hooks/realtime-event-constants.d.ts +1 -0
  520. package/dist/react/hooks/realtime-event-constants.js +8 -0
  521. package/dist/react/hooks/useEntityDelete.js +5 -1
  522. package/dist/react/hooks/useMessage.js +5 -1
  523. package/dist/repositories/index.d.ts +2 -2
  524. package/dist/repositories/index.js +6 -1
  525. package/dist/schemas/registry.d.ts +13 -20
  526. package/dist/schemas/registry.js +31 -14
  527. package/dist/schemas/webhooks/google-oauth.d.ts +2 -2
  528. package/dist/security/encrypted.d.ts +117 -0
  529. package/dist/security/encrypted.js +100 -0
  530. package/dist/security/index.d.ts +5 -2
  531. package/dist/security/index.js +16 -2
  532. package/dist/security/pii-accessors.d.ts +71 -0
  533. package/dist/security/pii-accessors.js +150 -0
  534. package/dist/security/pii-encrypt.d.ts +0 -8
  535. package/dist/security/pii-encrypt.js +22 -15
  536. package/dist/security/pii-mask.d.ts +18 -0
  537. package/dist/security/pii-mask.js +27 -0
  538. package/dist/seed/_helpers/search-txt-wrappers.d.ts +6 -6
  539. package/dist/seed/_helpers/search-txt-wrappers.js +22 -0
  540. package/dist/seed/addresses-seed-data.d.ts +2 -2
  541. package/dist/seed/authenticity-knowledge-seed-data.d.ts +34 -0
  542. package/dist/seed/authenticity-knowledge-seed-data.js +1277 -0
  543. package/dist/seed/bids-seed-data.d.ts +2 -2
  544. package/dist/seed/bids-seed-data.js +23 -2
  545. package/dist/seed/events-seed-data.d.ts +2 -2
  546. package/dist/seed/events-seed-data.js +5 -0
  547. package/dist/seed/faq-seed-data.js +175 -5
  548. package/dist/seed/homepage-sections-seed-data.js +39 -23
  549. package/dist/seed/index.d.ts +1 -0
  550. package/dist/seed/index.js +1 -0
  551. package/dist/seed/lottery-entries-seed-data.d.ts +2 -2
  552. package/dist/seed/offers-seed-data.d.ts +2 -2
  553. package/dist/seed/offers-seed-data.js +1 -1
  554. package/dist/seed/orders-seed-data.d.ts +2 -2
  555. package/dist/seed/payouts-seed-data.d.ts +2 -2
  556. package/dist/seed/payouts-seed-data.js +1 -1
  557. package/dist/seed/reviews-seed-data.d.ts +1 -2
  558. package/dist/seed/seed-purpose.js +7 -0
  559. package/dist/seed/sessions-seed-data.d.ts +2 -2
  560. package/dist/seed/sessions-seed-data.js +5 -0
  561. package/dist/seed/site-settings-seed-data.js +1 -1
  562. package/dist/seed/support-tickets-seed-data.d.ts +2 -2
  563. package/dist/seed/support-tickets-seed-data.js +1 -1
  564. package/dist/seed/users-seed-data.d.ts +2 -2
  565. package/dist/seed/users-seed-data.js +1 -1
  566. package/dist/seo/json-ld.js +5 -1
  567. package/dist/server.d.ts +18 -3
  568. package/dist/server.js +59 -3
  569. package/dist/styles.css +237 -1
  570. package/dist/tailwind-utilities.css +1 -1
  571. package/dist/ui/components/Button.js +7 -1
  572. package/dist/ui/components/FilterChipGroup.d.ts +11 -0
  573. package/dist/ui/components/FilterChipGroup.js +1 -1
  574. package/dist/ui/components/ImageGallery.js +6 -1
  575. package/dist/ui/components/ListingLayout.js +14 -8
  576. package/dist/ui/components/OverflowRow.d.ts +92 -0
  577. package/dist/ui/components/OverflowRow.js +203 -0
  578. package/dist/ui/components/OverflowRow.style.css +235 -0
  579. package/dist/ui/components/RecordDetailModal.js +14 -1
  580. package/dist/ui/components/RowActionMenu.js +5 -1
  581. package/dist/ui/components/SideDrawer.js +5 -1
  582. package/dist/ui/components/SideModal.js +9 -1
  583. package/dist/ui/components/TabBarShell.d.ts +12 -1
  584. package/dist/ui/components/TabBarShell.js +3 -2
  585. package/dist/ui/components/Tabs.js +36 -24
  586. package/dist/ui/components/Toast.d.ts +3 -24
  587. package/dist/ui/components/Toast.js +2 -19
  588. package/dist/ui/components/TopBannerPortal.d.ts +15 -0
  589. package/dist/ui/components/TopBannerPortal.js +19 -0
  590. package/dist/ui/components/UnsavedChangesModal.js +5 -1
  591. package/dist/ui/components/index.style.css +1 -0
  592. package/dist/ui/components/row-collapse.d.ts +15 -0
  593. package/dist/ui/components/row-collapse.js +127 -0
  594. package/dist/ui/components/toast-context.d.ts +63 -0
  595. package/dist/ui/components/toast-context.js +48 -0
  596. package/dist/ui/components/top-banner-slot.d.ts +37 -0
  597. package/dist/ui/components/top-banner-slot.js +45 -0
  598. package/dist/ui/icons/icon-registry.d.ts +6 -0
  599. package/dist/ui/icons/icon-registry.js +17 -1
  600. package/dist/ui/index.d.ts +2 -0
  601. package/dist/ui/index.js +1 -0
  602. package/dist/utils/array.helper.d.ts +2 -2
  603. package/dist/utils/array.helper.js +5 -5
  604. package/dist/utils/id-generators.d.ts +6 -0
  605. package/dist/utils/id-generators.js +10 -0
  606. package/dist/utils/media-url.js +0 -2
  607. package/dist/utils/search-txt-builders.d.ts +28 -4
  608. package/dist/utils/search-txt-builders.js +41 -1
  609. package/dist/validation/schemas.d.ts +8 -8
  610. package/package.json +6 -2
  611. package/scripts/seed-cli.mjs +3 -0
  612. package/dist/features/account/components/UserAddressesView.d.ts +0 -13
  613. package/dist/features/account/components/UserAddressesView.js +0 -5
  614. package/dist/features/account/components/UserNotificationsView.d.ts +0 -15
  615. package/dist/features/account/components/UserNotificationsView.js +0 -12
  616. package/dist/features/account/components/UserSettingsView.d.ts +0 -16
  617. package/dist/features/account/components/UserSettingsView.js +0 -13
  618. package/dist/features/account/components/UserSupportView.d.ts +0 -3
  619. package/dist/features/account/components/UserSupportView.js +0 -166
  620. package/dist/features/admin/components/DemoSeedView.d.ts +0 -11
  621. package/dist/features/admin/components/DemoSeedView.js +0 -5
  622. package/dist/features/auth/components/AuthStatusPanel.d.ts +0 -10
  623. package/dist/features/auth/components/AuthStatusPanel.js +0 -22
  624. package/dist/features/categories/components/CategoryProductsView.d.ts +0 -45
  625. package/dist/features/categories/components/CategoryProductsView.js +0 -21
  626. package/dist/features/homepage/components/HowItWorksInfoView.d.ts +0 -36
  627. package/dist/features/homepage/components/HowItWorksInfoView.js +0 -10
  628. package/dist/features/layout/BottomActions.d.ts +0 -1
  629. package/dist/features/layout/BottomActions.js +0 -311
  630. package/dist/features/products/components/ProductsView.d.ts +0 -6
  631. package/dist/features/products/components/ProductsView.js +0 -5
  632. package/dist/features/seller/components/SellerStoreView.d.ts +0 -8
  633. package/dist/features/seller/components/SellerStoreView.js +0 -8
@@ -12,10 +12,10 @@ function getBusinessDayCutoff(daysAgo) {
12
12
  return cutoff;
13
13
  }
14
14
  export async function runAutoPayoutEligibility(ctx) {
15
- if (ctx.env("FEATURE_PAYOUTS") !== "true") {
16
- ctx.logger.info("FEATURE_PAYOUTS disabled — skipping auto-payout eligibility");
17
- return;
18
- }
15
+ // `FEATURE_PAYOUTS` gate deleted 2026-10-19 — see `auctionSettlement.ts`.
16
+ // This was the one flag actually set (`functions/.env.letitrip-in-app`), so
17
+ // unlike its four siblings this job was running; removing the gate is a
18
+ // no-op in behaviour and removes the lever that could silently stop payouts.
19
19
  ctx.logger.info("Starting daily auto-payout eligibility sweep", {
20
20
  windowDays: AUTO_PAYOUT_WINDOW_DAYS,
21
21
  });
@@ -48,6 +48,26 @@ export async function runAutoPayoutEligibility(ctx) {
48
48
  ctx.logger.warn(`Store/seller ${storeId} not found — skipping ${orders.length} order(s)`, { orderIds: orders.map((o) => o.id) });
49
49
  continue;
50
50
  }
51
+ /*
52
+ * 🛑 REVEALED before building a payout. This is the fix for active data
53
+ * corruption, not a style change.
54
+ *
55
+ * `userRepository.findById` is ciphertext-by-default, and
56
+ * `payoutRepository.createPayout` ENCRYPTS `sellerEmail` and `upiId`
57
+ * (`PAYOUT_PII_FIELDS`). Passing the stored values straight through
58
+ * encrypted them a SECOND time, and nothing in the codebase ever
59
+ * double-decrypts — so every payout this cron wrote carried a
60
+ * permanently unreadable `upiId`, which is the field the money is sent to.
61
+ *
62
+ * It also poisoned the blind index: `piiIndicesFor` HMACs whatever it is
63
+ * given, so hashing already-encrypted input produced a valid-looking
64
+ * `sellerEmailIndex` that can never match a lookup by the real address.
65
+ *
66
+ * `payoutDetails` needs its own unwrap because it is encrypted by
67
+ * `encryptPayoutDetails`, a separate scheme from the `piiFields` path, so
68
+ * `revealUser` handles it explicitly.
69
+ */
70
+ const sellerPlain = userRepository.revealUser(seller);
51
71
  const sellerId = store.ownerId;
52
72
  /*
53
73
  * The TAXABLE VALUE — see `orderTaxableValue`. Two narrowings, both
@@ -65,8 +85,9 @@ export async function runAutoPayoutEligibility(ctx) {
65
85
  const { platformFee, gatewayFee, gstOnFee: gstAmount, netAmount } = computePayoutDeduction(grossAmount, commissions);
66
86
  const payoutInput = {
67
87
  storeId,
68
- sellerName: (seller.displayName ?? seller.email ?? sellerId),
69
- sellerEmail: (seller.email ?? ""),
88
+ // `displayName` is plaintext by D1; the email fallback must be revealed.
89
+ sellerName: (seller.displayName ?? sellerPlain.email ?? sellerId),
90
+ sellerEmail: sellerPlain.email ?? "",
70
91
  orderIds: orders.map((o) => o.id),
71
92
  amount: netAmount,
72
93
  grossAmount,
@@ -79,23 +100,31 @@ export async function runAutoPayoutEligibility(ctx) {
79
100
  isAutomatic: true,
80
101
  currency: getDefaultCurrency(),
81
102
  status: "pending",
82
- paymentMethod: seller.payoutDetails?.method === "upi"
103
+ paymentMethod: sellerPlain.payoutDetails?.method === "upi"
83
104
  ? "upi"
84
105
  : "bank_transfer",
85
- upiId: seller.payoutDetails?.method === "upi" ? seller.payoutDetails.upiId : undefined,
86
- bankAccount: seller.payoutDetails?.method === "bank_transfer" &&
87
- seller.payoutDetails.bankAccount
106
+ upiId: sellerPlain.payoutDetails?.method === "upi"
107
+ ? sellerPlain.payoutDetails.upiId
108
+ : undefined,
109
+ /*
110
+ * Only the MASKED account fields are copied, which is why this block
111
+ * escaped the double-encryption above — `accountNumberMasked`,
112
+ * `ifscCode` and `bankName` are in no PII list. The real
113
+ * `accountNumber` is deliberately not carried onto the payout.
114
+ */
115
+ bankAccount: sellerPlain.payoutDetails?.method === "bank_transfer" &&
116
+ sellerPlain.payoutDetails.bankAccount
88
117
  ? {
89
- accountHolderName: seller.payoutDetails.bankAccount.accountHolderName,
90
- accountNumberMasked: seller.payoutDetails.bankAccount.accountNumberMasked,
91
- ifscCode: seller.payoutDetails.bankAccount.ifscCode,
92
- bankName: seller.payoutDetails.bankAccount.bankName,
118
+ accountHolderName: sellerPlain.payoutDetails.bankAccount.accountHolderName,
119
+ accountNumberMasked: sellerPlain.payoutDetails.bankAccount.accountNumberMasked,
120
+ ifscCode: sellerPlain.payoutDetails.bankAccount.ifscCode,
121
+ bankName: sellerPlain.payoutDetails.bankAccount.bankName,
93
122
  }
94
123
  : undefined,
95
124
  notes: `Auto-payout — ${orders.length} delivered order(s) past ${AUTO_PAYOUT_WINDOW_DAYS}-day window`,
96
125
  requestedAt: new Date(),
97
126
  };
98
- const { id: payoutId } = await payoutRepository.create(payoutInput);
127
+ const { id: payoutId } = await payoutRepository.createPayout(payoutInput);
99
128
  for (let i = 0; i < orders.length; i += BATCH_LIMIT) {
100
129
  const slice = orders.slice(i, i + BATCH_LIMIT);
101
130
  const batch = ctx.db.batch();
@@ -51,10 +51,9 @@ async function sweepBundleMembers(productIds, ctx) {
51
51
  };
52
52
  }
53
53
  export async function runBundleStockSync(ctx) {
54
- if (ctx.env("FEATURE_BUNDLES") !== "true") {
55
- ctx.logger.info("FEATURE_BUNDLES disabled — skipping bundle stock sync");
56
- return;
57
- }
54
+ // `FEATURE_BUNDLES` gate deleted 2026-10-19 — see `auctionSettlement.ts` for
55
+ // why these survived the 2026-08-29 flag retirement. Unset in
56
+ // `functions/.env.letitrip-in-app`, so this scheduled sweep had never run.
58
57
  ctx.logger.info("Bundle stock sync starting (SB-UNI-V categories)");
59
58
  const snap = await ctx.db
60
59
  .collection(CATEGORIES_COLLECTION)
@@ -16,6 +16,16 @@ const EMAIL_STALE_MS = 60 * 60 * 1000;
16
16
  /** Long enough for an open thread to notice a ping before it prunes; the
17
17
  * message itself lives in Firestore regardless — this only clears the ping. */
18
18
  const CHAT_STALE_MS = 15 * 60 * 1000;
19
+ /**
20
+ * 🛑 SIXTY minutes, and the four-times-longer window is load-bearing rather
21
+ * than cautious. A `max`-tier trace fans out across up to sixty parts and can
22
+ * exceed fifteen minutes end to end; a channel pruned while the run is still
23
+ * working reads to the client as "it died", which is the one signal this
24
+ * channel exists to make impossible. The durable history is on the run
25
+ * document, so the cost of keeping the node an hour is a handful of small
26
+ * nodes and the cost of dropping it early is a false failure report.
27
+ */
28
+ const STICKER_TRACE_STALE_MS = 60 * 60 * 1000;
19
29
  const JOBS_TTL_DAYS = 30;
20
30
  export async function runCleanupRtdbEvents(ctx) {
21
31
  ctx.logger.info("Starting RTDB events cleanup");
@@ -111,6 +121,40 @@ export async function runCleanupRtdbEvents(ctx) {
111
121
  void normalizeError(emailErr);
112
122
  ctx.logger.error("Email events cleanup failed (non-fatal)", emailErr);
113
123
  }
124
+ /*
125
+ * Sticker kiss-cut tracer progress channels. One node per run, overwritten
126
+ * in place as the trace advances, so the channel's size is bounded by
127
+ * concurrent runs rather than by history — but only because this prunes it.
128
+ * `auction-bids/*` is the Firebase budget's one family with no TTL; do not
129
+ * make this the second.
130
+ *
131
+ * The run DOCUMENT keeps the durable event log, so removing a node loses
132
+ * nothing a retry panel or a post-mortem reads.
133
+ */
134
+ try {
135
+ const traceSnap = await rtdb.ref(RTDB_PATHS.STICKER_TRACE).get();
136
+ if (traceSnap.exists()) {
137
+ const allTraceNodes = traceSnap.val();
138
+ const staleTraceIds = Object.entries(allTraceNodes)
139
+ .filter(([, node]) => {
140
+ const at = node.updatedAt ?? 0;
141
+ // Missing or non-finite is stale BY DEFINITION — it can never age
142
+ // out on its own, so leaving it would pin the node forever.
143
+ return !Number.isFinite(at) || at === 0 || at < now - STICKER_TRACE_STALE_MS;
144
+ })
145
+ .map(([id]) => id);
146
+ if (staleTraceIds.length > 0) {
147
+ await Promise.all(staleTraceIds.map((id) => rtdb.ref(`${RTDB_PATHS.STICKER_TRACE}/${id}`).remove()));
148
+ ctx.logger.info("Sticker trace progress nodes removed", {
149
+ count: staleTraceIds.length,
150
+ });
151
+ }
152
+ }
153
+ }
154
+ catch (traceErr) {
155
+ void normalizeError(traceErr);
156
+ ctx.logger.error("Sticker trace cleanup failed (non-fatal)", traceErr);
157
+ }
114
158
  /*
115
159
  * D9 — chat new-message pings. Its own file says it: "an unpruned RTDB
116
160
  * channel is precisely the thing that quietly accumulates… Do not make it
@@ -0,0 +1,78 @@
1
+ /**
2
+ * The ONE reason → {HTTP status, stable code} map for the two event prize-draw
3
+ * job cores (`assignSpinPrize`, `triggerEventRaffle`).
4
+ *
5
+ * ## Why this exists
6
+ *
7
+ * Each core returns a `reason` string instead of throwing, and each is reachable
8
+ * by TWO entry points — a Next.js API route and a Firebase callable handler.
9
+ * That made four translations of one vocabulary, and all four disagreed:
10
+ *
11
+ * · `api/events/[id]/spin/route.ts` — had `feature_disabled`, no `not_active`
12
+ * · `jobs/handlers/assignSpinPrize.ts` — `identity_required` → 400 (route said 401),
13
+ * no `feature_disabled` branch at all
14
+ * · `api/admin/events/[id]/trigger-raffle/route.ts` — EVERYTHING → 409
15
+ * · `jobs/handlers/triggerEventRaffle.ts` — only 404 / 422
16
+ *
17
+ * Root Cause #85 ("a handler reachable by two entry points with different
18
+ * behaviour"), four times over in one feature. The spin route's own header
19
+ * already documented the trap and still only fixed its own half.
20
+ *
21
+ * ## Two rules that produced real bugs
22
+ *
23
+ * 1. 🛑 **A PERMANENT refusal must never take a retryable status.** The spin
24
+ * route's fallback was 409 (`ALREADY_EXISTS`), described in its own comment
25
+ * as "a benign can't-spin-right-now state". An unlisted permanent reason
26
+ * therefore shipped `{code:"ALREADY_EXISTS", error:"<reason>"}` — an envelope
27
+ * naming two unrelated things — which the UI rendered as "Spin failed.
28
+ * Please try again.", inviting a retry that could never succeed.
29
+ *
30
+ * 2. 🛑 **A reason-less result is a SUCCESS to both routes.** Both check
31
+ * `if (data.reason && !data.<successField>)`, so a core branch that returned
32
+ * early *without* a `reason` fell through to `successResponse`.
33
+ * `triggerEventRaffle`'s feature-flag branch did exactly that and answered
34
+ * `200 "Raffle triggered"` with no winner. Every non-success branch in either
35
+ * core must set a reason from this map.
36
+ *
37
+ * There is deliberately NO fallback entry here: `reasonToHttp` is exhaustive
38
+ * over `EventDrawReason`, so adding a reason without a status is a compile
39
+ * error rather than a silent 409.
40
+ */
41
+ export declare const EVENT_DRAW_REASON: {
42
+ /** Neither a signed-in user nor a hashed guest identity was supplied. */
43
+ readonly IDENTITY_REQUIRED: "identity_required";
44
+ /** Guest attempt on an event that has not opted into guest participation. */
45
+ readonly LOGIN_REQUIRED: "login_required";
46
+ readonly EVENT_NOT_FOUND: "event_not_found";
47
+ /** Draft / paused / cancelled / ended — see each core's status precondition. */
48
+ readonly NOT_ACTIVE: "not_active";
49
+ readonly NO_PRIZES_CONFIGURED: "no_prizes_configured";
50
+ readonly OUTSIDE_SPIN_WINDOW: "outside_spin_window";
51
+ /** This identity has already consumed its `spinMaxPerUser` allowance. */
52
+ readonly ALREADY_USED: "already_used";
53
+ readonly NOT_A_SPIN_WHEEL: "not_a_spin_wheel";
54
+ readonly NOT_A_RAFFLE: "not_a_raffle";
55
+ /** A winner is already recorded; a second draw would mean two winners. */
56
+ readonly ALREADY_TRIGGERED: "already_triggered";
57
+ readonly NO_ELIGIBLE_ENTRIES: "no_eligible_entries";
58
+ };
59
+ export type EventDrawReason = (typeof EVENT_DRAW_REASON)[keyof typeof EVENT_DRAW_REASON];
60
+ export interface EventDrawHttpMapping {
61
+ status: number;
62
+ /** Stable code the client resolves through `toUserMessage` / `errors.codes.*`. */
63
+ code: string;
64
+ /**
65
+ * Developer-facing fallback sentence. The client renders copy from `code`, so
66
+ * this is what shows in a log, a curl, or a locale with no key — never the
67
+ * primary UI string.
68
+ */
69
+ message: string;
70
+ }
71
+ /**
72
+ * Translate a core's `reason` into the response shape both entry points use.
73
+ *
74
+ * An unrecognised reason maps to **500**, not to the old 409 fallback: a reason
75
+ * this map has never heard of is a bug in the core, and a 5xx is what gets it
76
+ * recorded by `onRequestError` instead of being filed as an ordinary conflict.
77
+ */
78
+ export declare function reasonToHttp(reason: string | undefined): EventDrawHttpMapping;
@@ -0,0 +1,133 @@
1
+ /**
2
+ * The ONE reason → {HTTP status, stable code} map for the two event prize-draw
3
+ * job cores (`assignSpinPrize`, `triggerEventRaffle`).
4
+ *
5
+ * ## Why this exists
6
+ *
7
+ * Each core returns a `reason` string instead of throwing, and each is reachable
8
+ * by TWO entry points — a Next.js API route and a Firebase callable handler.
9
+ * That made four translations of one vocabulary, and all four disagreed:
10
+ *
11
+ * · `api/events/[id]/spin/route.ts` — had `feature_disabled`, no `not_active`
12
+ * · `jobs/handlers/assignSpinPrize.ts` — `identity_required` → 400 (route said 401),
13
+ * no `feature_disabled` branch at all
14
+ * · `api/admin/events/[id]/trigger-raffle/route.ts` — EVERYTHING → 409
15
+ * · `jobs/handlers/triggerEventRaffle.ts` — only 404 / 422
16
+ *
17
+ * Root Cause #85 ("a handler reachable by two entry points with different
18
+ * behaviour"), four times over in one feature. The spin route's own header
19
+ * already documented the trap and still only fixed its own half.
20
+ *
21
+ * ## Two rules that produced real bugs
22
+ *
23
+ * 1. 🛑 **A PERMANENT refusal must never take a retryable status.** The spin
24
+ * route's fallback was 409 (`ALREADY_EXISTS`), described in its own comment
25
+ * as "a benign can't-spin-right-now state". An unlisted permanent reason
26
+ * therefore shipped `{code:"ALREADY_EXISTS", error:"<reason>"}` — an envelope
27
+ * naming two unrelated things — which the UI rendered as "Spin failed.
28
+ * Please try again.", inviting a retry that could never succeed.
29
+ *
30
+ * 2. 🛑 **A reason-less result is a SUCCESS to both routes.** Both check
31
+ * `if (data.reason && !data.<successField>)`, so a core branch that returned
32
+ * early *without* a `reason` fell through to `successResponse`.
33
+ * `triggerEventRaffle`'s feature-flag branch did exactly that and answered
34
+ * `200 "Raffle triggered"` with no winner. Every non-success branch in either
35
+ * core must set a reason from this map.
36
+ *
37
+ * There is deliberately NO fallback entry here: `reasonToHttp` is exhaustive
38
+ * over `EventDrawReason`, so adding a reason without a status is a compile
39
+ * error rather than a silent 409.
40
+ */
41
+ import { EVENT_DRAW_ERROR_CODES } from "../../../../errors/error-codes.js";
42
+ export const EVENT_DRAW_REASON = {
43
+ /** Neither a signed-in user nor a hashed guest identity was supplied. */
44
+ IDENTITY_REQUIRED: "identity_required",
45
+ /** Guest attempt on an event that has not opted into guest participation. */
46
+ LOGIN_REQUIRED: "login_required",
47
+ EVENT_NOT_FOUND: "event_not_found",
48
+ /** Draft / paused / cancelled / ended — see each core's status precondition. */
49
+ NOT_ACTIVE: "not_active",
50
+ NO_PRIZES_CONFIGURED: "no_prizes_configured",
51
+ OUTSIDE_SPIN_WINDOW: "outside_spin_window",
52
+ /** This identity has already consumed its `spinMaxPerUser` allowance. */
53
+ ALREADY_USED: "already_used",
54
+ NOT_A_SPIN_WHEEL: "not_a_spin_wheel",
55
+ NOT_A_RAFFLE: "not_a_raffle",
56
+ /** A winner is already recorded; a second draw would mean two winners. */
57
+ ALREADY_TRIGGERED: "already_triggered",
58
+ NO_ELIGIBLE_ENTRIES: "no_eligible_entries",
59
+ };
60
+ const MAPPING = {
61
+ [EVENT_DRAW_REASON.IDENTITY_REQUIRED]: {
62
+ status: 401,
63
+ code: EVENT_DRAW_ERROR_CODES.IDENTITY_REQUIRED,
64
+ message: "No user or guest identity was provided",
65
+ },
66
+ [EVENT_DRAW_REASON.LOGIN_REQUIRED]: {
67
+ status: 401,
68
+ code: EVENT_DRAW_ERROR_CODES.LOGIN_REQUIRED,
69
+ message: "Sign in to take part in this event",
70
+ },
71
+ [EVENT_DRAW_REASON.EVENT_NOT_FOUND]: {
72
+ status: 404,
73
+ code: EVENT_DRAW_ERROR_CODES.EVENT_NOT_FOUND,
74
+ message: "Event not found",
75
+ },
76
+ [EVENT_DRAW_REASON.NOT_ACTIVE]: {
77
+ status: 409,
78
+ code: EVENT_DRAW_ERROR_CODES.EVENT_NOT_ACTIVE,
79
+ message: "This event is not running right now",
80
+ },
81
+ [EVENT_DRAW_REASON.NO_PRIZES_CONFIGURED]: {
82
+ status: 422,
83
+ code: EVENT_DRAW_ERROR_CODES.SPIN_NO_PRIZES,
84
+ message: "No spin prizes are configured for this event",
85
+ },
86
+ [EVENT_DRAW_REASON.OUTSIDE_SPIN_WINDOW]: {
87
+ status: 403,
88
+ code: EVENT_DRAW_ERROR_CODES.SPIN_OUTSIDE_WINDOW,
89
+ message: "This spin wheel is not open right now",
90
+ },
91
+ [EVENT_DRAW_REASON.ALREADY_USED]: {
92
+ status: 409,
93
+ code: EVENT_DRAW_ERROR_CODES.SPIN_ALREADY_USED,
94
+ message: "This identity has already used its spins for this event",
95
+ },
96
+ [EVENT_DRAW_REASON.NOT_A_SPIN_WHEEL]: {
97
+ status: 422,
98
+ code: EVENT_DRAW_ERROR_CODES.NOT_A_SPIN_WHEEL,
99
+ message: "This event is not a spin wheel",
100
+ },
101
+ [EVENT_DRAW_REASON.NOT_A_RAFFLE]: {
102
+ status: 422,
103
+ code: EVENT_DRAW_ERROR_CODES.RAFFLE_NOT_A_RAFFLE,
104
+ message: "This event does not have a raffle",
105
+ },
106
+ [EVENT_DRAW_REASON.ALREADY_TRIGGERED]: {
107
+ status: 409,
108
+ code: EVENT_DRAW_ERROR_CODES.RAFFLE_ALREADY_DRAWN,
109
+ message: "A winner has already been drawn for this raffle",
110
+ },
111
+ [EVENT_DRAW_REASON.NO_ELIGIBLE_ENTRIES]: {
112
+ status: 409,
113
+ code: EVENT_DRAW_ERROR_CODES.RAFFLE_NO_ELIGIBLE_ENTRIES,
114
+ message: "No eligible entries to draw from",
115
+ },
116
+ };
117
+ const UNKNOWN = {
118
+ status: 500,
119
+ code: EVENT_DRAW_ERROR_CODES.UNKNOWN_REASON,
120
+ message: "The event could not be processed",
121
+ };
122
+ /**
123
+ * Translate a core's `reason` into the response shape both entry points use.
124
+ *
125
+ * An unrecognised reason maps to **500**, not to the old 409 fallback: a reason
126
+ * this map has never heard of is a bug in the core, and a 5xx is what gets it
127
+ * recorded by `onRequestError` instead of being filed as an ordinary conflict.
128
+ */
129
+ export function reasonToHttp(reason) {
130
+ if (!reason)
131
+ return UNKNOWN;
132
+ return MAPPING[reason] ?? UNKNOWN;
133
+ }
@@ -53,17 +53,31 @@ function getStringArrayOpt(baseOpts, key) {
53
53
  }
54
54
  const LISTERS = {
55
55
  products: (m, o) => productRepository.list(m, o),
56
- categories: (m) => categoriesRepository.list(m),
57
- brands: (m) => categoriesRepository.list({
56
+ /*
57
+ * 🛑 These four forward `search`, and did not until 2026-10-17.
58
+ *
59
+ * `categoriesRepository.list` and `couponsRepository.list` both accept
60
+ * `opts?: { search?: string }`, and all four listers below were written
61
+ * `(m) => repo.list(m)` — so a search term reaching the Function was
62
+ * DISCARDED and the page came back unfiltered with a 200, while the same
63
+ * route's local fallback filtered correctly. Exactly the divergence the
64
+ * comment further down records for orders/reviews/blogPosts/events/stores
65
+ * and faqs, four collections later: category, brand, coupon and
66
+ * sublisting-category search.
67
+ *
68
+ * Found by `audit-lister-opts-forwarding`, which now blocks the shape.
69
+ */
70
+ categories: (m, o) => categoriesRepository.list(m, { search: getStringOpt(o, "search") }),
71
+ brands: (m, o) => categoriesRepository.list({
58
72
  ...m,
59
73
  filters: m.filters
60
74
  ? `${m.filters},categoryType==brand`
61
75
  : "categoryType==brand",
62
- }),
76
+ }, { search: getStringOpt(o, "search") }),
63
77
  orders: (m, o) => orderRepository.listAll(m, { search: getStringOpt(o, "search") }),
64
78
  reviews: (m, o) => reviewRepository.listAll(m, { search: getStringOpt(o, "search") }),
65
- coupons: (m) => couponsRepository.list(m),
66
- bids: (m) => bidRepository.list(m),
79
+ coupons: (m, o) => couponsRepository.list(m, { search: getStringOpt(o, "search") }),
80
+ bids: (m, o) => bidRepository.list(m, { search: getStringOpt(o, "search") }),
67
81
  payouts: (m) => payoutRepository.list(m),
68
82
  blogPosts: (m, o) => blogRepository.listAll(m, { search: getStringOpt(o, "search") }),
69
83
  events: (m, o) => eventRepository.list(m, { search: getStringOpt(o, "search") }),
@@ -84,13 +98,19 @@ const LISTERS = {
84
98
  tags: getStringArrayOpt(o, "tags"),
85
99
  }),
86
100
  notifications: (m) => notificationRepository.list(m),
87
- scammers: (m) => scammerRepository.listAll(m),
88
- sublistingCategories: (m) => categoriesRepository.list({
101
+ /*
102
+ * `/api/admin/scammers` passes `{ search: q }` to this same method locally —
103
+ * its route comment records that the identity arrays "were never searched at
104
+ * all despite the box promising them" before searchTxt. Through the Function
105
+ * the opt was dropped again, so the two executors disagreed.
106
+ */
107
+ scammers: (m, o) => scammerRepository.listAll(m, { search: getStringOpt(o, "search") }),
108
+ sublistingCategories: (m, o) => categoriesRepository.list({
89
109
  ...m,
90
110
  filters: m.filters
91
111
  ? `${m.filters},categoryType==sublisting`
92
112
  : "categoryType==sublisting",
93
- }),
113
+ }, { search: getStringOpt(o, "search") }),
94
114
  productFeatures: (m) => productFeaturesRepository.list(m),
95
115
  homepageSections: (m) => homepageSectionsRepository.list(m),
96
116
  users: (m) => userRepository.list(m),
@@ -1,4 +1,5 @@
1
1
  import { normalizeError } from "../../../../errors/normalize.js";
2
+ import { ORDER_PII_FIELDS, revealPii } from "../../../../security/index.js";
2
3
  import { adminNotificationsRepository, storeRepository, userRepository } from "../../../../repositories/index.js";
3
4
  import { decryptPii } from "../../../../security/index.js";
4
5
  import { sendWhatsAppBusinessMessage, buildPurchaseAnnouncementMessage, } from "../../../../features/whatsapp-bot/server.js";
@@ -91,7 +92,17 @@ export async function handleOrderCreate(input, ctx) {
91
92
  * `decryptPii` was already imported in this file and used for the store
92
93
  * owner's phone eleven lines up; the buyer's name was simply missed.
93
94
  */
94
- const buyerName = decryptPii(order.userName) ?? order.userName ?? "A customer";
95
+ /*
96
+ * The NAMED accessor, not a bare `decryptPii` cast.
97
+ *
98
+ * This already decrypted and therefore already WORKED — but through a cast
99
+ * that defeated the brand, so "is every reader converted?" could not be
100
+ * answered by grepping for `reveal*`. Routing it through `revealOrder` makes
101
+ * the decision visible in review and in a grep, which is the whole argument
102
+ * for named accessors over an inline decrypt.
103
+ */
104
+ const buyerName = revealPii(order, ORDER_PII_FIELDS).userName ??
105
+ "A customer";
95
106
  const message = buildPurchaseAnnouncementMessage({
96
107
  buyerName,
97
108
  firstItemName,
@@ -10,6 +10,17 @@ export async function handleScamReportCreate(input, ctx) {
10
10
  if (reportedBy) {
11
11
  try {
12
12
  const reporter = await userRepository.findById(reportedBy);
13
+ /*
14
+ * REVEALED, because this notification is DELIVERED to the reporter and a
15
+ * masked address cannot receive mail.
16
+ *
17
+ * `findById` stopped decrypting when `UserRepository` went
18
+ * ciphertext-by-default, so `reporter.email` is an `enc:v1:` blob — it
19
+ * would have been handed to the mailer verbatim. The old intersection
20
+ * brand could not object, because `Encrypted<string>` was a subtype of
21
+ * `string`.
22
+ */
23
+ const reporterPlain = reporter ? userRepository.revealUser(reporter) : null;
13
24
  await sendNotification({
14
25
  userId: reportedBy,
15
26
  type: "scam_report_update",
@@ -18,8 +29,8 @@ export async function handleScamReportCreate(input, ctx) {
18
29
  message: `Your report for "${name}" has been received. Our team will review it within 48 hours.`,
19
30
  relatedId: scammerId,
20
31
  relatedType: "scammer",
21
- userEmail: reporter?.email ?? undefined,
22
- userPhone: reporter?.phoneNumber ?? undefined,
32
+ userEmail: reporterPlain?.email ?? undefined,
33
+ userPhone: reporterPlain?.phoneNumber ?? undefined,
23
34
  });
24
35
  }
25
36
  catch (err) {
@@ -13,6 +13,12 @@ export async function handleScamReportRejected(input, ctx) {
13
13
  const name = displayNames?.[0] ?? "Unknown";
14
14
  try {
15
15
  const reporter = await userRepository.findById(reportedBy);
16
+ /*
17
+ * REVEALED, because this notification is DELIVERED to the reporter and a
18
+ * masked address cannot receive mail. `findById` is ciphertext-by-default,
19
+ * so passing `.email` straight through handed the mailer an `enc:v1:` blob.
20
+ */
21
+ const reporterPlain = reporter ? userRepository.revealUser(reporter) : null;
16
22
  await sendNotification({
17
23
  userId: reportedBy,
18
24
  type: "scam_report_update",
@@ -21,8 +27,8 @@ export async function handleScamReportRejected(input, ctx) {
21
27
  message: `Your report for "${name}" could not be verified with the evidence provided. You may submit a new report with additional evidence.`,
22
28
  relatedId: scammerId,
23
29
  relatedType: "scammer",
24
- userEmail: reporter?.email ?? undefined,
25
- userPhone: reporter?.phoneNumber ?? undefined,
30
+ userEmail: reporterPlain?.email ?? undefined,
31
+ userPhone: reporterPlain?.phoneNumber ?? undefined,
26
32
  });
27
33
  }
28
34
  catch (err) {
@@ -13,6 +13,12 @@ export async function handleScamReportVerified(input, ctx) {
13
13
  const name = displayNames?.[0] ?? "Unknown";
14
14
  try {
15
15
  const reporter = await userRepository.findById(reportedBy);
16
+ /*
17
+ * REVEALED, because this notification is DELIVERED to the reporter and a
18
+ * masked address cannot receive mail. `findById` is ciphertext-by-default,
19
+ * so passing `.email` straight through handed the mailer an `enc:v1:` blob.
20
+ */
21
+ const reporterPlain = reporter ? userRepository.revealUser(reporter) : null;
16
22
  await sendNotification({
17
23
  userId: reportedBy,
18
24
  type: "scam_report_update",
@@ -21,8 +27,8 @@ export async function handleScamReportVerified(input, ctx) {
21
27
  message: `The report for "${name}" has been verified and published to the Scam Registry. Thank you for helping protect the community.`,
22
28
  relatedId: scammerId,
23
29
  relatedType: "scammer",
24
- userEmail: reporter?.email ?? undefined,
25
- userPhone: reporter?.phoneNumber ?? undefined,
30
+ userEmail: reporterPlain?.email ?? undefined,
31
+ userPhone: reporterPlain?.phoneNumber ?? undefined,
26
32
  });
27
33
  }
28
34
  catch (err) {
@@ -5,9 +5,16 @@
5
5
  import { notifyRevalidate } from "./revalidateNotify.js";
6
6
  export async function handleStoreWrite(input, ctx) {
7
7
  // The search-index sync this used to perform is gone (Firestore queries handle
8
- // search now), so the only remaining side-effect is cache invalidation: drop
9
- // the ISR entries for this store's page and the stores listing. Reuses the
10
- // existing trigger, so this costs no additional invocations, and performs no
11
- // Firestore write (Root Cause #92).
8
+ // search now), so the only remaining side-effect here is cache invalidation:
9
+ // drop the ISR entries for this store's page and the stores listing. Reuses
10
+ // the existing trigger, so it costs no additional invocations, and this
11
+ // function performs no Firestore write.
12
+ //
13
+ // 🛑 The HANDLER above it does write one, as of the public search index:
14
+ // `markSearchIndexDirty` flips a boolean on `searchIndex/manifest`. That is
15
+ // still safe under Root Cause #92 — a different collection from the one the
16
+ // trigger watches, with a boolean read-then-write guard — but the old
17
+ // blanket claim that this trigger writes nothing is no longer true, and a
18
+ // comment that is false is worse than no comment.
12
19
  await notifyRevalidate({ collection: "stores", id: input.storeId }, ctx);
13
20
  }
@@ -14,10 +14,11 @@ const ORDER_COLLECTION = "orders";
14
14
  * — do not change the selection algorithm.
15
15
  */
16
16
  export async function assignPrizeDrawWinner(ctx, args) {
17
- if (ctx.env("FEATURE_PRIZE_DRAWS") !== "true") {
18
- ctx.logger.info("FEATURE_PRIZE_DRAWS disabled — skipping winner assignment");
19
- return { kind: "not_eligible" };
20
- }
17
+ // The `FEATURE_PRIZE_DRAWS` gate here was deleted 2026-10-19 with the other
18
+ // four readers — see the header of `assignSpinPrize.ts`. This one was the
19
+ // worst-shaped of them: it returned `kind: "not_eligible"`, which every
20
+ // caller treats as "this order does not win anything", so with the env var
21
+ // unset a paid prize-draw entry was silently recorded as a non-winner.
21
22
  const { orderId, productId } = args;
22
23
  const orderRef = ctx.db.collection(ORDER_COLLECTION).doc(orderId);
23
24
  const productRef = ctx.db.collection(PRODUCT_COLLECTION).doc(productId);
@@ -17,10 +17,7 @@ const PRIZE_DRAW_LISTING_TYPE = "prize-draw";
17
17
  * "closed".
18
18
  */
19
19
  export async function runPrizeDrawExpiryReveal(ctx) {
20
- if (ctx.env("FEATURE_PRIZE_DRAWS") !== "true") {
21
- ctx.logger.info("FEATURE_PRIZE_DRAWS disabled — skipping prize-draw expiry reveal");
22
- return;
23
- }
20
+ // `FEATURE_PRIZE_DRAWS` gate deleted 2026-10-19 — see `assignSpinPrize.ts`.
24
21
  ctx.logger.info("Prize-draw expiry reveal sweep starting");
25
22
  const snap = await ctx.db
26
23
  .collection(PRODUCT_COLLECTION)
@@ -18,8 +18,7 @@ function isSoldOut(doc) {
18
18
  * the draw, then closes it.
19
19
  */
20
20
  export async function handlePrizeDrawSoldOut(input, ctx) {
21
- if (ctx.env("FEATURE_PRIZE_DRAWS") !== "true")
22
- return;
21
+ // `FEATURE_PRIZE_DRAWS` gate deleted 2026-10-19 — see `assignSpinPrize.ts`.
23
22
  const { productId, before, after } = input;
24
23
  if (!after)
25
24
  return;
@@ -6,10 +6,13 @@ import { ProductStatusValues } from "../../../../features/products/schemas/fires
6
6
  * (coupon.startDate IS NULL OR <= now) filter Firestore can't express.
7
7
  */
8
8
  export async function runPromotions(_input, ctx) {
9
- if (ctx.env("FEATURE_EVENTS") !== "true") {
10
- ctx.logger.info("FEATURE_EVENTS disabled — skipping promotions");
11
- return { promotedProducts: [], featuredProducts: [], activeCoupons: [] };
12
- }
9
+ /*
10
+ * `FEATURE_EVENTS` gate deleted 2026-10-19 — see `auctionSettlement.ts`.
11
+ * Unset in the Functions env, and this branch returned three EMPTY ARRAYS,
12
+ * which is indistinguishable from "nothing is promoted right now" to every
13
+ * caller. A refusal shaped like a valid empty answer is the worst of the
14
+ * nine; the spin route at least produced a 503 somebody could see.
15
+ */
13
16
  ctx.logger.info("Promotions data requested");
14
17
  const now = new Date();
15
18
  const nowIso = now.toISOString();
@@ -0,0 +1,7 @@
1
+ import type { JobContext } from "../runtime/types";
2
+ export declare function runSearchIndexBuild(ctx: JobContext): Promise<void>;
3
+ /**
4
+ * Force a full rebuild, ignoring the manifest's cadence. For a one-off repair
5
+ * after a schema bump or a reseed.
6
+ */
7
+ export declare function runSearchIndexFullRebuild(ctx: JobContext): Promise<void>;