@mohasinac/appkit 4.53.0 → 4.53.1

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 (500) hide show
  1. package/dist/.build-stamp.json +3 -3
  2. package/dist/_internal/client/scaffolds/AppShell.js +1 -1
  3. package/dist/_internal/server/features/auctions/og.d.ts +3 -1
  4. package/dist/_internal/server/features/auctions/og.js +3 -1
  5. package/dist/_internal/server/features/bundles/actions.js +1 -1
  6. package/dist/_internal/server/features/business-documents/download.d.ts +41 -0
  7. package/dist/_internal/server/features/business-documents/download.js +91 -0
  8. package/dist/_internal/server/features/categories/adapters.d.ts +1 -1
  9. package/dist/_internal/server/features/categories/adapters.js +10 -0
  10. package/dist/_internal/server/features/checkout/actions.d.ts +14 -0
  11. package/dist/_internal/server/features/checkout/actions.js +106 -12
  12. package/dist/_internal/server/features/checkout/bundle-expansion.js +17 -0
  13. package/dist/_internal/server/features/checkout/data.d.ts +22 -0
  14. package/dist/_internal/server/features/checkout/group-rule-revalidation.d.ts +34 -0
  15. package/dist/_internal/server/features/checkout/group-rule-revalidation.js +124 -0
  16. package/dist/_internal/server/features/checkout/supplier-identity.d.ts +55 -0
  17. package/dist/_internal/server/features/checkout/supplier-identity.js +81 -0
  18. package/dist/_internal/server/features/classified/metadata.js +1 -1
  19. package/dist/_internal/server/features/classified/og.d.ts +3 -1
  20. package/dist/_internal/server/features/classified/og.js +3 -1
  21. package/dist/_internal/server/features/digital-code/metadata.js +1 -1
  22. package/dist/_internal/server/features/digital-code/og.d.ts +3 -1
  23. package/dist/_internal/server/features/digital-code/og.js +3 -1
  24. package/dist/_internal/server/features/digital-code/pool.d.ts +19 -4
  25. package/dist/_internal/server/features/digital-code/pool.js +19 -4
  26. package/dist/_internal/server/features/live/metadata.js +1 -1
  27. package/dist/_internal/server/features/live/og.d.ts +3 -1
  28. package/dist/_internal/server/features/live/og.js +3 -1
  29. package/dist/_internal/server/features/messages/actions.js +1 -1
  30. package/dist/_internal/server/features/parts/og.js +1 -1
  31. package/dist/_internal/server/features/pre-orders/og.d.ts +3 -1
  32. package/dist/_internal/server/features/pre-orders/og.js +3 -1
  33. package/dist/_internal/server/features/price-index/search.d.ts +18 -0
  34. package/dist/_internal/server/features/price-index/search.js +47 -7
  35. package/dist/_internal/server/features/prize-draws/og.d.ts +3 -1
  36. package/dist/_internal/server/features/prize-draws/og.js +3 -1
  37. package/dist/_internal/server/features/products/group-members.d.ts +26 -0
  38. package/dist/_internal/server/features/products/group-members.js +7 -1
  39. package/dist/_internal/server/features/products/og.d.ts +3 -1
  40. package/dist/_internal/server/features/products/og.js +3 -1
  41. package/dist/_internal/server/features/search/scoped-sources.d.ts +26 -0
  42. package/dist/_internal/server/features/search/scoped-sources.js +252 -0
  43. package/dist/_internal/server/features/search/search-everything.d.ts +57 -0
  44. package/dist/_internal/server/features/search/search-everything.js +70 -20
  45. package/dist/_internal/server/features/seo/sitemap.js +6 -0
  46. package/dist/_internal/server/features/shared/listing-adapters.js +4 -2
  47. package/dist/_internal/server/features/sticker-trace/adapters.d.ts +11 -0
  48. package/dist/_internal/server/features/sticker-trace/adapters.js +1 -0
  49. package/dist/_internal/server/features/sticker-trace/promote-to-listings.d.ts +26 -0
  50. package/dist/_internal/server/features/sticker-trace/promote-to-listings.js +264 -0
  51. package/dist/_internal/server/features/sticker-trace/sheet-actions.d.ts +3 -1
  52. package/dist/_internal/server/features/sticker-trace/sheet-actions.js +32 -0
  53. package/dist/_internal/server/features/sticker-trace/storage.d.ts +20 -1
  54. package/dist/_internal/server/features/sticker-trace/storage.js +20 -1
  55. package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
  56. package/dist/_internal/server/features/stores/adapters.js +16 -0
  57. package/dist/_internal/server/features/stores/index.d.ts +1 -0
  58. package/dist/_internal/server/features/stores/index.js +1 -0
  59. package/dist/_internal/server/features/stores/tabs.d.ts +25 -0
  60. package/dist/_internal/server/features/stores/tabs.js +122 -0
  61. package/dist/_internal/shared/checkout/rules/_defaults.js +0 -2
  62. package/dist/_internal/shared/checkout/rules/_limits.d.ts +14 -1
  63. package/dist/_internal/shared/checkout/rules/_limits.js +14 -1
  64. package/dist/_internal/shared/checkout/rules/_registry.js +2 -0
  65. package/dist/_internal/shared/checkout/rules/auction.rule.js +9 -1
  66. package/dist/_internal/shared/checkout/rules/bundle.rule.js +13 -0
  67. package/dist/_internal/shared/checkout/rules/index.d.ts +2 -0
  68. package/dist/_internal/shared/checkout/rules/index.js +9 -0
  69. package/dist/_internal/shared/checkout/rules/offer.rule.js +0 -1
  70. package/dist/_internal/shared/checkout/rules/payment-gate.d.ts +26 -0
  71. package/dist/_internal/shared/checkout/rules/payment-gate.js +133 -0
  72. package/dist/_internal/shared/checkout/rules/prize-draw.rule.js +29 -8
  73. package/dist/_internal/shared/checkout/rules/spares.rule.d.ts +16 -0
  74. package/dist/_internal/shared/checkout/rules/spares.rule.js +5 -0
  75. package/dist/_internal/shared/checkout/rules/types.d.ts +26 -2
  76. package/dist/_internal/shared/config/schema.d.ts +122 -0
  77. package/dist/_internal/shared/features/cart/schema.js +3 -2
  78. package/dist/_internal/shared/features/products/group-rules.d.ts +75 -0
  79. package/dist/_internal/shared/features/products/group-rules.js +142 -0
  80. package/dist/_internal/shared/listing-types/_registry.d.ts +24 -0
  81. package/dist/_internal/shared/listing-types/_registry.js +39 -1
  82. package/dist/_internal/shared/listing-types/art/config.d.ts +1 -0
  83. package/dist/_internal/shared/listing-types/art/config.js +2 -0
  84. package/dist/_internal/shared/listing-types/auction/config.d.ts +1 -0
  85. package/dist/_internal/shared/listing-types/auction/config.js +2 -0
  86. package/dist/_internal/shared/listing-types/availability.js +48 -0
  87. package/dist/_internal/shared/listing-types/capabilities.js +19 -0
  88. package/dist/_internal/shared/listing-types/classified/config.d.ts +1 -0
  89. package/dist/_internal/shared/listing-types/classified/config.js +2 -0
  90. package/dist/_internal/shared/listing-types/digital-code/config.d.ts +1 -0
  91. package/dist/_internal/shared/listing-types/digital-code/config.js +2 -0
  92. package/dist/_internal/shared/listing-types/feature-flags.js +1 -0
  93. package/dist/_internal/shared/listing-types/live/config.d.ts +1 -0
  94. package/dist/_internal/shared/listing-types/live/config.js +2 -0
  95. package/dist/_internal/shared/listing-types/pre-order/config.d.ts +1 -0
  96. package/dist/_internal/shared/listing-types/pre-order/config.js +2 -0
  97. package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +1 -0
  98. package/dist/_internal/shared/listing-types/prize-draw/config.js +2 -0
  99. package/dist/_internal/shared/listing-types/spares/config.d.ts +74 -0
  100. package/dist/_internal/shared/listing-types/spares/config.js +60 -0
  101. package/dist/_internal/shared/listing-types/spares/ctas.d.ts +1 -0
  102. package/dist/_internal/shared/listing-types/spares/ctas.js +4 -0
  103. package/dist/_internal/shared/listing-types/spares/og.js +1 -0
  104. package/dist/_internal/shared/listing-types/spares/schema.d.ts +2 -0
  105. package/dist/_internal/shared/listing-types/spares/schema.js +3 -0
  106. package/dist/_internal/shared/listing-types/spares/seed-factory.d.ts +1 -0
  107. package/dist/_internal/shared/listing-types/spares/seed-factory.js +1 -0
  108. package/dist/_internal/shared/listing-types/standard/config.d.ts +1 -0
  109. package/dist/_internal/shared/listing-types/standard/config.js +2 -0
  110. package/dist/_internal/shared/listing-types/stickers/config.d.ts +1 -0
  111. package/dist/_internal/shared/listing-types/stickers/config.js +2 -0
  112. package/dist/_internal/shared/search/match.d.ts +11 -0
  113. package/dist/_internal/shared/search/match.js +2 -1
  114. package/dist/_internal/shared/search/to-groups.d.ts +52 -0
  115. package/dist/_internal/shared/search/to-groups.js +141 -0
  116. package/dist/client.d.ts +8 -2
  117. package/dist/client.js +4 -1
  118. package/dist/constants/api-endpoints.d.ts +39 -15
  119. package/dist/constants/api-endpoints.js +28 -5
  120. package/dist/constants/cache-invalidation.js +3 -1
  121. package/dist/constants/field-names.d.ts +6 -0
  122. package/dist/constants/field-names.js +6 -0
  123. package/dist/features/about/components/PolicyPageView.d.ts +22 -2
  124. package/dist/features/about/components/PolicyPageView.js +14 -2
  125. package/dist/features/about/components/PublicProfileView.js +2 -1
  126. package/dist/features/about/components/ShippingPolicyView.js +42 -2
  127. package/dist/features/account/components/NotificationBell.js +1 -1
  128. package/dist/features/account/hooks/useProfileStats.js +5 -1
  129. package/dist/features/addresses/repository/addresses.repository.d.ts +16 -0
  130. package/dist/features/addresses/repository/addresses.repository.js +21 -0
  131. package/dist/features/admin/actions/admin-actions.js +16 -1
  132. package/dist/features/admin/components/AdminCategoryEditorView.js +19 -2
  133. package/dist/features/admin/components/AdminNavigationView.js +1 -1
  134. package/dist/features/admin/components/AdminPageHeader.js +1 -1
  135. package/dist/features/admin/components/AdminProductEditorView.js +17 -2
  136. package/dist/features/admin/components/AdminSidebar.js +1 -1
  137. package/dist/features/admin/components/AdminSiteSettingsView.js +39 -8
  138. package/dist/features/admin/components/AdminSparesView.d.ts +12 -0
  139. package/dist/features/admin/components/AdminSparesView.js +30 -0
  140. package/dist/features/admin/components/AdminUsersView.js +9 -7
  141. package/dist/features/admin/components/index.d.ts +2 -0
  142. package/dist/features/admin/components/index.js +1 -0
  143. package/dist/features/admin/components/sections/adminSectionsTypes.js +7 -0
  144. package/dist/features/admin/constants/filter-tabs.d.ts +3 -0
  145. package/dist/features/admin/constants/filter-tabs.js +1 -0
  146. package/dist/features/admin/schemas/firestore.d.ts +26 -2
  147. package/dist/features/auctions/components/AuctionDetailPageView.js +4 -11
  148. package/dist/features/auth/repository/user.repository.d.ts +13 -0
  149. package/dist/features/auth/repository/user.repository.js +28 -0
  150. package/dist/features/auth/schemas/firestore.d.ts +2 -0
  151. package/dist/features/auth/schemas/firestore.js +2 -0
  152. package/dist/features/business-documents/repository/business-documents.repository.d.ts +58 -0
  153. package/dist/features/business-documents/repository/business-documents.repository.js +54 -0
  154. package/dist/features/business-documents/schemas/firestore.d.ts +105 -0
  155. package/dist/features/business-documents/schemas/firestore.js +75 -0
  156. package/dist/features/cart/actions/cart-actions.js +83 -6
  157. package/dist/features/cart/repository/cart.repository.js +32 -4
  158. package/dist/features/cart/schemas/firestore.d.ts +20 -0
  159. package/dist/features/cart/schemas/index.d.ts +2 -2
  160. package/dist/features/catalogue/components/PublicCatalogueItemDetailView.js +1 -1
  161. package/dist/features/categories/api/[id]/price-guidance/route.d.ts +42 -0
  162. package/dist/features/categories/api/[id]/price-guidance/route.js +113 -0
  163. package/dist/features/categories/components/BrandDetailPageView.js +19 -3
  164. package/dist/features/categories/components/BrandDetailTabs.js +10 -0
  165. package/dist/features/categories/components/CategoriesIndexListing.js +23 -8
  166. package/dist/features/categories/components/CategoryDetailPageView.js +141 -14
  167. package/dist/features/categories/components/CategoryDetailTabs.js +12 -0
  168. package/dist/features/categories/components/CategoryGrid.js +10 -1
  169. package/dist/features/categories/components/PriceGuidanceHint.d.ts +29 -0
  170. package/dist/features/categories/components/PriceGuidanceHint.js +61 -0
  171. package/dist/features/categories/components/SubcategoryCardRow.d.ts +27 -0
  172. package/dist/features/categories/components/SubcategoryCardRow.js +98 -0
  173. package/dist/features/categories/constants/category-tabs.d.ts +20 -25
  174. package/dist/features/categories/constants/category-tabs.js +22 -39
  175. package/dist/features/categories/repository/categories.repository.d.ts +12 -0
  176. package/dist/features/categories/repository/categories.repository.js +20 -0
  177. package/dist/features/categories/schemas/firestore.d.ts +22 -1
  178. package/dist/features/categories/schemas/firestore.js +10 -0
  179. package/dist/features/categories/schemas/index.d.ts +6 -0
  180. package/dist/features/categories/schemas/index.js +2 -0
  181. package/dist/features/categories/types/index.d.ts +8 -0
  182. package/dist/features/categories/utils/taxonomy-visual.d.ts +16 -3
  183. package/dist/features/categories/utils/taxonomy-visual.js +26 -10
  184. package/dist/features/classified/components/ClassifiedDetailPageView.js +4 -9
  185. package/dist/features/contact/components/ContactPageView.d.ts +33 -1
  186. package/dist/features/contact/components/ContactPageView.js +58 -28
  187. package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +4 -9
  188. package/dist/features/grouped/components/GroupedListingDetailView.js +9 -1
  189. package/dist/features/grouped/schemas/firestore.d.ts +5 -0
  190. package/dist/features/homepage/actions/homepage-section-actions.d.ts +3 -3
  191. package/dist/features/homepage/components/CollectionCardsSection.d.ts +28 -6
  192. package/dist/features/homepage/components/CollectionCardsSection.js +43 -8
  193. package/dist/features/homepage/components/HowItWorksSection.d.ts +23 -6
  194. package/dist/features/homepage/components/HowItWorksSection.js +4 -4
  195. package/dist/features/homepage/components/PromoGrid.d.ts +31 -2
  196. package/dist/features/homepage/components/PromoGrid.js +12 -3
  197. package/dist/features/homepage/components/TestimonialsCarousel.d.ts +34 -2
  198. package/dist/features/homepage/components/TestimonialsCarousel.js +1 -1
  199. package/dist/features/homepage/components/index.d.ts +0 -20
  200. package/dist/features/homepage/components/index.js +0 -11
  201. package/dist/features/homepage/index.d.ts +0 -2
  202. package/dist/features/homepage/index.js +0 -2
  203. package/dist/features/homepage/lib/section-renderer.d.ts +9 -0
  204. package/dist/features/homepage/lib/section-renderer.js +202 -58
  205. package/dist/features/homepage/repository/homepage-sections.repository.d.ts +35 -3
  206. package/dist/features/homepage/repository/homepage-sections.repository.js +58 -8
  207. package/dist/features/homepage/schemas/firestore.d.ts +106 -3
  208. package/dist/features/homepage/schemas/firestore.js +32 -2
  209. package/dist/features/homepage/schemas/index.d.ts +36 -7
  210. package/dist/features/homepage/schemas/index.js +39 -27
  211. package/dist/features/homepage/server.d.ts +0 -3
  212. package/dist/features/homepage/server.js +0 -3
  213. package/dist/features/homepage/types/index.d.ts +0 -47
  214. package/dist/features/homepage/types/index.js +49 -0
  215. package/dist/features/layout/AppLayoutShell.js +1 -1
  216. package/dist/features/layout/BottomNavItem.js +1 -1
  217. package/dist/features/layout/BottomSheet.js +1 -1
  218. package/dist/features/layout/TitleBarLayout.js +1 -1
  219. package/dist/features/live/components/LiveItemDetailPageView.js +4 -9
  220. package/dist/features/media/hooks/useMedia.js +17 -0
  221. package/dist/features/media/repository/media-assets.repository.d.ts +46 -0
  222. package/dist/features/media/repository/media-assets.repository.js +31 -0
  223. package/dist/features/media/trust-signals.d.ts +85 -0
  224. package/dist/features/media/trust-signals.js +126 -0
  225. package/dist/features/parts/components/PartDetailPageView.d.ts +14 -1
  226. package/dist/features/parts/components/PartDetailPageView.js +2 -2
  227. package/dist/features/parts/components/PartsIndexPageView.d.ts +11 -2
  228. package/dist/features/parts/components/PartsIndexPageView.js +2 -2
  229. package/dist/features/parts/components/PartsSearchBox.d.ts +9 -0
  230. package/dist/features/parts/components/PartsSearchBox.js +57 -0
  231. package/dist/features/parts/schemas/firestore.d.ts +149 -3
  232. package/dist/features/parts/schemas/firestore.js +184 -0
  233. package/dist/features/payments/repository/payout.repository.d.ts +15 -0
  234. package/dist/features/payments/repository/payout.repository.js +21 -0
  235. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +4 -11
  236. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +1 -1
  237. package/dist/features/price-index/components/PriceIndexToolView.d.ts +3 -1
  238. package/dist/features/price-index/components/PriceIndexToolView.js +92 -13
  239. package/dist/features/products/components/CompareOverlay.d.ts +18 -1
  240. package/dist/features/products/components/CompareOverlay.js +21 -2
  241. package/dist/features/products/components/CustomSectionTabContent.d.ts +31 -0
  242. package/dist/features/products/components/CustomSectionTabContent.js +29 -3
  243. package/dist/features/products/components/GroupMemberPicker.d.ts +19 -1
  244. package/dist/features/products/components/GroupMemberPicker.js +46 -8
  245. package/dist/features/products/components/GroupSettingsPanel.d.ts +11 -1
  246. package/dist/features/products/components/GroupSettingsPanel.js +91 -3
  247. package/dist/features/products/components/PrizeDrawDetailPageView.js +1 -1
  248. package/dist/features/products/components/PrizeDrawEntryActions.d.ts +15 -1
  249. package/dist/features/products/components/PrizeDrawEntryActions.js +70 -8
  250. package/dist/features/products/components/ProductDetailPageView.js +74 -15
  251. package/dist/features/products/components/ProductForm.d.ts +13 -1
  252. package/dist/features/products/components/ProductForm.js +16 -2
  253. package/dist/features/products/components/ProductsIndexListing.d.ts +16 -1
  254. package/dist/features/products/components/ProductsIndexListing.js +3 -3
  255. package/dist/features/products/components/ShowGroupSection.js +15 -2
  256. package/dist/features/products/components/SparesListView.d.ts +7 -0
  257. package/dist/features/products/components/SparesListView.js +39 -0
  258. package/dist/features/products/constants/action-defs.d.ts +1 -0
  259. package/dist/features/products/constants/action-defs.js +1 -0
  260. package/dist/features/products/repository/products.repository.d.ts +98 -0
  261. package/dist/features/products/repository/products.repository.js +235 -17
  262. package/dist/features/products/schemas/firestore.d.ts +97 -4
  263. package/dist/features/products/schemas/firestore.js +104 -0
  264. package/dist/features/products/schemas/index.d.ts +10 -19
  265. package/dist/features/products/schemas/index.js +23 -6
  266. package/dist/features/products/types/index.d.ts +45 -1
  267. package/dist/features/products/utils/group-member-image.d.ts +39 -0
  268. package/dist/features/products/utils/group-member-image.js +3 -0
  269. package/dist/features/products/utils/listing-badge-variant.js +4 -0
  270. package/dist/features/reviews/components/ReviewsList.js +1 -1
  271. package/dist/features/scams/components/ScamProfileView.js +1 -1
  272. package/dist/features/search/components/EntityTypeahead.d.ts +44 -0
  273. package/dist/features/search/components/EntityTypeahead.js +92 -0
  274. package/dist/features/search/components/Search.d.ts +12 -1
  275. package/dist/features/search/components/Search.js +47 -3
  276. package/dist/features/search/components/SearchFacetRail.d.ts +11 -0
  277. package/dist/features/search/components/SearchFacetRail.js +92 -0
  278. package/dist/features/search/components/SearchResultsClient.d.ts +33 -0
  279. package/dist/features/search/components/SearchResultsClient.js +103 -0
  280. package/dist/features/search/components/SearchResultsPageView.d.ts +15 -1
  281. package/dist/features/search/components/SearchResultsPageView.js +2 -2
  282. package/dist/features/search/components/index.d.ts +0 -6
  283. package/dist/features/search/components/index.js +0 -3
  284. package/dist/features/search/hooks/useNavSuggestions.d.ts +13 -0
  285. package/dist/features/search/hooks/useScopedSearch.d.ts +34 -0
  286. package/dist/features/search/hooks/useScopedSearch.js +114 -0
  287. package/dist/features/search/hooks/useSiteSearch.d.ts +26 -0
  288. package/dist/features/search/hooks/useSiteSearch.js +149 -0
  289. package/dist/features/search/index.d.ts +0 -4
  290. package/dist/features/search/index.js +0 -4
  291. package/dist/features/search/manifest.d.ts +12 -0
  292. package/dist/features/search/manifest.js +17 -2
  293. package/dist/features/search/server.d.ts +0 -3
  294. package/dist/features/search/server.js +0 -3
  295. package/dist/features/seller/components/SellerListingTypeView.d.ts +1 -1
  296. package/dist/features/seller/components/SellerListingTypeView.js +20 -0
  297. package/dist/features/seller/components/SellerPayoutSettingsView.js +35 -14
  298. package/dist/features/seller/components/SellerProductShell.d.ts +1 -1
  299. package/dist/features/seller/components/SellerProductShell.js +2 -1
  300. package/dist/features/seller/components/SellerSidebar.js +1 -1
  301. package/dist/features/seller/components/SellerSparesView.d.ts +17 -0
  302. package/dist/features/seller/components/SellerSparesView.js +6 -0
  303. package/dist/features/seller/components/index.d.ts +2 -0
  304. package/dist/features/seller/components/index.js +1 -0
  305. package/dist/features/shell/CommandPalette.js +1 -1
  306. package/dist/features/sticker-trace/schemas/firestore.d.ts +19 -0
  307. package/dist/features/stores/components/StoreDetailLayoutView.d.ts +1 -1
  308. package/dist/features/stores/components/StoreDetailLayoutView.js +7 -82
  309. package/dist/features/stores/components/StoreHeader.js +1 -2
  310. package/dist/features/stores/components/StoreSparesPageView.d.ts +27 -0
  311. package/dist/features/stores/components/StoreSparesPageView.js +48 -0
  312. package/dist/features/stores/schemas/firestore.d.ts +19 -0
  313. package/dist/features/tester/seed-data/authored/buying__spares-and-groups.d.ts +2 -0
  314. package/dist/features/tester/seed-data/authored/buying__spares-and-groups.js +96 -0
  315. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.d.ts +2 -0
  316. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.js +280 -45
  317. package/dist/features/tester/seed-data/authored/content-discovery__category-tabs-franchise-bundles.js +54 -32
  318. package/dist/features/tester/seed-data/authored/content-discovery__parts-database.js +3 -2
  319. package/dist/features/tester/seed-data/authored/content-discovery__price-index-and-compare.d.ts +2 -0
  320. package/dist/features/tester/seed-data/authored/content-discovery__price-index-and-compare.js +73 -0
  321. package/dist/features/tester/seed-data/authored/content-discovery__site-wide-index.d.ts +2 -0
  322. package/dist/features/tester/seed-data/authored/content-discovery__site-wide-index.js +340 -0
  323. package/dist/features/tester/seed-data/authored/index.js +16 -0
  324. package/dist/features/tester/seed-data/authored/search-and-nav__header-search.d.ts +1 -0
  325. package/dist/features/tester/seed-data/authored/search-and-nav__header-search.js +57 -0
  326. package/dist/features/tester/seed-data/authored/selling__spares-and-group-editing.d.ts +2 -0
  327. package/dist/features/tester/seed-data/authored/selling__spares-and-group-editing.js +77 -0
  328. package/dist/features/tester/seed-data/authored/tools__sticker-promote-to-listings.d.ts +2 -0
  329. package/dist/features/tester/seed-data/authored/tools__sticker-promote-to-listings.js +58 -0
  330. package/dist/features/tester/seed-data/authored/tools__sticker-tracer.js +5 -4
  331. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +372 -18
  332. package/dist/index.d.ts +17 -57
  333. package/dist/index.js +35 -96
  334. package/dist/next/routing/route-map.d.ts +42 -1
  335. package/dist/next/routing/route-map.js +45 -0
  336. package/dist/providers/db-firebase/base.repository.d.ts +22 -0
  337. package/dist/providers/db-firebase/base.repository.js +36 -0
  338. package/dist/schemas/registry.d.ts +15 -6
  339. package/dist/security/blind-index-tokens.d.ts +54 -0
  340. package/dist/security/blind-index-tokens.js +152 -0
  341. package/dist/security/index.d.ts +1 -1
  342. package/dist/security/index.js +1 -1
  343. package/dist/security/settings-encryption.d.ts +35 -0
  344. package/dist/security/settings-encryption.js +91 -0
  345. package/dist/seed/_helpers/brand-rows.js +38 -14
  346. package/dist/seed/_helpers/category-forest.js +73 -7
  347. package/dist/seed/_helpers/category-images-generated.d.ts +25 -6
  348. package/dist/seed/_helpers/category-images-generated.js +81 -6
  349. package/dist/seed/_helpers/category-models.d.ts +1 -1
  350. package/dist/seed/_helpers/category-models.js +7 -1
  351. package/dist/seed/_helpers/category-parts-glossary-map.js +8 -0
  352. package/dist/seed/_helpers/category-parts.d.ts +1 -1
  353. package/dist/seed/_helpers/category-parts.js +50 -2
  354. package/dist/seed/_helpers/character-features.d.ts +1 -1
  355. package/dist/seed/_helpers/character-features.js +2 -1
  356. package/dist/seed/_helpers/franchise-rows.js +10 -2
  357. package/dist/seed/_helpers/media.d.ts +47 -0
  358. package/dist/seed/_helpers/media.js +34 -0
  359. package/dist/seed/authenticity-knowledge-seed-data.d.ts +49 -5
  360. package/dist/seed/authenticity-knowledge-seed-data.js +10001 -549
  361. package/dist/seed/categories-seed-data.js +124 -20
  362. package/dist/seed/grouped-listings-seed-data.js +16 -0
  363. package/dist/seed/homepage-sections-seed-data.js +94 -5
  364. package/dist/seed/index.d.ts +2 -3
  365. package/dist/seed/index.js +2 -2
  366. package/dist/seed/manifest.js +3 -0
  367. package/dist/seed/media-assets-seed-data.d.ts +1 -1
  368. package/dist/seed/media-assets-seed-data.js +746 -196
  369. package/dist/seed/model-composition-seed-data.js +122 -6
  370. package/dist/seed/part-glossary-seed-data.d.ts +1 -1
  371. package/dist/seed/part-glossary-seed-data.js +37219 -463
  372. package/dist/seed/products-art-seed-data.js +7 -18
  373. package/dist/seed/products-auctions-seed-data.js +56 -47
  374. package/dist/seed/products-beyblade-x-seed-data.d.ts +2 -0
  375. package/dist/seed/products-beyblade-x-seed-data.js +441 -0
  376. package/dist/seed/products-catalogue-seed-data.d.ts +5 -5
  377. package/dist/seed/products-catalogue-seed-data.js +1500 -1240
  378. package/dist/seed/products-classifieds-seed-data.js +9 -27
  379. package/dist/seed/products-digital-codes-seed-data.js +9 -18
  380. package/dist/seed/products-live-items-seed-data.js +5 -13
  381. package/dist/seed/products-preorders-seed-data.js +67 -33
  382. package/dist/seed/products-prize-draws-seed-data.js +8 -17
  383. package/dist/seed/products-spares-seed-data.d.ts +2 -0
  384. package/dist/seed/products-spares-seed-data.js +368 -0
  385. package/dist/seed/products-standard-seed-data.js +39 -126
  386. package/dist/seed/products-stickers-seed-data.js +59 -15
  387. package/dist/seed/site-settings-seed-data.js +8 -0
  388. package/dist/seo/json-ld.d.ts +25 -0
  389. package/dist/seo/json-ld.js +28 -0
  390. package/dist/server-entry.d.ts +3 -1
  391. package/dist/server-entry.js +2 -2
  392. package/dist/server.d.ts +9 -9
  393. package/dist/server.js +27 -25
  394. package/dist/styles.css +202 -1
  395. package/dist/tailwind-input.css +31 -17
  396. package/dist/tailwind-utilities.css +1 -1
  397. package/dist/ui/components/Accordion.js +1 -1
  398. package/dist/ui/components/Breadcrumb.js +1 -1
  399. package/dist/ui/components/DetailPageGallery.js +0 -2
  400. package/dist/ui/components/DetailPageHero.js +0 -1
  401. package/dist/ui/components/DetailPageTabs.js +1 -1
  402. package/dist/ui/components/Divider.js +3 -3
  403. package/dist/ui/components/GatedPrice.js +5 -1
  404. package/dist/ui/components/HorizontalScroller.js +1 -1
  405. package/dist/ui/components/ListingLayout.js +3 -3
  406. package/dist/ui/components/MediaTabs.style.css +81 -0
  407. package/dist/ui/components/Pagination.js +1 -1
  408. package/dist/ui/components/PendingValue.d.ts +45 -0
  409. package/dist/ui/components/PendingValue.js +7 -0
  410. package/dist/ui/components/Radio.style.css +119 -0
  411. package/dist/ui/components/RatingDisplay.js +2 -2
  412. package/dist/ui/components/SettingsSection.js +0 -2
  413. package/dist/ui/components/SiteLogo.js +3 -0
  414. package/dist/ui/components/SiteMark.js +3 -0
  415. package/dist/ui/components/SortDropdown.js +1 -1
  416. package/dist/ui/components/SpecTable.d.ts +58 -0
  417. package/dist/ui/components/SpecTable.js +8 -0
  418. package/dist/ui/components/StarRating.js +1 -3
  419. package/dist/ui/components/SummaryCard.js +1 -1
  420. package/dist/ui/components/index.style.css +1 -0
  421. package/dist/ui/icons/icon-registry.d.ts +1 -0
  422. package/dist/ui/icons/icon-registry.js +9 -1
  423. package/dist/ui/index.d.ts +4 -0
  424. package/dist/ui/index.js +2 -0
  425. package/dist/utils/search-txt-query.d.ts +12 -0
  426. package/dist/utils/search-txt-query.js +12 -0
  427. package/package.json +1 -1
  428. package/scripts/dedupe-peer-deps.mjs +18 -0
  429. package/scripts/seed-cli.mjs +135 -26
  430. package/scripts/verify-css-build.mjs +118 -37
  431. package/dist/_internal/server/features/search/actions.d.ts +0 -7
  432. package/dist/_internal/server/features/search/actions.js +0 -21
  433. package/dist/_internal/server/features/search/data.d.ts +0 -15
  434. package/dist/_internal/server/features/search/data.js +0 -18
  435. package/dist/_internal/server/features/search/index.d.ts +0 -3
  436. package/dist/_internal/server/features/search/index.js +0 -2
  437. package/dist/features/homepage/api/[id]/route.d.ts +0 -23
  438. package/dist/features/homepage/api/[id]/route.js +0 -103
  439. package/dist/features/homepage/api/route.d.ts +0 -14
  440. package/dist/features/homepage/api/route.js +0 -140
  441. package/dist/features/homepage/api/sections/[id]/route.d.ts +0 -26
  442. package/dist/features/homepage/api/sections/[id]/route.js +0 -95
  443. package/dist/features/homepage/api/sections/route.d.ts +0 -13
  444. package/dist/features/homepage/api/sections/route.js +0 -82
  445. package/dist/features/homepage/components/AdvertisementBanner.d.ts +0 -14
  446. package/dist/features/homepage/components/AdvertisementBanner.js +0 -35
  447. package/dist/features/homepage/components/BeforeAfterCard.d.ts +0 -9
  448. package/dist/features/homepage/components/BeforeAfterCard.js +0 -73
  449. package/dist/features/homepage/components/FeaturedResultsSection.d.ts +0 -17
  450. package/dist/features/homepage/components/FeaturedResultsSection.js +0 -17
  451. package/dist/features/homepage/components/HeroBanner.d.ts +0 -7
  452. package/dist/features/homepage/components/HeroBanner.js +0 -43
  453. package/dist/features/homepage/components/HeroSection.d.ts +0 -7
  454. package/dist/features/homepage/components/HeroSection.js +0 -6
  455. package/dist/features/homepage/components/HomepageSkeleton.d.ts +0 -2
  456. package/dist/features/homepage/components/HomepageSkeleton.js +0 -21
  457. package/dist/features/homepage/components/HomepageView.d.ts +0 -25
  458. package/dist/features/homepage/components/HomepageView.js +0 -5
  459. package/dist/features/homepage/components/NewsletterBanner.d.ts +0 -23
  460. package/dist/features/homepage/components/NewsletterBanner.js +0 -37
  461. package/dist/features/homepage/components/SiteFeaturesSection.d.ts +0 -14
  462. package/dist/features/homepage/components/SiteFeaturesSection.js +0 -11
  463. package/dist/features/homepage/components/TrustBadges.d.ts +0 -6
  464. package/dist/features/homepage/components/TrustBadges.js +0 -46
  465. package/dist/features/homepage/components/TrustIndicatorsSection.d.ts +0 -12
  466. package/dist/features/homepage/components/TrustIndicatorsSection.js +0 -11
  467. package/dist/features/homepage/hooks/useHomepage.d.ts +0 -11
  468. package/dist/features/homepage/hooks/useHomepage.js +0 -17
  469. package/dist/features/homepage/hooks/useHomepageSections.d.ts +0 -2
  470. package/dist/features/homepage/hooks/useHomepageSections.js +0 -10
  471. package/dist/features/homepage/repository/homepage.repository.d.ts +0 -11
  472. package/dist/features/homepage/repository/homepage.repository.js +0 -25
  473. package/dist/features/search/actions/index.d.ts +0 -1
  474. package/dist/features/search/actions/index.js +0 -1
  475. package/dist/features/search/actions/search-actions.d.ts +0 -18
  476. package/dist/features/search/actions/search-actions.js +0 -43
  477. package/dist/features/search/api/route.d.ts +0 -22
  478. package/dist/features/search/api/route.js +0 -128
  479. package/dist/features/search/columns/index.d.ts +0 -17
  480. package/dist/features/search/columns/index.js +0 -49
  481. package/dist/features/search/components/SearchFiltersRow.d.ts +0 -22
  482. package/dist/features/search/components/SearchFiltersRow.js +0 -21
  483. package/dist/features/search/components/SearchResultsSection.d.ts +0 -53
  484. package/dist/features/search/components/SearchResultsSection.js +0 -35
  485. package/dist/features/search/components/SearchView.d.ts +0 -27
  486. package/dist/features/search/components/SearchView.js +0 -8
  487. package/dist/features/search/hooks/useSearch.d.ts +0 -21
  488. package/dist/features/search/hooks/useSearch.js +0 -33
  489. package/dist/features/search/repository/search.repository.d.ts +0 -14
  490. package/dist/features/search/repository/search.repository.js +0 -59
  491. package/dist/features/search/schemas/index.d.ts +0 -70
  492. package/dist/features/search/schemas/index.js +0 -36
  493. package/dist/features/search/types/index.d.ts +0 -48
  494. package/dist/features/stores/components/StoreScopedSearch.d.ts +0 -17
  495. package/dist/features/stores/components/StoreScopedSearch.js +0 -27
  496. package/dist/seed/defaults/homepage-sections.d.ts +0 -2
  497. package/dist/seed/defaults/homepage-sections.js +0 -60
  498. package/dist/seed/factories/homepage-section.factory.d.ts +0 -10
  499. package/dist/seed/factories/homepage-section.factory.js +0 -13
  500. /package/dist/{features/search/types/index.js → _internal/shared/listing-types/spares/og.d.ts} +0 -0
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "stampVersion": 1,
3
- "version": "4.53.0",
4
- "head": "78e72eb24243b0ee3afea21614fbbadee45d2b51",
3
+ "version": "4.53.1",
4
+ "head": "d45b9f65d4b73c4c4a079a8ee5553600ddd0c251",
5
5
  "branch": "main",
6
6
  "dirty": false,
7
- "builtAt": "2026-10-19T12:44:44.499Z"
7
+ "builtAt": "2026-10-19T21:36:59.723Z"
8
8
  }
@@ -6,5 +6,5 @@ export function AppShell({ children, slotHeader, slotFooter, slotSidebar, render
6
6
  const header = renderHeader ? renderHeader(ctx) : slotHeader;
7
7
  const footer = renderFooter ? renderFooter(ctx) : slotFooter;
8
8
  const sidebar = renderSidebar ? renderSidebar(ctx) : slotSidebar;
9
- return (_jsxs(Stack, { className: `appkit-app-shell min-h-screen ${className ?? ""}`, children: [header ? (_jsx(BlockHeader, { className: "sticky top-0 z-30 w-full", "data-appshell-slot": "header", children: header })) : null, _jsxs(Div, { layout: "flex", className: "flex-1", children: [sidebar ? (_jsx(Aside, { className: "hidden lg:block lg:w-64 lg:shrink-0", "data-appshell-slot": "sidebar", children: sidebar })) : null, _jsx(Main, { className: "min-w-0 flex-1", "data-appshell-slot": "main", children: children })] }), footer ? (_jsx(BlockFooter, { className: "w-full", "data-appshell-slot": "footer", children: footer })) : null] }));
9
+ return (_jsxs(Stack, { className: `min-h-screen ${className ?? ""}`, children: [header ? (_jsx(BlockHeader, { className: "sticky top-0 z-30 w-full", "data-appshell-slot": "header", children: header })) : null, _jsxs(Div, { layout: "flex", className: "flex-1", children: [sidebar ? (_jsx(Aside, { className: "hidden lg:block lg:w-64 lg:shrink-0", "data-appshell-slot": "sidebar", children: sidebar })) : null, _jsx(Main, { className: "min-w-0 flex-1", "data-appshell-slot": "main", children: children })] }), footer ? (_jsx(BlockFooter, { className: "w-full", "data-appshell-slot": "footer", children: footer })) : null] }));
10
10
  }
@@ -8,7 +8,9 @@ interface AuctionDocLike {
8
8
  title?: string | null;
9
9
  auctionEndDate?: Date | string | null;
10
10
  mainImage?: string | null;
11
- images?: (string | null | undefined)[] | null;
11
+ images?: ({
12
+ url: string;
13
+ } | string | null | undefined)[] | null;
12
14
  }
13
15
  /** High-level OG renderer — accepts the raw auction document from `getAuctionForDetail`. */
14
16
  export declare function renderAuctionOg(doc: AuctionDocLike | null | undefined, opts: {
@@ -14,7 +14,9 @@ export function renderAuctionOg(doc, opts) {
14
14
  return renderAuctionOgImage({
15
15
  title: doc?.title ?? "Live Auction",
16
16
  endsLabel,
17
- imageUrl: resolveOgImageUrl(doc?.mainImage || doc?.images?.[0] || null, opts.baseUrl),
17
+ imageUrl: resolveOgImageUrl(doc?.mainImage ||
18
+ (typeof doc?.images?.[0] === "string" ? doc.images[0] : doc?.images?.[0]?.url) ||
19
+ null, opts.baseUrl),
18
20
  }, opts.siteName);
19
21
  }
20
22
  export function renderAuctionOgImage(data, siteName) {
@@ -68,7 +68,7 @@ quantity = 1) {
68
68
  quantity: 1,
69
69
  unitPrice: p.price,
70
70
  title: p.title,
71
- image: p.images?.[0] ?? p.mainImage,
71
+ image: p.images?.[0]?.url ?? p.mainImage,
72
72
  gstRate: p.gstRate,
73
73
  hsnCode: p.hsnCode,
74
74
  listingType: normalizeListingType(p),
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Reads a statutory business document — GST certificate, Udyam registration,
3
+ * bank passbook — and decrypts it for an admin.
4
+ *
5
+ * 🛑 WHY THIS EXISTS rather than a `/media/{slug}` URL. Same two facts that
6
+ * forced `digital-code/download.ts` into the same shape, and either alone is
7
+ * enough:
8
+ *
9
+ * 1. `storage.rules` grants `allow read: if true` on EVERY object in the
10
+ * bucket. All real access goes through the Admin SDK, so that is an
11
+ * acceptable safety net — but it means Storage itself protects nothing.
12
+ * 2. `GET /api/media/[...slug]` performs NO authentication. It is a bare
13
+ * handler with no session read, deliberately, because its job is public
14
+ * product photography.
15
+ *
16
+ * So the bytes live under a private prefix that mints no `mediaAssets` row —
17
+ * and the row IS the public slug, so no row means no public URL — and are read
18
+ * only from here, after the route has checked the caller is an admin.
19
+ *
20
+ * On top of that, and unlike the digital-code case, these objects are stored
21
+ * ENCRYPTED: a bank passbook sitting in plaintext in a bucket whose rules say
22
+ * `read: if true` would depend entirely on nobody ever minting a slug for it.
23
+ */
24
+ export interface BusinessDocumentResolution {
25
+ ok: boolean;
26
+ status?: number;
27
+ message?: string;
28
+ buffer?: Buffer;
29
+ contentType?: string;
30
+ fileName?: string;
31
+ }
32
+ /**
33
+ * Resolve, download and decrypt the document with id `documentId`.
34
+ *
35
+ * The caller is responsible for the authorization check — the route wraps this
36
+ * in `createRouteHandler({ roles: ROLES_ADMIN_ONLY, permission: "settings:write" })`.
37
+ * This function deliberately takes no viewer: there is no per-row ownership to
38
+ * evaluate, so inventing a `viewerUid` parameter it never reads would imply a
39
+ * check that is not happening here.
40
+ */
41
+ export declare function resolveBusinessDocument(documentId: string): Promise<BusinessDocumentResolution>;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Reads a statutory business document — GST certificate, Udyam registration,
3
+ * bank passbook — and decrypts it for an admin.
4
+ *
5
+ * 🛑 WHY THIS EXISTS rather than a `/media/{slug}` URL. Same two facts that
6
+ * forced `digital-code/download.ts` into the same shape, and either alone is
7
+ * enough:
8
+ *
9
+ * 1. `storage.rules` grants `allow read: if true` on EVERY object in the
10
+ * bucket. All real access goes through the Admin SDK, so that is an
11
+ * acceptable safety net — but it means Storage itself protects nothing.
12
+ * 2. `GET /api/media/[...slug]` performs NO authentication. It is a bare
13
+ * handler with no session read, deliberately, because its job is public
14
+ * product photography.
15
+ *
16
+ * So the bytes live under a private prefix that mints no `mediaAssets` row —
17
+ * and the row IS the public slug, so no row means no public URL — and are read
18
+ * only from here, after the route has checked the caller is an admin.
19
+ *
20
+ * On top of that, and unlike the digital-code case, these objects are stored
21
+ * ENCRYPTED: a bank passbook sitting in plaintext in a bucket whose rules say
22
+ * `read: if true` would depend entirely on nobody ever minting a slug for it.
23
+ */
24
+ import { getAdminStorage } from "../../../../providers/db-firebase/index.js";
25
+ import { normalizeError } from "../../../../errors/normalize.js";
26
+ import { decryptBuffer, isBufferEncrypted } from "../../../../security/settings-encryption.js";
27
+ import { businessDocumentsRepository } from "../../../../features/business-documents/repository/business-documents.repository.js";
28
+ /**
29
+ * Resolve, download and decrypt the document with id `documentId`.
30
+ *
31
+ * The caller is responsible for the authorization check — the route wraps this
32
+ * in `createRouteHandler({ roles: ROLES_ADMIN_ONLY, permission: "settings:write" })`.
33
+ * This function deliberately takes no viewer: there is no per-row ownership to
34
+ * evaluate, so inventing a `viewerUid` parameter it never reads would imply a
35
+ * check that is not happening here.
36
+ */
37
+ export async function resolveBusinessDocument(documentId) {
38
+ const record = await businessDocumentsRepository.findById(documentId);
39
+ if (!record) {
40
+ return { ok: false, status: 404, message: "Document not found" };
41
+ }
42
+ let stored;
43
+ try {
44
+ const file = getAdminStorage().bucket().file(record.storagePath);
45
+ const [buffer] = await file.download();
46
+ stored = buffer;
47
+ }
48
+ catch (err) {
49
+ void normalizeError(err);
50
+ return { ok: false, status: 404, message: "Document is no longer available" };
51
+ }
52
+ /*
53
+ * Branch on the RECORDED flag, never on sniffing the buffer.
54
+ *
55
+ * `isBufferEncrypted` is used only to catch disagreement: a row that claims
56
+ * encryption over an object that has none means the upload half-failed or
57
+ * the object was replaced by hand, and handing those bytes back as though
58
+ * nothing were wrong is how a plaintext passbook gets served while every log
59
+ * line says it was encrypted. Refuse and say which way the mismatch runs.
60
+ */
61
+ if (record.encrypted !== isBufferEncrypted(stored)) {
62
+ return {
63
+ ok: false,
64
+ status: 500,
65
+ message: record.encrypted
66
+ ? "Stored document is not encrypted but its record says it is — refusing to serve it."
67
+ : "Stored document is encrypted but its record says it is not — refusing to guess.",
68
+ };
69
+ }
70
+ let plaintext;
71
+ if (record.encrypted) {
72
+ try {
73
+ plaintext = decryptBuffer(stored);
74
+ }
75
+ catch (err) {
76
+ // A GCM auth failure means the wrong key or a tampered object. Both are
77
+ // worth a 500 and a log; neither is worth telling the caller which.
78
+ void normalizeError(err);
79
+ return { ok: false, status: 500, message: "Document could not be decrypted" };
80
+ }
81
+ }
82
+ else {
83
+ plaintext = stored;
84
+ }
85
+ return {
86
+ ok: true,
87
+ buffer: plaintext,
88
+ contentType: record.contentType || "application/octet-stream",
89
+ fileName: record.fileName || "document",
90
+ };
91
+ }
@@ -31,7 +31,7 @@ import type { CategoryItem } from "../../../../features/categories/types/index";
31
31
  * the object literal in `toCategoryListItem` — the audit asserts both
32
32
  * directions.
33
33
  */
34
- export declare const PUBLIC_CATEGORY_FIELDS: readonly ["id", "name", "slug", "description", "rootId", "parentIds", "childrenIds", "tier", "path", "order", "isLeaf", "ancestors", "categoryType", "itemCode", "isFeatured", "featuredPriority", "seo", "display", "isActive", "highlights", "faqs", "brandWebsite", "brandCountry", "brandFounded", "metrics", "createdAt", "updatedAt"];
34
+ export declare const PUBLIC_CATEGORY_FIELDS: readonly ["id", "name", "slug", "description", "rootId", "parentIds", "childrenIds", "tier", "path", "order", "isLeaf", "ancestors", "categoryType", "itemCode", "isFeatured", "featuredPriority", "seo", "display", "isActive", "highlights", "faqs", "brandWebsite", "brandCountry", "brandFounded", "hasbroName", "hasbroCoverImage", "metrics", "createdAt", "updatedAt"];
35
35
  /**
36
36
  * Fields withheld, each with the reason. Never remove one without replacing
37
37
  * the reason — "it seemed unused" is how a field ends up public by accident.
@@ -37,6 +37,14 @@ export const PUBLIC_CATEGORY_FIELDS = [
37
37
  "brandWebsite",
38
38
  "brandCountry",
39
39
  "brandFounded",
40
+ /*
41
+ * The Hasbro alternate name and its cover, rendered as "Also known as" by
42
+ * `CategoryDetailPageView`. Public because the whole point of the field is
43
+ * that a buyer who only knows the Hasbro season name can SEE the
44
+ * correspondence — a name on a toy box is not sensitive.
45
+ */
46
+ "hasbroName",
47
+ "hasbroCoverImage",
40
48
  // Rollup counts only — see `metrics` in the private list.
41
49
  "metrics",
42
50
  "createdAt",
@@ -217,6 +225,8 @@ export function toCategoryListItem(doc) {
217
225
  brandWebsite: doc.brandWebsite,
218
226
  brandCountry: doc.brandCountry,
219
227
  brandFounded: doc.brandFounded,
228
+ hasbroName: doc.hasbroName,
229
+ hasbroCoverImage: doc.hasbroCoverImage,
220
230
  metrics: toPublicMetrics(doc.metrics),
221
231
  // 🛑 `CategoryDocument` stores Dates; `CategoryItem` declares strings —
222
232
  // this projection is also the serialisation boundary. Converting here
@@ -39,6 +39,20 @@ export declare function resolveShippingCost(storeId: string | undefined): Promis
39
39
  storeState: string | undefined;
40
40
  /** C5b — the resolved policy, so a caller can quote with the cart in hand. */
41
41
  shippingPolicy: StoreShippingPolicy;
42
+ /**
43
+ * The seller's own tax registration, from the store read this function
44
+ * already performs.
45
+ *
46
+ * Returned here rather than re-fetched in `createOrderForGroup` so the
47
+ * checkout path pays no extra Firestore read for data already in scope
48
+ * (Rule #6). Raw fields, not a resolved identity — the seller-vs-platform
49
+ * decision belongs to `resolveSupplierIdentity` alone.
50
+ */
51
+ storeTaxIdentity: {
52
+ gstin?: string;
53
+ legalName?: string;
54
+ registeredAddress?: string;
55
+ } | undefined;
42
56
  /**
43
57
  * 🛑 True when the mode is `estimate` and no carrier rate was supplied.
44
58
  *
@@ -38,11 +38,13 @@ import { CHECKOUT_DEFAULT_COMMISSIONS, CHECKOUT_DEFAULT_EMI_SETTINGS } from "../
38
38
  import { checkEmiEligibility, computeEmiSchedule } from "../../../shared/features/emi/schedule.js";
39
39
  import { formatShippingAddress } from "./data.js";
40
40
  import { enforceMaxPerUserForCart } from "./prize-bundle-gates.js";
41
- import { getListingRule, runSyncPreflight, } from "../../../shared/checkout/rules/index.js";
41
+ import { getListingRule, runSyncPreflight, assertPaymentMethodAllowed, } from "../../../shared/checkout/rules/index.js";
42
+ import { revalidateGroupLines } from "./group-rule-revalidation.js";
42
43
  import { cartIsDigitalOnly } from "../../../shared/listing-types/cart-shipping.js";
43
44
  import { processRefundAction } from "../refunds/actions.js";
44
45
  import { sendNotification } from "../../../../features/admin/actions/notification-actions.js";
45
46
  import { resolveDisplayedUpiId } from "./upi-resolution.js";
47
+ import { resolveSupplierIdentity } from "./supplier-identity.js";
46
48
  import { PAYMENT_WINDOW_MS } from "../../../../features/orders/constants/payment-window.js";
47
49
  import { isCheckoutValueOtpVerified } from "../../../../features/checkout/actions/checkout-value-otp-actions.js";
48
50
  const AUDIT_LOG_FAIL_MSG = "checkout: audit log failed (non-critical)";
@@ -193,6 +195,9 @@ export async function resolveShippingCost(storeId) {
193
195
  shippingPolicy: DEFAULT_STORE_SHIPPING_POLICY,
194
196
  shippingUnavailable: false,
195
197
  storeProtections: { shipping: false, sale: false },
198
+ // No store, so no seller registration — the caller falls back to the
199
+ // platform's via resolveSupplierIdentity.
200
+ storeTaxIdentity: undefined,
196
201
  };
197
202
  }
198
203
  const store = await storeRepository.findById(storeId);
@@ -246,6 +251,25 @@ export async function resolveShippingCost(storeId) {
246
251
  shipping: store?.supportsShippingProtection === true,
247
252
  sale: store?.supportsSaleProtection === true,
248
253
  },
254
+ /*
255
+ * The seller's own tax registration, returned from the store read this
256
+ * function ALREADY does.
257
+ *
258
+ * Deliberately not a second `storeRepository.findById` in
259
+ * `createOrderForGroup`: that would add one Firestore read per order group
260
+ * to the checkout path for data already sitting in this scope, against
261
+ * Rule #6's round-trip budget. Returning the three raw fields rather than
262
+ * the resolved identity keeps the decision in one place —
263
+ * `resolveSupplierIdentity` — instead of splitting it across a shipping
264
+ * helper and a checkout action.
265
+ */
266
+ storeTaxIdentity: store
267
+ ? {
268
+ gstin: store.gstin,
269
+ legalName: store.legalName,
270
+ registeredAddress: store.registeredAddress,
271
+ }
272
+ : undefined,
249
273
  };
250
274
  }
251
275
  /**
@@ -475,7 +499,17 @@ async function createOrderForGroup(group, orderType, ctx) {
475
499
  return expandCartLineToOrderRows(item, product, ctx.productById).map((baseLine) => itemRule.decorateOrderItem(baseLine, product));
476
500
  });
477
501
  const totalQuantity = group.reduce((sum, { item }) => sum + item.quantity, 0);
478
- const { shippingFee, storeOwnerId, storeEmiEnabled, storeState, storeProtections } = await resolveShippingCost(firstItem.storeId);
502
+ const { shippingFee, storeOwnerId, storeEmiEnabled, storeState, storeProtections, storeTaxIdentity } = await resolveShippingCost(firstItem.storeId);
503
+ /*
504
+ * Who issues this invoice — the seller if they have their own GSTIN, the
505
+ * platform otherwise. ONE function decides, and it is the only place that
506
+ * knows the order (Root Cause #75: a money rule reachable by copy-paste
507
+ * gets copied, and the copies miss branches added later).
508
+ *
509
+ * Snapshot below and never recomputed: `OrderDocument`'s own comment is
510
+ * that these are the registration "as it stood at the moment of supply".
511
+ */
512
+ const supplier = resolveSupplierIdentity(storeTaxIdentity, gstSettings ? { gst: gstSettings } : undefined);
479
513
  // P-8 GST — sum per-line-item tax (each product may carry its own gstRate),
480
514
  // then split the group total into a single cgst/sgst/igst breakdown for the
481
515
  // order document. Skipped entirely when GST is off or the buyer's state is
@@ -671,12 +705,17 @@ async function createOrderForGroup(group, orderType, ctx) {
671
705
  * `taxableAmount` so the taxed base stays the base the tax was charged on,
672
706
  * and recorded here so the invoice's columns can reconcile. */
673
707
  exemptAmount: gstBreakdown?.exemptAmount || undefined,
674
- /* Our registration AS IT STANDS NOW. A tax invoice without the supplier's
675
- * GSTIN is not a tax invoice, and the invoice page cannot read it from
676
- * site settings — `gst` is in PRIVATE_SITE_FIELDS. See the schema. */
677
- supplierGstin: gstSettings?.enabled ? gstSettings.gstin || undefined : undefined,
678
- supplierLegalName: gstSettings?.enabled ? gstSettings.legalName || undefined : undefined,
679
- supplierAddress: gstSettings?.enabled ? gstSettings.address || undefined : undefined,
708
+ /* The supplier of record AS IT STANDS NOW. A tax invoice without the
709
+ * supplier's GSTIN is not a tax invoice, and the invoice page cannot read
710
+ * it from site settings — `gst` is in PRIVATE_SITE_FIELDS. See the schema.
711
+ *
712
+ * 🛑 This was `gstSettings.gstin` unconditionally — the PLATFORM's
713
+ * registration on every order ever placed, with no way for a seller to
714
+ * invoice under their own, while the seeded FAQ told buyers otherwise.
715
+ * It now resolves seller-first via `resolveSupplierIdentity`. */
716
+ supplierGstin: supplier.gstin,
717
+ supplierLegalName: supplier.legalName,
718
+ supplierAddress: supplier.address,
680
719
  /* Per-rate, for Rule 46. Computed by `sumGroupGst` rather than re-derived
681
720
  * downstream — a mixed 5%+18% order cannot produce a compliant invoice
682
721
  * from the aggregate triple alone. */
@@ -873,6 +912,23 @@ export async function createCheckoutOrderAction(input) {
873
912
  preTxProductById.set(preTxLookup.productIds[i], snap.data());
874
913
  }
875
914
  }
915
+ /*
916
+ * Payment-method gate — before `enforceMaxPerUserForCart`, which runs count
917
+ * queries, because this answer needs no reads at all.
918
+ *
919
+ * 🛑 `preTxProductById` is the right map and `preTxPairs` below is NOT: that
920
+ * pairing keeps only `getCartItemMemberIds(item)[0]`, so a bundle or grouped
921
+ * line contributes one member and the rest are invisible. The gate walks
922
+ * every member of every line against this map.
923
+ *
924
+ * 🛑 This ONE call site is complete coverage, and that is worth stating so
925
+ * nobody adds a second. Only `cod`/`cash`/`emi` are ever blocked (auction,
926
+ * bundle, prize-draw) and all three arrive here; the Razorpay path is always
927
+ * `"online"`, which no rule blocks — and a throw there would land AFTER
928
+ * capture, taking the buyer's money and then refusing the order. Pre-capture
929
+ * is the only safe place for this, and the method is decided here.
930
+ */
931
+ assertPaymentMethodAllowed(cartItems, preTxProductById, paymentMethod);
876
932
  const preTxPairs = cartItems
877
933
  .map((item) => {
878
934
  const [firstMember] = getCartItemMemberIds(item);
@@ -982,6 +1038,28 @@ export async function createCheckoutOrderAction(input) {
982
1038
  throw new ValidationError(ERROR_MESSAGES.CHECKOUT.INSUFFICIENT_STOCK);
983
1039
  }
984
1040
  const { coupons: appliedCoupons, dropped: droppedCoupons } = await revalidateAppliedCoupons(cart.appliedCoupons ?? [], available, uid);
1041
+ /*
1042
+ * The THIRD group-rule enforcement point: the picker mirrors the rules,
1043
+ * `addGroupLineToCart` enforces them at add time, and this re-checks them at
1044
+ * placement. Without it a rule edited after a line was already in a cart is
1045
+ * never re-checked at all, and a quoted discount percentage outlives the rule
1046
+ * it was copied from.
1047
+ *
1048
+ * 🛑 Runs AFTER the stock bucketing, over `available` rather than the whole
1049
+ * cart — a line already dropped for being out of stock does not need its
1050
+ * group rules adjudicated too, and reporting both about one line would be two
1051
+ * explanations for one outcome.
1052
+ *
1053
+ * A blocked line THROWS: its selection is no longer valid and no price is
1054
+ * right for it. A repriced one is surfaced, which is `droppedCoupons`'
1055
+ * discipline — the buyer is on the payment step and cannot fix a seller's
1056
+ * rule change from there.
1057
+ */
1058
+ const groupRecheck = await revalidateGroupLines(available.map(({ item }) => item));
1059
+ if (groupRecheck.blocked.length > 0) {
1060
+ const first = groupRecheck.blocked[0];
1061
+ throw Object.assign(new ValidationError(`"${first.groupTitle}" can no longer be bought as selected. ${first.reason} Update that line in your cart and try again.`), { code: "GROUP_RULES_CHANGED" });
1062
+ }
985
1063
  const orderGroups = splitCartIntoOrderGroups(available);
986
1064
  // Admin-bypass orders are immediately paid and processing; generate a shared
987
1065
  // transaction reference for all orders in this checkout batch.
@@ -1039,6 +1117,15 @@ export async function createCheckoutOrderAction(input) {
1039
1117
  itemCount: orderIds.length,
1040
1118
  ...(unavailable.length > 0 ? { unavailableItems: unavailable } : {}),
1041
1119
  ...(droppedCoupons.length > 0 ? { droppedCoupons } : {}),
1120
+ ...(groupRecheck.repriced.length > 0
1121
+ ? {
1122
+ repricedGroupLines: groupRecheck.repriced.map((r) => ({
1123
+ groupTitle: r.groupTitle,
1124
+ previousPercent: r.previousPercent,
1125
+ currentPercent: r.currentPercent,
1126
+ })),
1127
+ }
1128
+ : {}),
1042
1129
  };
1043
1130
  }
1044
1131
  const EMPTY_PRICING_PREVIEW = {
@@ -1387,7 +1474,14 @@ async function createPhonePeGroupOrder(group, orderType, ctx) {
1387
1474
  // Reuses the same store/seller lookup as the COD/UPI path above instead
1388
1475
  // of re-implementing it inline — was two sequential findById calls per
1389
1476
  // seller group here, duplicated from resolveShippingCost.
1390
- const { shippingFee, storeOwnerId, storeState } = await resolveShippingCost(firstItem.storeId);
1477
+ const { shippingFee, storeOwnerId, storeState, storeTaxIdentity } = await resolveShippingCost(firstItem.storeId);
1478
+ /*
1479
+ * Same supplier-of-record rule as `createOrderForGroup`, through the same
1480
+ * function. This path (PhonePe verify / webhook) is the SECOND place an
1481
+ * order is created, and the two have drifted before — add-on fees, and the
1482
+ * whole tax breakdown, were both missing here until C0c defect 1.
1483
+ */
1484
+ const supplier = resolveSupplierIdentity(storeTaxIdentity, siteSettings ? { gst: siteSettings.gst } : undefined);
1391
1485
  const groupLines = group.map(({ item, product }) => ({ itemId: item.itemId, lineTotal: lineTotalFor(item, product) }));
1392
1486
  const { couponDiscount, appliedDiscounts } = computeGroupCouponDiscount(appliedCoupons, groupLines, groupTotal, cartSubtotal, firstItem.storeId);
1393
1487
  // Mirrors createOrderForGroup — without this the online-payment path wrote
@@ -1543,9 +1637,9 @@ async function createPhonePeGroupOrder(group, orderType, ctx) {
1543
1637
  exemptAmount: phonepeGst?.exemptAmount || undefined,
1544
1638
  // Our registration at the moment of supply — see the schema. Mirrors the
1545
1639
  // COD/UPI path so both produce an invoiceable order.
1546
- supplierGstin: siteSettings?.gst?.enabled ? siteSettings.gst.gstin || undefined : undefined,
1547
- supplierLegalName: siteSettings?.gst?.enabled ? siteSettings.gst.legalName || undefined : undefined,
1548
- supplierAddress: siteSettings?.gst?.enabled ? siteSettings.gst.address || undefined : undefined,
1640
+ supplierGstin: supplier.gstin,
1641
+ supplierLegalName: supplier.legalName,
1642
+ supplierAddress: supplier.address,
1549
1643
  gstByRate: phonepeGst?.byRate.length ? phonepeGst.byRate : undefined,
1550
1644
  gstAmount: (phonepeGst?.gstAmount ?? 0) + platformFeeGst || undefined,
1551
1645
  cgst: phonepeGst?.cgst || undefined,
@@ -60,6 +60,23 @@ export function validateCartItemStock(item, productById, decrements) {
60
60
  if (!product || product.status !== ProductStatusValues.PUBLISHED) {
61
61
  return { productId: member.productId, availableQty: product?.availableQuantity ?? 0 };
62
62
  }
63
+ /*
64
+ * 🛑 Made to order: skip the stock CHECK for this member.
65
+ *
66
+ * There is nothing to be short of — the thing is printed or built when the
67
+ * order arrives. `availableQuantity` on such a row goes negative by design
68
+ * and that negative IS the production queue, which is why the check is
69
+ * bypassed here and `getExpandedDecrements` above is deliberately left
70
+ * alone: it still counts, the decrement still lands, and
71
+ * `stock-restore.ts` can still mirror it exactly on a cancellation. Skip
72
+ * the decrement instead and a cancelled order restores stock that was
73
+ * never taken.
74
+ *
75
+ * Placed AFTER the published-status check on purpose: a draft or archived
76
+ * listing is unbuyable whatever its production model.
77
+ */
78
+ if (product.madeToOrder === true)
79
+ continue;
63
80
  // The fallback must be member-weighted too. Left as a bare `item.quantity`
64
81
  // it would validate a line needing 3× of a member against demand for 1
65
82
  // whenever the cumulative map didn't happen to carry that product.
@@ -35,4 +35,26 @@ export interface CheckoutOrderResult {
35
35
  code: string;
36
36
  reason: string;
37
37
  }[];
38
+ /**
39
+ * Grouped lines whose group DISCOUNT had changed since they were added. The
40
+ * order is priced at the group's current rule and the change surfaced here,
41
+ * for the same reason `droppedCoupons` exists: honouring the stale percent
42
+ * would charge less than the seller now offers, and changing a total the
43
+ * buyer has read without telling them is worse than either.
44
+ */
45
+ repricedGroupLines?: {
46
+ groupTitle: string;
47
+ previousPercent: number;
48
+ currentPercent: number;
49
+ }[];
50
+ /**
51
+ * Grouped lines whose selection no longer satisfies the group's rules — the
52
+ * seller tightened them after the line was added. REPORTED rather than
53
+ * repriced: "this group now requires item X" cannot be fixed by adjusting a
54
+ * number, so the line is not silently bought.
55
+ */
56
+ blockedGroupLines?: {
57
+ groupTitle: string;
58
+ reason: string;
59
+ }[];
38
60
  }
@@ -0,0 +1,34 @@
1
+ import type { CartItemDocument } from "../../../../features/cart/schemas/firestore";
2
+ export interface GroupLineRepriced {
3
+ itemId: string;
4
+ groupTitle: string;
5
+ /** What the line was quoted at. */
6
+ previousPercent: number;
7
+ /** What the group's rule says now. */
8
+ currentPercent: number;
9
+ }
10
+ export interface GroupLineBlocked {
11
+ itemId: string;
12
+ groupTitle: string;
13
+ /** Buyer-facing, from `checkGroupRules`. */
14
+ reason: string;
15
+ }
16
+ export interface GroupRuleRevalidation {
17
+ repriced: GroupLineRepriced[];
18
+ blocked: GroupLineBlocked[];
19
+ }
20
+ /**
21
+ * Re-validate every multi-member line in the checkout batch.
22
+ *
23
+ * 🛑 A null `rules` — the group is gone, or the read failed — is treated as
24
+ * UNRESTRICTED and the line is left exactly as it is. Failing open is right in
25
+ * both cases: a transient Firestore error must not block a payment, and a
26
+ * deleted group is not a reason to refuse a selection the buyer already made
27
+ * and already had priced.
28
+ *
29
+ * 🛑 Bundle lines are deliberately skipped. A bundle is all-or-nothing with its
30
+ * own locked price — `unitPriceFor`'s bundle branch runs BEFORE its members
31
+ * branch precisely so the discount that IS the bundle is not recomputed from
32
+ * list prices — so self-assembly rules have nothing to say about one.
33
+ */
34
+ export declare function revalidateGroupLines(items: readonly CartItemDocument[]): Promise<GroupRuleRevalidation>;
@@ -0,0 +1,124 @@
1
+ /*
2
+ * WHY: A group's rules and its discount are seller-editable, and a cart can sit
3
+ * for days. `addGroupLineToCart` checked both at add time and nothing
4
+ * re-checked them — so a rule tightened afterwards was never applied, and
5
+ * a line kept quoting a discount percentage the seller had since changed.
6
+ * WHAT: The third enforcement point — re-validate every multi-member line
7
+ * against its group's CURRENT rules, immediately before pricing.
8
+ *
9
+ * 🛑 IT REPORTS, IT DOES NOT SILENTLY RESOLVE. A changed discount is the
10
+ * delicate case and it has two wrong answers: honouring the stale percent
11
+ * charges less than the seller now offers, and re-deriving silently changes a
12
+ * total the buyer has already read and agreed to. So the line is repriced to
13
+ * the current rule AND the change is handed back to the caller to surface —
14
+ * exactly what `revalidateAppliedCoupons` does with a lapsed coupon, for the
15
+ * same reason: the buyer is on the payment step and cannot fix a seller's rule
16
+ * change from there, so failing the whole checkout is hostile.
17
+ *
18
+ * 🛑 A rule VIOLATION is different from a repriced discount and is treated
19
+ * differently. "This group now requires item X" cannot be fixed by adjusting a
20
+ * number — the selection itself is no longer valid — so that line is reported
21
+ * as blocked rather than quietly bought.
22
+ *
23
+ * EXPORTS: GroupLineRepriced, GroupLineBlocked, GroupRuleRevalidation,
24
+ * revalidateGroupLines
25
+ *
26
+ * @tag domain:checkout
27
+ * @tag layer:server
28
+ * @tag pattern:none
29
+ * @tag access:server
30
+ * @tag consumers:checkout/actions
31
+ * @tag sideEffects:firestore
32
+ */
33
+ import { safeRead } from "../../../../errors/safe-read.js";
34
+ import { serverLogger } from "../../../../monitoring/server-logger.js";
35
+ import { productRepository } from "../../../../repositories/index.js";
36
+ import { groupedListingsRepository } from "../../../../features/grouped/repository/grouped-listings.repository.js";
37
+ import { checkGroupRules, readGroupRules, } from "../../../shared/features/products/group-rules.js";
38
+ import { isMultiMemberLine } from "../../../shared/checkout/line-members.js";
39
+ /** One group's rules, from whichever of the two homes owns them. */
40
+ async function rulesFor(item) {
41
+ const groupId = item.groupId;
42
+ if (!groupId)
43
+ return null;
44
+ if (item.groupSource === "grouped-listing") {
45
+ const doc = await safeRead(() => groupedListingsRepository.findById(groupId), {
46
+ route: "/checkout",
47
+ key: "groupedListings.rules",
48
+ fallback: null,
49
+ });
50
+ return doc ? readGroupRules(doc) : null;
51
+ }
52
+ /*
53
+ * A product group's rules live on the PARENT product, and `groupId` IS the
54
+ * parent's slug (`startGroup` sets `groupId = slug`, and products are pure
55
+ * slugs), so this resolves directly.
56
+ */
57
+ const parent = await safeRead(() => productRepository.findById(groupId), {
58
+ route: "/checkout",
59
+ key: "products.groupParentRules",
60
+ fallback: null,
61
+ });
62
+ return parent ? readGroupRules(parent) : null;
63
+ }
64
+ /**
65
+ * Re-validate every multi-member line in the checkout batch.
66
+ *
67
+ * 🛑 A null `rules` — the group is gone, or the read failed — is treated as
68
+ * UNRESTRICTED and the line is left exactly as it is. Failing open is right in
69
+ * both cases: a transient Firestore error must not block a payment, and a
70
+ * deleted group is not a reason to refuse a selection the buyer already made
71
+ * and already had priced.
72
+ *
73
+ * 🛑 Bundle lines are deliberately skipped. A bundle is all-or-nothing with its
74
+ * own locked price — `unitPriceFor`'s bundle branch runs BEFORE its members
75
+ * branch precisely so the discount that IS the bundle is not recomputed from
76
+ * list prices — so self-assembly rules have nothing to say about one.
77
+ */
78
+ export async function revalidateGroupLines(items) {
79
+ const repriced = [];
80
+ const blocked = [];
81
+ const lines = items.filter((i) => isMultiMemberLine(i) && !i.bundleCategorySlug && i.lineKind === "group");
82
+ if (lines.length === 0)
83
+ return { repriced, blocked };
84
+ for (const item of lines) {
85
+ const rules = await rulesFor(item);
86
+ if (!rules)
87
+ continue;
88
+ const members = item.groupMembers ?? [];
89
+ const violations = checkGroupRules(rules, members.map((m) => ({
90
+ productId: m.productId,
91
+ quantity: m.quantity,
92
+ title: m.title,
93
+ })));
94
+ if (violations.length > 0) {
95
+ blocked.push({
96
+ itemId: item.itemId,
97
+ groupTitle: item.groupTitle ?? item.productTitle,
98
+ reason: violations[0].message,
99
+ });
100
+ /*
101
+ * Reported and NOT repriced. A blocked line's price is irrelevant — the
102
+ * caller is about to refuse it — and repricing it first would leave a
103
+ * stored price for a line that never sold.
104
+ */
105
+ continue;
106
+ }
107
+ const quoted = item.groupDiscountPercent ?? 0;
108
+ const current = Math.min(100, Math.max(0, rules.groupDiscountPercent ?? 0));
109
+ if (quoted !== current) {
110
+ repriced.push({
111
+ itemId: item.itemId,
112
+ groupTitle: item.groupTitle ?? item.productTitle,
113
+ previousPercent: quoted,
114
+ currentPercent: current,
115
+ });
116
+ serverLogger.info("checkout: group discount changed since add-to-cart", {
117
+ itemId: item.itemId,
118
+ quoted,
119
+ current,
120
+ });
121
+ }
122
+ }
123
+ return { repriced, blocked };
124
+ }