@mohasinac/appkit 4.53.0 → 4.53.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (520) hide show
  1. package/dist/.build-stamp.json +3 -3
  2. package/dist/_internal/client/scaffolds/AppShell.js +1 -1
  3. package/dist/_internal/client/theme/ThemeProvider.js +15 -1
  4. package/dist/_internal/server/features/auctions/og.d.ts +3 -1
  5. package/dist/_internal/server/features/auctions/og.js +3 -1
  6. package/dist/_internal/server/features/bundles/actions.js +1 -1
  7. package/dist/_internal/server/features/business-documents/download.d.ts +41 -0
  8. package/dist/_internal/server/features/business-documents/download.js +91 -0
  9. package/dist/_internal/server/features/categories/adapters.d.ts +1 -1
  10. package/dist/_internal/server/features/categories/adapters.js +10 -0
  11. package/dist/_internal/server/features/categories/price-guidance-resolve.d.ts +66 -0
  12. package/dist/_internal/server/features/categories/price-guidance-resolve.js +138 -0
  13. package/dist/_internal/server/features/checkout/actions.d.ts +14 -0
  14. package/dist/_internal/server/features/checkout/actions.js +106 -12
  15. package/dist/_internal/server/features/checkout/bundle-expansion.js +17 -0
  16. package/dist/_internal/server/features/checkout/data.d.ts +22 -0
  17. package/dist/_internal/server/features/checkout/group-rule-revalidation.d.ts +34 -0
  18. package/dist/_internal/server/features/checkout/group-rule-revalidation.js +124 -0
  19. package/dist/_internal/server/features/checkout/supplier-identity.d.ts +55 -0
  20. package/dist/_internal/server/features/checkout/supplier-identity.js +81 -0
  21. package/dist/_internal/server/features/classified/metadata.js +1 -1
  22. package/dist/_internal/server/features/classified/og.d.ts +3 -1
  23. package/dist/_internal/server/features/classified/og.js +3 -1
  24. package/dist/_internal/server/features/digital-code/metadata.js +1 -1
  25. package/dist/_internal/server/features/digital-code/og.d.ts +3 -1
  26. package/dist/_internal/server/features/digital-code/og.js +3 -1
  27. package/dist/_internal/server/features/digital-code/pool.d.ts +19 -4
  28. package/dist/_internal/server/features/digital-code/pool.js +19 -4
  29. package/dist/_internal/server/features/live/metadata.js +1 -1
  30. package/dist/_internal/server/features/live/og.d.ts +3 -1
  31. package/dist/_internal/server/features/live/og.js +3 -1
  32. package/dist/_internal/server/features/messages/actions.js +1 -1
  33. package/dist/_internal/server/features/parts/og.js +1 -1
  34. package/dist/_internal/server/features/pre-orders/og.d.ts +3 -1
  35. package/dist/_internal/server/features/pre-orders/og.js +3 -1
  36. package/dist/_internal/server/features/price-index/market.d.ts +57 -0
  37. package/dist/_internal/server/features/price-index/market.js +120 -0
  38. package/dist/_internal/server/features/price-index/search.d.ts +18 -0
  39. package/dist/_internal/server/features/price-index/search.js +47 -7
  40. package/dist/_internal/server/features/prize-draws/og.d.ts +3 -1
  41. package/dist/_internal/server/features/prize-draws/og.js +3 -1
  42. package/dist/_internal/server/features/products/group-members.d.ts +26 -0
  43. package/dist/_internal/server/features/products/group-members.js +7 -1
  44. package/dist/_internal/server/features/products/list-public.d.ts +12 -0
  45. package/dist/_internal/server/features/products/list-public.js +10 -1
  46. package/dist/_internal/server/features/products/listing-tab-counts.d.ts +25 -1
  47. package/dist/_internal/server/features/products/listing-tab-counts.js +128 -10
  48. package/dist/_internal/server/features/products/og.d.ts +3 -1
  49. package/dist/_internal/server/features/products/og.js +3 -1
  50. package/dist/_internal/server/features/search/scoped-sources.d.ts +26 -0
  51. package/dist/_internal/server/features/search/scoped-sources.js +252 -0
  52. package/dist/_internal/server/features/search/search-everything.d.ts +57 -0
  53. package/dist/_internal/server/features/search/search-everything.js +70 -20
  54. package/dist/_internal/server/features/seo/sitemap.js +6 -0
  55. package/dist/_internal/server/features/shared/listing-adapters.js +4 -2
  56. package/dist/_internal/server/features/sticker-trace/adapters.d.ts +11 -0
  57. package/dist/_internal/server/features/sticker-trace/adapters.js +1 -0
  58. package/dist/_internal/server/features/sticker-trace/promote-to-listings.d.ts +26 -0
  59. package/dist/_internal/server/features/sticker-trace/promote-to-listings.js +264 -0
  60. package/dist/_internal/server/features/sticker-trace/sheet-actions.d.ts +3 -1
  61. package/dist/_internal/server/features/sticker-trace/sheet-actions.js +32 -0
  62. package/dist/_internal/server/features/sticker-trace/storage.d.ts +20 -1
  63. package/dist/_internal/server/features/sticker-trace/storage.js +20 -1
  64. package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
  65. package/dist/_internal/server/features/stores/adapters.js +16 -0
  66. package/dist/_internal/server/features/stores/index.d.ts +1 -0
  67. package/dist/_internal/server/features/stores/index.js +1 -0
  68. package/dist/_internal/server/features/stores/tabs.d.ts +30 -0
  69. package/dist/_internal/server/features/stores/tabs.js +124 -0
  70. package/dist/_internal/shared/checkout/rules/_defaults.js +0 -2
  71. package/dist/_internal/shared/checkout/rules/_limits.d.ts +14 -1
  72. package/dist/_internal/shared/checkout/rules/_limits.js +14 -1
  73. package/dist/_internal/shared/checkout/rules/_registry.js +2 -0
  74. package/dist/_internal/shared/checkout/rules/auction.rule.js +9 -1
  75. package/dist/_internal/shared/checkout/rules/bundle.rule.js +13 -0
  76. package/dist/_internal/shared/checkout/rules/index.d.ts +2 -0
  77. package/dist/_internal/shared/checkout/rules/index.js +9 -0
  78. package/dist/_internal/shared/checkout/rules/offer.rule.js +0 -1
  79. package/dist/_internal/shared/checkout/rules/payment-gate.d.ts +26 -0
  80. package/dist/_internal/shared/checkout/rules/payment-gate.js +133 -0
  81. package/dist/_internal/shared/checkout/rules/prize-draw.rule.js +29 -8
  82. package/dist/_internal/shared/checkout/rules/spares.rule.d.ts +16 -0
  83. package/dist/_internal/shared/checkout/rules/spares.rule.js +5 -0
  84. package/dist/_internal/shared/checkout/rules/types.d.ts +26 -2
  85. package/dist/_internal/shared/config/schema.d.ts +122 -0
  86. package/dist/_internal/shared/features/cart/schema.js +3 -2
  87. package/dist/_internal/shared/features/products/group-rules.d.ts +75 -0
  88. package/dist/_internal/shared/features/products/group-rules.js +142 -0
  89. package/dist/_internal/shared/listing-types/_registry.d.ts +24 -0
  90. package/dist/_internal/shared/listing-types/_registry.js +39 -1
  91. package/dist/_internal/shared/listing-types/art/config.d.ts +1 -0
  92. package/dist/_internal/shared/listing-types/art/config.js +2 -0
  93. package/dist/_internal/shared/listing-types/auction/config.d.ts +1 -0
  94. package/dist/_internal/shared/listing-types/auction/config.js +2 -0
  95. package/dist/_internal/shared/listing-types/availability.js +48 -0
  96. package/dist/_internal/shared/listing-types/capabilities.js +19 -0
  97. package/dist/_internal/shared/listing-types/classified/config.d.ts +1 -0
  98. package/dist/_internal/shared/listing-types/classified/config.js +2 -0
  99. package/dist/_internal/shared/listing-types/digital-code/config.d.ts +1 -0
  100. package/dist/_internal/shared/listing-types/digital-code/config.js +2 -0
  101. package/dist/_internal/shared/listing-types/feature-flags.js +1 -0
  102. package/dist/_internal/shared/listing-types/live/config.d.ts +1 -0
  103. package/dist/_internal/shared/listing-types/live/config.js +2 -0
  104. package/dist/_internal/shared/listing-types/pre-order/config.d.ts +1 -0
  105. package/dist/_internal/shared/listing-types/pre-order/config.js +2 -0
  106. package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +1 -0
  107. package/dist/_internal/shared/listing-types/prize-draw/config.js +2 -0
  108. package/dist/_internal/shared/listing-types/spares/config.d.ts +74 -0
  109. package/dist/_internal/shared/listing-types/spares/config.js +60 -0
  110. package/dist/_internal/shared/listing-types/spares/ctas.d.ts +1 -0
  111. package/dist/_internal/shared/listing-types/spares/ctas.js +4 -0
  112. package/dist/_internal/shared/listing-types/spares/og.js +1 -0
  113. package/dist/_internal/shared/listing-types/spares/schema.d.ts +2 -0
  114. package/dist/_internal/shared/listing-types/spares/schema.js +3 -0
  115. package/dist/_internal/shared/listing-types/spares/seed-factory.d.ts +1 -0
  116. package/dist/_internal/shared/listing-types/spares/seed-factory.js +1 -0
  117. package/dist/_internal/shared/listing-types/standard/config.d.ts +1 -0
  118. package/dist/_internal/shared/listing-types/standard/config.js +2 -0
  119. package/dist/_internal/shared/listing-types/stickers/config.d.ts +1 -0
  120. package/dist/_internal/shared/listing-types/stickers/config.js +2 -0
  121. package/dist/_internal/shared/search/match.d.ts +11 -0
  122. package/dist/_internal/shared/search/match.js +30 -3
  123. package/dist/_internal/shared/search/to-groups.d.ts +52 -0
  124. package/dist/_internal/shared/search/to-groups.js +141 -0
  125. package/dist/client.d.ts +8 -2
  126. package/dist/client.js +4 -1
  127. package/dist/constants/api-endpoints.d.ts +46 -15
  128. package/dist/constants/api-endpoints.js +35 -5
  129. package/dist/constants/cache-invalidation.js +3 -1
  130. package/dist/constants/field-names.d.ts +6 -0
  131. package/dist/constants/field-names.js +6 -0
  132. package/dist/features/about/components/PolicyPageView.d.ts +22 -2
  133. package/dist/features/about/components/PolicyPageView.js +14 -2
  134. package/dist/features/about/components/PublicProfileView.js +2 -1
  135. package/dist/features/about/components/ShippingPolicyView.js +42 -2
  136. package/dist/features/account/components/NotificationBell.js +1 -1
  137. package/dist/features/account/hooks/useProfileStats.js +5 -1
  138. package/dist/features/addresses/repository/addresses.repository.d.ts +16 -0
  139. package/dist/features/addresses/repository/addresses.repository.js +21 -0
  140. package/dist/features/admin/actions/admin-actions.js +16 -1
  141. package/dist/features/admin/components/AdminCategoryEditorView.js +19 -2
  142. package/dist/features/admin/components/AdminNavigationView.js +1 -1
  143. package/dist/features/admin/components/AdminPageHeader.js +1 -1
  144. package/dist/features/admin/components/AdminProductEditorView.js +17 -2
  145. package/dist/features/admin/components/AdminSidebar.js +1 -1
  146. package/dist/features/admin/components/AdminSiteSettingsView.js +39 -8
  147. package/dist/features/admin/components/AdminSparesView.d.ts +12 -0
  148. package/dist/features/admin/components/AdminSparesView.js +30 -0
  149. package/dist/features/admin/components/AdminUsersView.js +9 -7
  150. package/dist/features/admin/components/index.d.ts +2 -0
  151. package/dist/features/admin/components/index.js +1 -0
  152. package/dist/features/admin/components/sections/adminSectionsTypes.js +7 -0
  153. package/dist/features/admin/constants/filter-tabs.d.ts +3 -0
  154. package/dist/features/admin/constants/filter-tabs.js +1 -0
  155. package/dist/features/admin/schemas/firestore.d.ts +26 -2
  156. package/dist/features/auctions/components/AuctionDetailPageView.js +12 -18
  157. package/dist/features/auth/repository/user.repository.d.ts +13 -0
  158. package/dist/features/auth/repository/user.repository.js +28 -0
  159. package/dist/features/auth/schemas/firestore.d.ts +2 -0
  160. package/dist/features/auth/schemas/firestore.js +2 -0
  161. package/dist/features/business-documents/repository/business-documents.repository.d.ts +58 -0
  162. package/dist/features/business-documents/repository/business-documents.repository.js +54 -0
  163. package/dist/features/business-documents/schemas/firestore.d.ts +105 -0
  164. package/dist/features/business-documents/schemas/firestore.js +75 -0
  165. package/dist/features/cart/actions/cart-actions.js +83 -6
  166. package/dist/features/cart/repository/cart.repository.js +32 -4
  167. package/dist/features/cart/schemas/firestore.d.ts +20 -0
  168. package/dist/features/cart/schemas/index.d.ts +2 -2
  169. package/dist/features/catalogue/components/PublicCatalogueItemDetailView.js +1 -1
  170. package/dist/features/categories/api/[id]/price-guidance/route.d.ts +42 -0
  171. package/dist/features/categories/api/[id]/price-guidance/route.js +90 -0
  172. package/dist/features/categories/components/BrandDetailPageView.js +32 -8
  173. package/dist/features/categories/components/BrandDetailTabs.d.ts +7 -1
  174. package/dist/features/categories/components/BrandDetailTabs.js +28 -3
  175. package/dist/features/categories/components/BundleCollage.js +3 -2
  176. package/dist/features/categories/components/BundleItemsPicker.js +3 -4
  177. package/dist/features/categories/components/CategoriesIndexListing.js +23 -8
  178. package/dist/features/categories/components/CategoryDetailPageView.js +157 -20
  179. package/dist/features/categories/components/CategoryDetailTabs.d.ts +7 -1
  180. package/dist/features/categories/components/CategoryDetailTabs.js +41 -7
  181. package/dist/features/categories/components/CategoryGrid.js +10 -1
  182. package/dist/features/categories/components/PriceGuidanceHint.d.ts +29 -0
  183. package/dist/features/categories/components/PriceGuidanceHint.js +61 -0
  184. package/dist/features/categories/components/SubcategoryCardRow.d.ts +27 -0
  185. package/dist/features/categories/components/SubcategoryCardRow.js +98 -0
  186. package/dist/features/categories/constants/category-tabs.d.ts +20 -25
  187. package/dist/features/categories/constants/category-tabs.js +22 -39
  188. package/dist/features/categories/repository/categories.repository.d.ts +12 -0
  189. package/dist/features/categories/repository/categories.repository.js +20 -0
  190. package/dist/features/categories/schemas/firestore.d.ts +22 -1
  191. package/dist/features/categories/schemas/firestore.js +10 -0
  192. package/dist/features/categories/schemas/index.d.ts +6 -0
  193. package/dist/features/categories/schemas/index.js +2 -0
  194. package/dist/features/categories/types/index.d.ts +8 -0
  195. package/dist/features/categories/utils/taxonomy-visual.d.ts +16 -3
  196. package/dist/features/categories/utils/taxonomy-visual.js +26 -10
  197. package/dist/features/classified/components/ClassifiedDetailPageView.js +14 -10
  198. package/dist/features/contact/components/ContactPageView.d.ts +33 -1
  199. package/dist/features/contact/components/ContactPageView.js +58 -28
  200. package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +14 -10
  201. package/dist/features/grouped/components/GroupedListingDetailView.js +9 -1
  202. package/dist/features/grouped/schemas/firestore.d.ts +5 -0
  203. package/dist/features/homepage/actions/homepage-section-actions.d.ts +3 -3
  204. package/dist/features/homepage/components/CollectionCardsSection.d.ts +28 -6
  205. package/dist/features/homepage/components/CollectionCardsSection.js +43 -8
  206. package/dist/features/homepage/components/HowItWorksSection.d.ts +23 -6
  207. package/dist/features/homepage/components/HowItWorksSection.js +4 -4
  208. package/dist/features/homepage/components/PromoGrid.d.ts +31 -2
  209. package/dist/features/homepage/components/PromoGrid.js +12 -3
  210. package/dist/features/homepage/components/TestimonialsCarousel.d.ts +34 -2
  211. package/dist/features/homepage/components/TestimonialsCarousel.js +1 -1
  212. package/dist/features/homepage/components/index.d.ts +0 -20
  213. package/dist/features/homepage/components/index.js +0 -11
  214. package/dist/features/homepage/index.d.ts +0 -2
  215. package/dist/features/homepage/index.js +0 -2
  216. package/dist/features/homepage/lib/section-renderer.d.ts +9 -0
  217. package/dist/features/homepage/lib/section-renderer.js +202 -58
  218. package/dist/features/homepage/repository/homepage-sections.repository.d.ts +35 -3
  219. package/dist/features/homepage/repository/homepage-sections.repository.js +58 -8
  220. package/dist/features/homepage/schemas/firestore.d.ts +106 -3
  221. package/dist/features/homepage/schemas/firestore.js +32 -2
  222. package/dist/features/homepage/schemas/index.d.ts +36 -7
  223. package/dist/features/homepage/schemas/index.js +39 -27
  224. package/dist/features/homepage/server.d.ts +0 -3
  225. package/dist/features/homepage/server.js +0 -3
  226. package/dist/features/homepage/types/index.d.ts +0 -47
  227. package/dist/features/homepage/types/index.js +49 -0
  228. package/dist/features/layout/AppLayoutShell.js +1 -1
  229. package/dist/features/layout/BottomNavItem.js +1 -1
  230. package/dist/features/layout/BottomSheet.js +1 -1
  231. package/dist/features/layout/TitleBarLayout.js +1 -1
  232. package/dist/features/live/components/LiveItemDetailPageView.js +14 -10
  233. package/dist/features/media/hooks/useMedia.js +17 -0
  234. package/dist/features/media/repository/media-assets.repository.d.ts +46 -0
  235. package/dist/features/media/repository/media-assets.repository.js +31 -0
  236. package/dist/features/media/trust-signals.d.ts +85 -0
  237. package/dist/features/media/trust-signals.js +126 -0
  238. package/dist/features/parts/components/PartDetailPageView.d.ts +14 -1
  239. package/dist/features/parts/components/PartDetailPageView.js +2 -2
  240. package/dist/features/parts/components/PartsIndexPageView.d.ts +11 -2
  241. package/dist/features/parts/components/PartsIndexPageView.js +2 -2
  242. package/dist/features/parts/components/PartsSearchBox.d.ts +9 -0
  243. package/dist/features/parts/components/PartsSearchBox.js +57 -0
  244. package/dist/features/parts/schemas/firestore.d.ts +149 -3
  245. package/dist/features/parts/schemas/firestore.js +184 -0
  246. package/dist/features/payments/repository/payout.repository.d.ts +15 -0
  247. package/dist/features/payments/repository/payout.repository.js +21 -0
  248. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +12 -18
  249. package/dist/features/pre-orders/components/PreOrdersIndexListing.js +1 -1
  250. package/dist/features/price-index/components/PriceIndexToolView.d.ts +24 -1
  251. package/dist/features/price-index/components/PriceIndexToolView.js +299 -17
  252. package/dist/features/price-index/lookup-target.d.ts +48 -0
  253. package/dist/features/price-index/lookup-target.js +107 -0
  254. package/dist/features/products/components/AvailabilityScopeHint.d.ts +22 -0
  255. package/dist/features/products/components/AvailabilityScopeHint.js +27 -0
  256. package/dist/features/products/components/CompareOverlay.d.ts +20 -2
  257. package/dist/features/products/components/CompareOverlay.js +23 -3
  258. package/dist/features/products/components/CustomSectionTabContent.d.ts +31 -0
  259. package/dist/features/products/components/CustomSectionTabContent.js +29 -3
  260. package/dist/features/products/components/GroupMemberPicker.d.ts +19 -1
  261. package/dist/features/products/components/GroupMemberPicker.js +46 -8
  262. package/dist/features/products/components/GroupSettingsPanel.d.ts +11 -1
  263. package/dist/features/products/components/GroupSettingsPanel.js +92 -3
  264. package/dist/features/products/components/PrizeDrawDetailPageView.js +1 -1
  265. package/dist/features/products/components/PrizeDrawEntryActions.d.ts +15 -1
  266. package/dist/features/products/components/PrizeDrawEntryActions.js +70 -8
  267. package/dist/features/products/components/ProductDetailPageView.js +81 -17
  268. package/dist/features/products/components/ProductForm.d.ts +13 -1
  269. package/dist/features/products/components/ProductForm.js +16 -2
  270. package/dist/features/products/components/ProductsIndexListing.d.ts +16 -1
  271. package/dist/features/products/components/ProductsIndexListing.js +3 -3
  272. package/dist/features/products/components/ShowGroupSection.js +15 -2
  273. package/dist/features/products/components/SparesListView.d.ts +7 -0
  274. package/dist/features/products/components/SparesListView.js +39 -0
  275. package/dist/features/products/components/SublistingCarouselSection.js +2 -1
  276. package/dist/features/products/constants/action-defs.d.ts +1 -0
  277. package/dist/features/products/constants/action-defs.js +1 -0
  278. package/dist/features/products/repository/products.repository.d.ts +99 -0
  279. package/dist/features/products/repository/products.repository.js +240 -18
  280. package/dist/features/products/schemas/firestore.d.ts +97 -4
  281. package/dist/features/products/schemas/firestore.js +104 -0
  282. package/dist/features/products/schemas/index.d.ts +10 -19
  283. package/dist/features/products/schemas/index.js +23 -6
  284. package/dist/features/products/types/index.d.ts +45 -1
  285. package/dist/features/products/utils/group-member-image.d.ts +46 -0
  286. package/dist/features/products/utils/group-member-image.js +4 -0
  287. package/dist/features/products/utils/listing-badge-variant.js +4 -0
  288. package/dist/features/reviews/components/ReviewsList.js +1 -1
  289. package/dist/features/scams/components/ScamProfileView.js +1 -1
  290. package/dist/features/search/components/EntityTypeahead.d.ts +44 -0
  291. package/dist/features/search/components/EntityTypeahead.js +92 -0
  292. package/dist/features/search/components/Search.d.ts +12 -1
  293. package/dist/features/search/components/Search.js +47 -3
  294. package/dist/features/search/components/SearchFacetRail.d.ts +11 -0
  295. package/dist/features/search/components/SearchFacetRail.js +92 -0
  296. package/dist/features/search/components/SearchResultsClient.d.ts +33 -0
  297. package/dist/features/search/components/SearchResultsClient.js +103 -0
  298. package/dist/features/search/components/SearchResultsPageView.d.ts +15 -1
  299. package/dist/features/search/components/SearchResultsPageView.js +2 -2
  300. package/dist/features/search/components/index.d.ts +0 -6
  301. package/dist/features/search/components/index.js +0 -3
  302. package/dist/features/search/hooks/useNavSuggestions.d.ts +13 -0
  303. package/dist/features/search/hooks/useScopedSearch.d.ts +34 -0
  304. package/dist/features/search/hooks/useScopedSearch.js +114 -0
  305. package/dist/features/search/hooks/useSiteSearch.d.ts +26 -0
  306. package/dist/features/search/hooks/useSiteSearch.js +149 -0
  307. package/dist/features/search/index.d.ts +0 -4
  308. package/dist/features/search/index.js +0 -4
  309. package/dist/features/search/manifest.d.ts +12 -0
  310. package/dist/features/search/manifest.js +17 -2
  311. package/dist/features/search/server.d.ts +0 -3
  312. package/dist/features/search/server.js +0 -3
  313. package/dist/features/seller/components/SellerListingTypeView.d.ts +1 -1
  314. package/dist/features/seller/components/SellerListingTypeView.js +20 -0
  315. package/dist/features/seller/components/SellerPayoutSettingsView.js +35 -14
  316. package/dist/features/seller/components/SellerProductShell.d.ts +1 -1
  317. package/dist/features/seller/components/SellerProductShell.js +2 -1
  318. package/dist/features/seller/components/SellerProductsView.js +3 -2
  319. package/dist/features/seller/components/SellerSidebar.js +1 -1
  320. package/dist/features/seller/components/SellerSparesView.d.ts +17 -0
  321. package/dist/features/seller/components/SellerSparesView.js +6 -0
  322. package/dist/features/seller/components/index.d.ts +2 -0
  323. package/dist/features/seller/components/index.js +1 -0
  324. package/dist/features/shell/CommandPalette.js +1 -1
  325. package/dist/features/sticker-trace/schemas/firestore.d.ts +19 -0
  326. package/dist/features/stores/components/StoreAuctionsListing.js +2 -1
  327. package/dist/features/stores/components/StoreDetailLayoutView.d.ts +1 -1
  328. package/dist/features/stores/components/StoreDetailLayoutView.js +7 -82
  329. package/dist/features/stores/components/StoreHeader.js +1 -2
  330. package/dist/features/stores/components/StoreSparesPageView.d.ts +27 -0
  331. package/dist/features/stores/components/StoreSparesPageView.js +48 -0
  332. package/dist/features/stores/schemas/firestore.d.ts +19 -0
  333. package/dist/features/tester/seed-data/authored/buying__spares-and-groups.d.ts +2 -0
  334. package/dist/features/tester/seed-data/authored/buying__spares-and-groups.js +96 -0
  335. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.d.ts +2 -0
  336. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.js +392 -45
  337. package/dist/features/tester/seed-data/authored/content-discovery__category-tabs-franchise-bundles.js +54 -32
  338. package/dist/features/tester/seed-data/authored/content-discovery__parts-database.js +3 -2
  339. package/dist/features/tester/seed-data/authored/content-discovery__price-index-and-compare.d.ts +2 -0
  340. package/dist/features/tester/seed-data/authored/content-discovery__price-index-and-compare.js +73 -0
  341. package/dist/features/tester/seed-data/authored/content-discovery__site-wide-index.d.ts +2 -0
  342. package/dist/features/tester/seed-data/authored/content-discovery__site-wide-index.js +340 -0
  343. package/dist/features/tester/seed-data/authored/index.js +16 -0
  344. package/dist/features/tester/seed-data/authored/search-and-nav__header-search.d.ts +1 -0
  345. package/dist/features/tester/seed-data/authored/search-and-nav__header-search.js +57 -0
  346. package/dist/features/tester/seed-data/authored/selling__spares-and-group-editing.d.ts +2 -0
  347. package/dist/features/tester/seed-data/authored/selling__spares-and-group-editing.js +77 -0
  348. package/dist/features/tester/seed-data/authored/tools__sticker-promote-to-listings.d.ts +2 -0
  349. package/dist/features/tester/seed-data/authored/tools__sticker-promote-to-listings.js +58 -0
  350. package/dist/features/tester/seed-data/authored/tools__sticker-tracer.js +5 -4
  351. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +384 -18
  352. package/dist/index.d.ts +17 -57
  353. package/dist/index.js +35 -96
  354. package/dist/next/routing/route-map.d.ts +42 -1
  355. package/dist/next/routing/route-map.js +45 -0
  356. package/dist/providers/db-firebase/base.repository.d.ts +22 -0
  357. package/dist/providers/db-firebase/base.repository.js +36 -0
  358. package/dist/schemas/registry.d.ts +15 -6
  359. package/dist/security/blind-index-tokens.d.ts +54 -0
  360. package/dist/security/blind-index-tokens.js +152 -0
  361. package/dist/security/index.d.ts +1 -1
  362. package/dist/security/index.js +1 -1
  363. package/dist/security/settings-encryption.d.ts +35 -0
  364. package/dist/security/settings-encryption.js +91 -0
  365. package/dist/seed/_helpers/brand-rows.js +38 -14
  366. package/dist/seed/_helpers/category-forest.js +73 -7
  367. package/dist/seed/_helpers/category-images-generated.d.ts +25 -6
  368. package/dist/seed/_helpers/category-images-generated.js +81 -6
  369. package/dist/seed/_helpers/category-models.d.ts +1 -1
  370. package/dist/seed/_helpers/category-models.js +7 -1
  371. package/dist/seed/_helpers/category-parts-glossary-map.js +8 -0
  372. package/dist/seed/_helpers/category-parts.d.ts +1 -1
  373. package/dist/seed/_helpers/category-parts.js +50 -2
  374. package/dist/seed/_helpers/character-features.d.ts +1 -1
  375. package/dist/seed/_helpers/character-features.js +2 -1
  376. package/dist/seed/_helpers/franchise-rows.js +10 -2
  377. package/dist/seed/_helpers/media.d.ts +47 -0
  378. package/dist/seed/_helpers/media.js +34 -0
  379. package/dist/seed/authenticity-knowledge-seed-data.d.ts +49 -5
  380. package/dist/seed/authenticity-knowledge-seed-data.js +10001 -549
  381. package/dist/seed/categories-seed-data.js +124 -20
  382. package/dist/seed/grouped-listings-seed-data.js +16 -0
  383. package/dist/seed/homepage-sections-seed-data.js +94 -5
  384. package/dist/seed/index.d.ts +2 -3
  385. package/dist/seed/index.js +2 -2
  386. package/dist/seed/manifest.js +3 -0
  387. package/dist/seed/media-assets-seed-data.d.ts +1 -1
  388. package/dist/seed/media-assets-seed-data.js +746 -196
  389. package/dist/seed/model-composition-seed-data.js +122 -6
  390. package/dist/seed/part-glossary-seed-data.d.ts +1 -1
  391. package/dist/seed/part-glossary-seed-data.js +37219 -463
  392. package/dist/seed/products-art-seed-data.js +7 -18
  393. package/dist/seed/products-auctions-seed-data.js +56 -47
  394. package/dist/seed/products-beyblade-x-seed-data.d.ts +2 -0
  395. package/dist/seed/products-beyblade-x-seed-data.js +476 -0
  396. package/dist/seed/products-catalogue-seed-data.d.ts +5 -5
  397. package/dist/seed/products-catalogue-seed-data.js +1500 -1240
  398. package/dist/seed/products-classifieds-seed-data.js +9 -27
  399. package/dist/seed/products-digital-codes-seed-data.js +9 -18
  400. package/dist/seed/products-live-items-seed-data.js +5 -13
  401. package/dist/seed/products-preorders-seed-data.js +67 -33
  402. package/dist/seed/products-prize-draws-seed-data.js +8 -17
  403. package/dist/seed/products-spares-seed-data.d.ts +2 -0
  404. package/dist/seed/products-spares-seed-data.js +368 -0
  405. package/dist/seed/products-standard-seed-data.js +39 -126
  406. package/dist/seed/products-stickers-seed-data.js +59 -15
  407. package/dist/seed/site-settings-seed-data.js +8 -0
  408. package/dist/seo/json-ld.d.ts +25 -0
  409. package/dist/seo/json-ld.js +28 -0
  410. package/dist/server-entry.d.ts +3 -1
  411. package/dist/server-entry.js +2 -2
  412. package/dist/server.d.ts +11 -9
  413. package/dist/server.js +35 -25
  414. package/dist/styles.css +202 -1
  415. package/dist/tailwind-input.css +31 -17
  416. package/dist/tailwind-utilities.css +1 -1
  417. package/dist/ui/components/Accordion.js +1 -1
  418. package/dist/ui/components/Breadcrumb.js +1 -1
  419. package/dist/ui/components/DetailPageGallery.js +0 -2
  420. package/dist/ui/components/DetailPageHero.js +0 -1
  421. package/dist/ui/components/DetailPageTabs.js +1 -1
  422. package/dist/ui/components/Divider.js +3 -3
  423. package/dist/ui/components/GatedPrice.js +5 -1
  424. package/dist/ui/components/HorizontalScroller.js +1 -1
  425. package/dist/ui/components/ListingLayout.js +3 -3
  426. package/dist/ui/components/MediaTabs.style.css +81 -0
  427. package/dist/ui/components/Pagination.js +1 -1
  428. package/dist/ui/components/PendingValue.d.ts +45 -0
  429. package/dist/ui/components/PendingValue.js +7 -0
  430. package/dist/ui/components/Radio.style.css +119 -0
  431. package/dist/ui/components/RatingDisplay.js +2 -2
  432. package/dist/ui/components/SettingsSection.js +0 -2
  433. package/dist/ui/components/SiteLogo.js +3 -0
  434. package/dist/ui/components/SiteMark.js +3 -0
  435. package/dist/ui/components/SortDropdown.js +1 -1
  436. package/dist/ui/components/SpecTable.d.ts +58 -0
  437. package/dist/ui/components/SpecTable.js +8 -0
  438. package/dist/ui/components/StarRating.js +1 -3
  439. package/dist/ui/components/SummaryCard.js +1 -1
  440. package/dist/ui/components/index.style.css +1 -0
  441. package/dist/ui/icons/icon-registry.d.ts +1 -0
  442. package/dist/ui/icons/icon-registry.js +9 -1
  443. package/dist/ui/index.d.ts +4 -0
  444. package/dist/ui/index.js +2 -0
  445. package/dist/utils/search-txt-query.d.ts +12 -0
  446. package/dist/utils/search-txt-query.js +12 -0
  447. package/package.json +1 -1
  448. package/scripts/dedupe-peer-deps.mjs +18 -0
  449. package/scripts/seed-cli.mjs +250 -35
  450. package/scripts/verify-css-build.mjs +118 -37
  451. package/dist/_internal/server/features/search/actions.d.ts +0 -7
  452. package/dist/_internal/server/features/search/actions.js +0 -21
  453. package/dist/_internal/server/features/search/data.d.ts +0 -15
  454. package/dist/_internal/server/features/search/data.js +0 -18
  455. package/dist/_internal/server/features/search/index.d.ts +0 -3
  456. package/dist/_internal/server/features/search/index.js +0 -2
  457. package/dist/features/homepage/api/[id]/route.d.ts +0 -23
  458. package/dist/features/homepage/api/[id]/route.js +0 -103
  459. package/dist/features/homepage/api/route.d.ts +0 -14
  460. package/dist/features/homepage/api/route.js +0 -140
  461. package/dist/features/homepage/api/sections/[id]/route.d.ts +0 -26
  462. package/dist/features/homepage/api/sections/[id]/route.js +0 -95
  463. package/dist/features/homepage/api/sections/route.d.ts +0 -13
  464. package/dist/features/homepage/api/sections/route.js +0 -82
  465. package/dist/features/homepage/components/AdvertisementBanner.d.ts +0 -14
  466. package/dist/features/homepage/components/AdvertisementBanner.js +0 -35
  467. package/dist/features/homepage/components/BeforeAfterCard.d.ts +0 -9
  468. package/dist/features/homepage/components/BeforeAfterCard.js +0 -73
  469. package/dist/features/homepage/components/FeaturedResultsSection.d.ts +0 -17
  470. package/dist/features/homepage/components/FeaturedResultsSection.js +0 -17
  471. package/dist/features/homepage/components/HeroBanner.d.ts +0 -7
  472. package/dist/features/homepage/components/HeroBanner.js +0 -43
  473. package/dist/features/homepage/components/HeroSection.d.ts +0 -7
  474. package/dist/features/homepage/components/HeroSection.js +0 -6
  475. package/dist/features/homepage/components/HomepageSkeleton.d.ts +0 -2
  476. package/dist/features/homepage/components/HomepageSkeleton.js +0 -21
  477. package/dist/features/homepage/components/HomepageView.d.ts +0 -25
  478. package/dist/features/homepage/components/HomepageView.js +0 -5
  479. package/dist/features/homepage/components/NewsletterBanner.d.ts +0 -23
  480. package/dist/features/homepage/components/NewsletterBanner.js +0 -37
  481. package/dist/features/homepage/components/SiteFeaturesSection.d.ts +0 -14
  482. package/dist/features/homepage/components/SiteFeaturesSection.js +0 -11
  483. package/dist/features/homepage/components/TrustBadges.d.ts +0 -6
  484. package/dist/features/homepage/components/TrustBadges.js +0 -46
  485. package/dist/features/homepage/components/TrustIndicatorsSection.d.ts +0 -12
  486. package/dist/features/homepage/components/TrustIndicatorsSection.js +0 -11
  487. package/dist/features/homepage/hooks/useHomepage.d.ts +0 -11
  488. package/dist/features/homepage/hooks/useHomepage.js +0 -17
  489. package/dist/features/homepage/hooks/useHomepageSections.d.ts +0 -2
  490. package/dist/features/homepage/hooks/useHomepageSections.js +0 -10
  491. package/dist/features/homepage/repository/homepage.repository.d.ts +0 -11
  492. package/dist/features/homepage/repository/homepage.repository.js +0 -25
  493. package/dist/features/search/actions/index.d.ts +0 -1
  494. package/dist/features/search/actions/index.js +0 -1
  495. package/dist/features/search/actions/search-actions.d.ts +0 -18
  496. package/dist/features/search/actions/search-actions.js +0 -43
  497. package/dist/features/search/api/route.d.ts +0 -22
  498. package/dist/features/search/api/route.js +0 -128
  499. package/dist/features/search/columns/index.d.ts +0 -17
  500. package/dist/features/search/columns/index.js +0 -49
  501. package/dist/features/search/components/SearchFiltersRow.d.ts +0 -22
  502. package/dist/features/search/components/SearchFiltersRow.js +0 -21
  503. package/dist/features/search/components/SearchResultsSection.d.ts +0 -53
  504. package/dist/features/search/components/SearchResultsSection.js +0 -35
  505. package/dist/features/search/components/SearchView.d.ts +0 -27
  506. package/dist/features/search/components/SearchView.js +0 -8
  507. package/dist/features/search/hooks/useSearch.d.ts +0 -21
  508. package/dist/features/search/hooks/useSearch.js +0 -33
  509. package/dist/features/search/repository/search.repository.d.ts +0 -14
  510. package/dist/features/search/repository/search.repository.js +0 -59
  511. package/dist/features/search/schemas/index.d.ts +0 -70
  512. package/dist/features/search/schemas/index.js +0 -36
  513. package/dist/features/search/types/index.d.ts +0 -48
  514. package/dist/features/stores/components/StoreScopedSearch.d.ts +0 -17
  515. package/dist/features/stores/components/StoreScopedSearch.js +0 -27
  516. package/dist/seed/defaults/homepage-sections.d.ts +0 -2
  517. package/dist/seed/defaults/homepage-sections.js +0 -60
  518. package/dist/seed/factories/homepage-section.factory.d.ts +0 -10
  519. package/dist/seed/factories/homepage-section.factory.js +0 -13
  520. /package/dist/{features/search/types/index.js → _internal/shared/listing-types/spares/og.d.ts} +0 -0
@@ -50,6 +50,7 @@ export declare const DEFAULT_ROUTE_MAP: {
50
50
  readonly STORE_DIGITAL_CODES: (storeSlug: string) => string;
51
51
  readonly STORE_LIVE: (storeSlug: string) => string;
52
52
  readonly STORE_ART: (storeSlug: string) => string;
53
+ readonly STORE_SPARES: (storeSlug: string) => string;
53
54
  readonly CATEGORIES: "/categories";
54
55
  readonly CATEGORY_DETAIL: (slug: string) => string;
55
56
  readonly BRANDS: "/brands";
@@ -78,6 +79,19 @@ export declare const DEFAULT_ROUTE_MAP: {
78
79
  readonly COOKIE_POLICY: "/cookies";
79
80
  readonly REFUND_POLICY: "/refund-policy";
80
81
  readonly SHIPPING_POLICY: "/shipping-policy";
82
+ /**
83
+ * Cancellation policy. Distinct from the refund policy, which already
84
+ * covers cancellation in passing — PhonePe's merchant review asks for it
85
+ * by name, and so does the Consumer Protection (E-Commerce) Rules 2020
86
+ * disclosure list.
87
+ */
88
+ readonly CANCELLATION_POLICY: "/cancellation-policy";
89
+ /**
90
+ * Grievance officer. A MANDATORY published disclosure under the Consumer
91
+ * Protection (E-Commerce) Rules 2020 and the IT Rules 2021 — name,
92
+ * designation, contact and a response commitment.
93
+ */
94
+ readonly GRIEVANCE: "/grievance";
81
95
  readonly HOW_AUCTIONS_WORK: "/how-auctions-work";
82
96
  readonly HOW_PRE_ORDERS_WORK: "/how-pre-orders-work";
83
97
  readonly HOW_OFFERS_WORK: "/how-offers-work";
@@ -124,6 +138,7 @@ export declare const DEFAULT_ROUTE_MAP: {
124
138
  readonly LIVE: "/live";
125
139
  readonly LIVE_DETAIL: (slug: string) => string;
126
140
  readonly ART: "/art";
141
+ readonly SPARES: "/spares";
127
142
  readonly CATALOGUE_ITEM_DETAIL: (ownerSlug: string, itemId: string) => string;
128
143
  };
129
144
  readonly ERRORS: {
@@ -246,6 +261,9 @@ export declare const DEFAULT_ROUTE_MAP: {
246
261
  readonly STICKERS: "/store/stickers";
247
262
  readonly STICKERS_NEW: "/store/stickers/new";
248
263
  readonly STICKERS_EDIT: (id: string) => string;
264
+ readonly SPARES: "/store/spares";
265
+ readonly SPARES_NEW: "/store/spares/new";
266
+ readonly SPARES_EDIT: (id: string) => string;
249
267
  readonly PRINT_CENTER: "/store/print-center";
250
268
  readonly FULFILLMENT: "/store/fulfillment";
251
269
  readonly PAYOUT_METHODS: "/store/payout-methods";
@@ -324,6 +342,7 @@ export declare const DEFAULT_ROUTE_MAP: {
324
342
  readonly LIVE: "/admin/live";
325
343
  readonly ART: "/admin/art";
326
344
  readonly STICKERS: "/admin/stickers";
345
+ readonly SPARES: "/admin/spares";
327
346
  readonly GROUPED_LISTINGS: "/admin/grouped-listings";
328
347
  readonly GROUPED_LISTINGS_NEW: "/admin/grouped-listings/new";
329
348
  readonly GROUPED_LISTINGS_EDIT: (id: string) => string;
@@ -466,6 +485,7 @@ export declare const ROUTES: {
466
485
  readonly STORE_DIGITAL_CODES: (storeSlug: string) => string;
467
486
  readonly STORE_LIVE: (storeSlug: string) => string;
468
487
  readonly STORE_ART: (storeSlug: string) => string;
488
+ readonly STORE_SPARES: (storeSlug: string) => string;
469
489
  readonly CATEGORIES: "/categories";
470
490
  readonly CATEGORY_DETAIL: (slug: string) => string;
471
491
  readonly BRANDS: "/brands";
@@ -494,6 +514,19 @@ export declare const ROUTES: {
494
514
  readonly COOKIE_POLICY: "/cookies";
495
515
  readonly REFUND_POLICY: "/refund-policy";
496
516
  readonly SHIPPING_POLICY: "/shipping-policy";
517
+ /**
518
+ * Cancellation policy. Distinct from the refund policy, which already
519
+ * covers cancellation in passing — PhonePe's merchant review asks for it
520
+ * by name, and so does the Consumer Protection (E-Commerce) Rules 2020
521
+ * disclosure list.
522
+ */
523
+ readonly CANCELLATION_POLICY: "/cancellation-policy";
524
+ /**
525
+ * Grievance officer. A MANDATORY published disclosure under the Consumer
526
+ * Protection (E-Commerce) Rules 2020 and the IT Rules 2021 — name,
527
+ * designation, contact and a response commitment.
528
+ */
529
+ readonly GRIEVANCE: "/grievance";
497
530
  readonly HOW_AUCTIONS_WORK: "/how-auctions-work";
498
531
  readonly HOW_PRE_ORDERS_WORK: "/how-pre-orders-work";
499
532
  readonly HOW_OFFERS_WORK: "/how-offers-work";
@@ -540,6 +573,7 @@ export declare const ROUTES: {
540
573
  readonly LIVE: "/live";
541
574
  readonly LIVE_DETAIL: (slug: string) => string;
542
575
  readonly ART: "/art";
576
+ readonly SPARES: "/spares";
543
577
  readonly CATALOGUE_ITEM_DETAIL: (ownerSlug: string, itemId: string) => string;
544
578
  };
545
579
  readonly ERRORS: {
@@ -662,6 +696,9 @@ export declare const ROUTES: {
662
696
  readonly STICKERS: "/store/stickers";
663
697
  readonly STICKERS_NEW: "/store/stickers/new";
664
698
  readonly STICKERS_EDIT: (id: string) => string;
699
+ readonly SPARES: "/store/spares";
700
+ readonly SPARES_NEW: "/store/spares/new";
701
+ readonly SPARES_EDIT: (id: string) => string;
665
702
  readonly PRINT_CENTER: "/store/print-center";
666
703
  readonly FULFILLMENT: "/store/fulfillment";
667
704
  readonly PAYOUT_METHODS: "/store/payout-methods";
@@ -740,6 +777,7 @@ export declare const ROUTES: {
740
777
  readonly LIVE: "/admin/live";
741
778
  readonly ART: "/admin/art";
742
779
  readonly STICKERS: "/admin/stickers";
780
+ readonly SPARES: "/admin/spares";
743
781
  readonly GROUPED_LISTINGS: "/admin/grouped-listings";
744
782
  readonly GROUPED_LISTINGS_NEW: "/admin/grouped-listings/new";
745
783
  readonly GROUPED_LISTINGS_EDIT: (id: string) => string;
@@ -903,6 +941,9 @@ export declare const SELLER_ROUTES: {
903
941
  readonly STICKERS: "/store/stickers";
904
942
  readonly STICKERS_NEW: "/store/stickers/new";
905
943
  readonly STICKERS_EDIT: (id: string) => string;
944
+ readonly SPARES: "/store/spares";
945
+ readonly SPARES_NEW: "/store/spares/new";
946
+ readonly SPARES_EDIT: (id: string) => string;
906
947
  readonly PRINT_CENTER: "/store/print-center";
907
948
  readonly FULFILLMENT: "/store/fulfillment";
908
949
  readonly PAYOUT_METHODS: "/store/payout-methods";
@@ -931,6 +972,6 @@ export declare const SELLER_ROUTES: {
931
972
  readonly GUIDE_SETTINGS: "/store/guide/settings";
932
973
  readonly GUIDE_WHATSAPP: "/store/guide/whatsapp";
933
974
  };
934
- export declare const PUBLIC_ROUTES: readonly ["/", string, string, string, string, string, string, string, string, string, string, string, string, string, string, string, string, string, "/unauthorized", "/auth/login", "/auth/register", "/auth/forgot-password", "/auth/reset-password", "/auth/verify-email"];
975
+ export declare const PUBLIC_ROUTES: readonly ["/", string, string, string, string, string, string, string, string, string, string, string, string, string, string, string, string, string, string, string, "/unauthorized", "/auth/login", "/auth/register", "/auth/forgot-password", "/auth/reset-password", "/auth/verify-email"];
935
976
  export declare const PROTECTED_ROUTES: readonly [string, string, string, string, string, string, string];
936
977
  export declare const AUTH_ROUTES: readonly ["/auth/login", "/auth/register"];
@@ -43,6 +43,13 @@ export const DEFAULT_ROUTE_MAP = {
43
43
  // `standard` — so the tab showed a real non-zero count and then landed on
44
44
  // a page containing none of those items.
45
45
  STORE_ART: (storeSlug) => `/stores/${storeSlug}/art`,
46
+ /*
47
+ * 🛑 `STORE_PAGE_TABS` is DERIVED from the plugin registry, so this tab
48
+ * appears the moment the plugin exists — and a missing
49
+ * `stores/[storeSlug]/spares/page.tsx` is then a clickable 404 that no
50
+ * audit covers. The folder lands in the same commit as this key.
51
+ */
52
+ STORE_SPARES: (storeSlug) => `/stores/${storeSlug}/spares`,
46
53
  CATEGORIES: "/categories",
47
54
  CATEGORY_DETAIL: (slug) => `/categories/${slug}`,
48
55
  BRANDS: "/brands",
@@ -86,6 +93,19 @@ export const DEFAULT_ROUTE_MAP = {
86
93
  COOKIE_POLICY: "/cookies",
87
94
  REFUND_POLICY: "/refund-policy",
88
95
  SHIPPING_POLICY: "/shipping-policy",
96
+ /**
97
+ * Cancellation policy. Distinct from the refund policy, which already
98
+ * covers cancellation in passing — PhonePe's merchant review asks for it
99
+ * by name, and so does the Consumer Protection (E-Commerce) Rules 2020
100
+ * disclosure list.
101
+ */
102
+ CANCELLATION_POLICY: "/cancellation-policy",
103
+ /**
104
+ * Grievance officer. A MANDATORY published disclosure under the Consumer
105
+ * Protection (E-Commerce) Rules 2020 and the IT Rules 2021 — name,
106
+ * designation, contact and a response commitment.
107
+ */
108
+ GRIEVANCE: "/grievance",
89
109
  HOW_AUCTIONS_WORK: "/how-auctions-work",
90
110
  HOW_PRE_ORDERS_WORK: "/how-pre-orders-work",
91
111
  HOW_OFFERS_WORK: "/how-offers-work",
@@ -188,6 +208,21 @@ export const DEFAULT_ROUTE_MAP = {
188
208
  // detail page stays PRODUCT_DETAIL (`/products/{slug}`), already wired in
189
209
  // `_internal/shared/listing-types/{art,stickers}/config.ts`.
190
210
  ART: "/art",
211
+ /*
212
+ * Part Two — loose components off disassembled items.
213
+ *
214
+ * 🛑 A REAL page, not a redirect shim like `/live`. Its plugin sets
215
+ * `inGeneralCatalogue: false`, and the rule for that flag is nav
216
+ * reachability: a type kept out of `/products` must own a page that
217
+ * `MAIN_NAV_ITEMS` links, or it is reachable from nowhere at all (Root
218
+ * Cause #61). A shim pointing back at `/products` would re-open exactly
219
+ * that hole while looking like it had closed it.
220
+ *
221
+ * Detail route stays `PRODUCT_DETAIL` — a spare checks out like any
222
+ * standard item, so it needs no bespoke detail page, same reasoning as
223
+ * art/stickers above.
224
+ */
225
+ SPARES: "/spares",
191
226
  // Personal catalogue (Feature B) — a user's own photo inventory of owned
192
227
  // items, distinct from marketplace listings. Public when the owner sets
193
228
  // an item's visibility to "public". The owner's full catalogue listing
@@ -319,6 +354,10 @@ export const DEFAULT_ROUTE_MAP = {
319
354
  STICKERS: "/store/stickers",
320
355
  STICKERS_NEW: "/store/stickers/new",
321
356
  STICKERS_EDIT: (id) => `/store/stickers/${id}/edit`,
357
+ // Part Two — spares
358
+ SPARES: "/store/spares",
359
+ SPARES_NEW: "/store/spares/new",
360
+ SPARES_EDIT: (id) => `/store/spares/${id}/edit`,
322
361
  PRINT_CENTER: "/store/print-center",
323
362
  FULFILLMENT: "/store/fulfillment",
324
363
  // S-STORE Tier — new extension routes
@@ -412,6 +451,8 @@ export const DEFAULT_ROUTE_MAP = {
412
451
  // EMI/art-stickers session — art / stickers
413
452
  ART: "/admin/art",
414
453
  STICKERS: "/admin/stickers",
454
+ // Part Two — spares
455
+ SPARES: "/admin/spares",
415
456
  GROUPED_LISTINGS: "/admin/grouped-listings",
416
457
  GROUPED_LISTINGS_NEW: "/admin/grouped-listings/new",
417
458
  GROUPED_LISTINGS_EDIT: (id) => `/admin/grouped-listings/${id}/edit`,
@@ -580,6 +621,10 @@ export const PUBLIC_ROUTES = [
580
621
  ROUTES.PUBLIC.PRIVACY,
581
622
  ROUTES.PUBLIC.ETHICS,
582
623
  ROUTES.PUBLIC.CODE_OF_CONDUCT,
624
+ ROUTES.PUBLIC.CANCELLATION_POLICY,
625
+ // Public by necessity: a grievance officer a complainant must sign in to
626
+ // find is not a published disclosure.
627
+ ROUTES.PUBLIC.GRIEVANCE,
583
628
  ROUTES.ERRORS.UNAUTHORIZED,
584
629
  ROUTES.AUTH.LOGIN,
585
630
  ROUTES.AUTH.REGISTER,
@@ -49,6 +49,28 @@ export declare abstract class BaseRepository<T extends DocumentData> {
49
49
  * text, so indexing an encrypted field would undo the encryption.
50
50
  */
51
51
  protected buildSearchTxtFor(_data: Record<string, JsonValue>): string[] | null;
52
+ /**
53
+ * Build this document's `*TokensIndex` fields — whole-word HMAC digests
54
+ * over PII, for admin search without decryption. Return `null` to leave
55
+ * the document alone (the default).
56
+ *
57
+ * Mirrors `buildSearchTxtFor`'s shape exactly, and for the reason that
58
+ * shape exists: a hook run from `applyWriteHooks` reaches EVERY write path
59
+ * — create, createWithId, update, the `*InTx`/`*InBatch` family, and a
60
+ * seed load, which goes through the same repository methods. A one-off
61
+ * backfill script cannot reach any of those; it only catches documents
62
+ * that already existed when it ran.
63
+ *
64
+ * 🛑 This is NOT `buildSearchTxtFor`'s inverse rule. `searchTxt` must never
65
+ * carry PII; this hook exists FOR PII, and runs in the only place that
66
+ * sees the plaintext before `encryptPiiFields` replaces it. See
67
+ * `security/blind-index-tokens.ts` for why the tokens are whole-word only.
68
+ *
69
+ * Return shape is `{ fieldName: digests[] }` rather than a single array,
70
+ * because a document can carry more than one token field (a payout has
71
+ * `sellerTokensIndex`, nothing else does yet, but the hook is general).
72
+ */
73
+ protected buildTokensIndexFor(_data: Record<string, JsonValue>): Record<string, string[]> | null;
52
74
  /**
53
75
  * The one place writes are transformed. Every write path routes through here
54
76
  * so a new method cannot silently skip encryption.
@@ -5,6 +5,7 @@ import { applySieveToFirestore, countSieveMatches, } from "./sieve.js";
5
5
  import { deserializeTimestamps, prepareForFirestore } from "./helpers.js";
6
6
  import { getAdminDb } from "./admin.js";
7
7
  import { encryptPiiFields, piiIndicesFor } from "../../security/pii-encrypt.js";
8
+ import { BLIND_INDEX_KEY_VERSION_FIELD, CURRENT_BLIND_INDEX_KEY_VERSION, } from "../../security/blind-index-tokens.js";
8
9
  /**
9
10
  * The underlying failure's message, for interpolation into a DatabaseError.
10
11
  *
@@ -133,6 +134,30 @@ export class BaseRepository {
133
134
  buildSearchTxtFor(_data) {
134
135
  return null;
135
136
  }
137
+ /**
138
+ * Build this document's `*TokensIndex` fields — whole-word HMAC digests
139
+ * over PII, for admin search without decryption. Return `null` to leave
140
+ * the document alone (the default).
141
+ *
142
+ * Mirrors `buildSearchTxtFor`'s shape exactly, and for the reason that
143
+ * shape exists: a hook run from `applyWriteHooks` reaches EVERY write path
144
+ * — create, createWithId, update, the `*InTx`/`*InBatch` family, and a
145
+ * seed load, which goes through the same repository methods. A one-off
146
+ * backfill script cannot reach any of those; it only catches documents
147
+ * that already existed when it ran.
148
+ *
149
+ * 🛑 This is NOT `buildSearchTxtFor`'s inverse rule. `searchTxt` must never
150
+ * carry PII; this hook exists FOR PII, and runs in the only place that
151
+ * sees the plaintext before `encryptPiiFields` replaces it. See
152
+ * `security/blind-index-tokens.ts` for why the tokens are whole-word only.
153
+ *
154
+ * Return shape is `{ fieldName: digests[] }` rather than a single array,
155
+ * because a document can carry more than one token field (a payout has
156
+ * `sellerTokensIndex`, nothing else does yet, but the hook is general).
157
+ */
158
+ buildTokensIndexFor(_data) {
159
+ return null;
160
+ }
136
161
  /**
137
162
  * The one place writes are transformed. Every write path routes through here
138
163
  * so a new method cannot silently skip encryption.
@@ -154,6 +179,17 @@ export class BaseRepository {
154
179
  const searchTxt = this.buildSearchTxtFor(out);
155
180
  if (searchTxt)
156
181
  out.searchTxt = searchTxt;
182
+ /*
183
+ * `data`, not `out` — the plaintext source, same as `piiIndicesFor`
184
+ * above. By this point `out` may already hold ciphertext, and hashing
185
+ * ciphertext would make the index meaningless.
186
+ */
187
+ const tokensIndex = this.buildTokensIndexFor(data);
188
+ if (tokensIndex) {
189
+ Object.assign(out, tokensIndex, {
190
+ [BLIND_INDEX_KEY_VERSION_FIELD]: CURRENT_BLIND_INDEX_KEY_VERSION,
191
+ });
192
+ }
157
193
  return out;
158
194
  }
159
195
  /**
@@ -1011,6 +1011,8 @@ export declare const SCHEMAS: {
1011
1011
  brandWebsite: import("zod").ZodOptional<import("zod").ZodString>;
1012
1012
  brandCountry: import("zod").ZodOptional<import("zod").ZodString>;
1013
1013
  brandFounded: import("zod").ZodOptional<import("zod").ZodNumber>;
1014
+ hasbroName: import("zod").ZodOptional<import("zod").ZodString>;
1015
+ hasbroCoverImage: import("zod").ZodOptional<import("zod").ZodString>;
1014
1016
  highlights: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString, "many">>;
1015
1017
  faqs: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodObject<{
1016
1018
  question: import("zod").ZodString;
@@ -1604,6 +1606,8 @@ export declare const SCHEMAS: {
1604
1606
  brandWebsite?: string | undefined;
1605
1607
  brandCountry?: string | undefined;
1606
1608
  brandFounded?: number | undefined;
1609
+ hasbroName?: string | undefined;
1610
+ hasbroCoverImage?: string | undefined;
1607
1611
  highlights?: string[] | undefined;
1608
1612
  contentBody?: string | undefined;
1609
1613
  descriptionTemplates?: {
@@ -1775,6 +1779,8 @@ export declare const SCHEMAS: {
1775
1779
  brandWebsite?: string | undefined;
1776
1780
  brandCountry?: string | undefined;
1777
1781
  brandFounded?: number | undefined;
1782
+ hasbroName?: string | undefined;
1783
+ hasbroCoverImage?: string | undefined;
1778
1784
  highlights?: string[] | undefined;
1779
1785
  contentBody?: string | undefined;
1780
1786
  descriptionTemplates?: {
@@ -2605,12 +2611,12 @@ export declare const SCHEMAS: {
2605
2611
  toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
2606
2612
  }, import("zod").ZodTypeAny, "passthrough">>]>;
2607
2613
  id: import("zod").ZodString;
2608
- type: import("zod").ZodEnum<["welcome", "carousel", "stats", "trust-indicators", "categories", "brands", "products", "pre-orders", "auctions", "banner", "features", "reviews", "whatsapp-community", "faq", "blog-articles", "newsletter", "stores", "events", "social-feed", "custom-cards", "google-reviews", "featured-bundles", "prize-draws", "event-raffles", "collection-cards"]>;
2614
+ type: import("zod").ZodEnum<[import("..").SectionType, ...import("..").SectionType[]]>;
2609
2615
  order: import("zod").ZodNumber;
2610
2616
  enabled: import("zod").ZodBoolean;
2611
2617
  config: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodType<import("./types").JsonValue, import("zod").ZodTypeDef, import("./types").JsonValue>>;
2612
2618
  }, "strip", import("zod").ZodTypeAny, {
2613
- type: "banner" | "stores" | "products" | "pre-orders" | "prize-draws" | "auctions" | "reviews" | "events" | "categories" | "brands" | "carousel" | "newsletter" | "features" | "stats" | "welcome" | "trust-indicators" | "whatsapp-community" | "faq" | "blog-articles" | "social-feed" | "custom-cards" | "google-reviews" | "featured-bundles" | "event-raffles" | "collection-cards";
2619
+ type: import("..").SectionType;
2614
2620
  id: string;
2615
2621
  createdAt: string | Date | import("zod").objectOutputType<{
2616
2622
  toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
@@ -2622,7 +2628,7 @@ export declare const SCHEMAS: {
2622
2628
  order: number;
2623
2629
  config: Record<string, import("./types").JsonValue>;
2624
2630
  }, {
2625
- type: "banner" | "stores" | "products" | "pre-orders" | "prize-draws" | "auctions" | "reviews" | "events" | "categories" | "brands" | "carousel" | "newsletter" | "features" | "stats" | "welcome" | "trust-indicators" | "whatsapp-community" | "faq" | "blog-articles" | "social-feed" | "custom-cards" | "google-reviews" | "featured-bundles" | "event-raffles" | "collection-cards";
2631
+ type: import("..").SectionType;
2626
2632
  id: string;
2627
2633
  createdAt: string | Date | import("zod").objectInputType<{
2628
2634
  toDate: import("zod").ZodFunction<import("zod").ZodTuple<[], import("zod").ZodUnknown>, import("zod").ZodDate>;
@@ -5501,18 +5507,21 @@ export declare const SCHEMAS: {
5501
5507
  audienceUserIds?: string[] | undefined;
5502
5508
  }>;
5503
5509
  readonly homepageSection: import("zod").ZodObject<{
5504
- type: import("zod").ZodEnum<["welcome", "carousel", "stats", "trust-indicators", "categories", "brands", "products", "pre-orders", "auctions", "banner", "features", "reviews", "whatsapp-community", "faq", "blog-articles", "newsletter", "stores", "events", "social-feed", "custom-cards", "google-reviews", "featured-bundles", "prize-draws", "event-raffles", "collection-cards"]>;
5510
+ type: import("zod").ZodEnum<[import("..").SectionType, ...import("..").SectionType[]]>;
5505
5511
  enabled: import("zod").ZodDefault<import("zod").ZodOptional<import("zod").ZodBoolean>>;
5506
5512
  order: import("zod").ZodOptional<import("zod").ZodNumber>;
5513
+ surface: import("zod").ZodOptional<import("zod").ZodEnum<["homepage", "category", "brand", "product", "store"]>>;
5507
5514
  config: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodType<import("./types").JsonValue, import("zod").ZodTypeDef, import("./types").JsonValue>>;
5508
5515
  }, "strip", import("zod").ZodTypeAny, {
5509
- type: "banner" | "stores" | "products" | "pre-orders" | "prize-draws" | "auctions" | "reviews" | "events" | "categories" | "brands" | "carousel" | "newsletter" | "features" | "stats" | "welcome" | "trust-indicators" | "whatsapp-community" | "faq" | "blog-articles" | "social-feed" | "custom-cards" | "google-reviews" | "featured-bundles" | "event-raffles" | "collection-cards";
5516
+ type: import("..").SectionType;
5510
5517
  enabled: boolean;
5511
5518
  config: Record<string, import("./types").JsonValue>;
5519
+ surface?: "brand" | "category" | "store" | "product" | "homepage" | undefined;
5512
5520
  order?: number | undefined;
5513
5521
  }, {
5514
- type: "banner" | "stores" | "products" | "pre-orders" | "prize-draws" | "auctions" | "reviews" | "events" | "categories" | "brands" | "carousel" | "newsletter" | "features" | "stats" | "welcome" | "trust-indicators" | "whatsapp-community" | "faq" | "blog-articles" | "social-feed" | "custom-cards" | "google-reviews" | "featured-bundles" | "event-raffles" | "collection-cards";
5522
+ type: import("..").SectionType;
5515
5523
  config: Record<string, import("./types").JsonValue>;
5524
+ surface?: "brand" | "category" | "store" | "product" | "homepage" | undefined;
5516
5525
  enabled?: boolean | undefined;
5517
5526
  order?: number | undefined;
5518
5527
  }>;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * The shortest token worth indexing.
3
+ *
4
+ * 🛑 Three, matching the frequency argument in the header. Two-character
5
+ * tokens are both uninformative as a search ("find everyone with 'li' in
6
+ * their name") and the regime where counting starts to work.
7
+ */
8
+ export declare const BLIND_INDEX_MIN_TOKEN = 3;
9
+ /** Tokens per field. A bound, so one pathological value cannot bloat a document. */
10
+ export declare const BLIND_INDEX_MAX_TOKENS = 24;
11
+ /** Split a value into whole, normalised, long-enough words. */
12
+ export declare function tokensOf(value: string): string[];
13
+ /**
14
+ * Build a `*TokensIndex` from one or more plaintext values.
15
+ *
16
+ * Returns `[]` rather than undefined for an empty input, so the field is
17
+ * always present and `array-contains` behaves predictably. An ABSENT array
18
+ * field and an empty one are the same to `array-contains`, but they are not
19
+ * the same to a human reading the document and wondering whether the
20
+ * backfill ran.
21
+ */
22
+ export declare function buildTokensIndex(...values: readonly (string | null | undefined)[]): string[];
23
+ /**
24
+ * The digest to pass to `array-contains` for one search term.
25
+ *
26
+ * Returns null when the term is too short to have been indexed — the caller
27
+ * must then return NOTHING rather than fall back to an unfiltered query.
28
+ * A two-character admin search that quietly listed every user would be the
29
+ * `plan.empty` bug (a query that normalises away matching everything) on
30
+ * the one surface where the result set is people.
31
+ */
32
+ export declare function tokensIndexQueryValue(term: string): string | null;
33
+ /**
34
+ * Which key version wrote a given index.
35
+ *
36
+ * 🛑 Rotating `PII_HMAC_KEY` invalidates every digest written before it, and
37
+ * the failure is silent: searches simply stop matching, which reads as "no
38
+ * such user" rather than as a broken index. Recording the version means a
39
+ * backfill can tell what it still has to rewrite instead of rewriting
40
+ * everything, and a mismatch is detectable rather than invisible.
41
+ */
42
+ export declare const BLIND_INDEX_KEY_VERSION_FIELD = "blindIndexKeyVersion";
43
+ /**
44
+ * The version every NEW write stamps. Bump by hand when `PII_HMAC_KEY`
45
+ * rotates — never computed, because a value derived from the key itself
46
+ * would be constant across every rotation and the whole point is to tell
47
+ * two rotations apart.
48
+ *
49
+ * Read from `PII_HMAC_KEY_VERSION` so the repository write path (which runs
50
+ * inside the Next.js/Functions runtime) and `backfill-blind-index.mjs`
51
+ * (which runs as a standalone script before `appkit/dist` is necessarily
52
+ * current) agree without importing from each other.
53
+ */
54
+ export declare const CURRENT_BLIND_INDEX_KEY_VERSION: number;
@@ -0,0 +1,152 @@
1
+ /*
2
+ * WHY: An admin needs to find a person by name without anything on the
3
+ * server being able to read that name, and without the index itself
4
+ * becoming the leak.
5
+ * WHAT: `*TokensIndex` — a whole-word HMAC token array, and the ONE
6
+ * normaliser both sides must use.
7
+ *
8
+ * ## 🛑 WHOLE WORDS ONLY, 3 characters minimum. This is the security
9
+ * boundary, not a tuning preference.
10
+ *
11
+ * The edge-n-gram expansion that makes `searchTxt` good is exactly what
12
+ * would make a blind index leak. An attacker with read access cannot
13
+ * compute HMACs without the key — but they can COUNT them. A 1-character
14
+ * prefix has 36 possible hashes and a 2-character one roughly 1,300, so the
15
+ * most frequent hash in the column is `a`, the second is `e`, and the
16
+ * distribution unpicks from there by ordinary frequency analysis. Whole
17
+ * tokens keep the space uninteresting, and "type a full first or last name"
18
+ * is what admin people-search actually needs.
19
+ *
20
+ * So: never call `buildSearchTxt` to build one of these, never add a prefix
21
+ * loop, and never derive one field from the other. `audit-blind-index-tokens`
22
+ * R1 blocks all three.
23
+ *
24
+ * ## 🛑 `hmacBlindIndex` does NOT normalise — it hashes the raw string
25
+ *
26
+ * `Mohasin` and `mohasin` therefore produce different digests. Both sides
27
+ * must run the same normaliser BEFORE hashing, and if they ever diverge a
28
+ * backfill does not fix it: you must first discover the divergence, and the
29
+ * symptom is "search returns nothing", which reads as "no such user".
30
+ *
31
+ * That is why `buildTokensIndex` and `tokensIndexQueryValue` live in one
32
+ * file and share `normaliseToken` — the write side and the query side
33
+ * cannot be edited independently.
34
+ *
35
+ * ## Why this is a DIFFERENT field from `searchTxt`, not an extension
36
+ *
37
+ * Different properties, deliberately: hashed not plaintext, whole-word not
38
+ * prefix-expanded, admin-only not public. `searchTxt` still never carries
39
+ * PII, and that rule is untouched. Keeping them visibly distinct is what
40
+ * stops someone "simplifying" one into the other.
41
+ *
42
+ * @tag domain:security
43
+ * @tag layer:shared
44
+ * @tag pattern:none
45
+ * @tag access:server
46
+ * @tag consumers:UserRepository,PayoutRepository,AddressesRepository,backfill-blind-index
47
+ * @tag sideEffects:none
48
+ */
49
+ import { hmacBlindIndex } from "./pii-encrypt.js";
50
+ /**
51
+ * The shortest token worth indexing.
52
+ *
53
+ * 🛑 Three, matching the frequency argument in the header. Two-character
54
+ * tokens are both uninformative as a search ("find everyone with 'li' in
55
+ * their name") and the regime where counting starts to work.
56
+ */
57
+ export const BLIND_INDEX_MIN_TOKEN = 3;
58
+ /** Tokens per field. A bound, so one pathological value cannot bloat a document. */
59
+ export const BLIND_INDEX_MAX_TOKENS = 24;
60
+ /**
61
+ * The ONE normaliser for this path.
62
+ *
63
+ * Deliberately NOT `normalizeSearchText`: that one exists to make the
64
+ * public write path and the Firestore token query agree, and it is tuned
65
+ * for product titles. Reusing it here would couple two schemes that must be
66
+ * able to change independently — and a change made for search reasons would
67
+ * silently invalidate every stored digest.
68
+ *
69
+ * Lower-case, strip diacritics, drop everything that is not a letter or a
70
+ * digit. An email is split on its punctuation too, so `mohsin0502@gmail.com`
71
+ * yields `mohsin0502`, `gmail`, `com` — the local part being the useful one.
72
+ */
73
+ function normaliseToken(raw) {
74
+ return raw
75
+ .normalize("NFD")
76
+ .replace(/[̀-ͯ]/g, "")
77
+ .toLowerCase()
78
+ .replace(/[^a-z0-9]/g, "");
79
+ }
80
+ /** Split a value into whole, normalised, long-enough words. */
81
+ export function tokensOf(value) {
82
+ const out = [];
83
+ const seen = new Set();
84
+ for (const part of value.split(/[\s.@_\-+/\\,;:()[\]]+/)) {
85
+ const t = normaliseToken(part);
86
+ if (t.length < BLIND_INDEX_MIN_TOKEN)
87
+ continue;
88
+ if (seen.has(t))
89
+ continue;
90
+ seen.add(t);
91
+ out.push(t);
92
+ if (out.length >= BLIND_INDEX_MAX_TOKENS)
93
+ break;
94
+ }
95
+ return out;
96
+ }
97
+ /**
98
+ * Build a `*TokensIndex` from one or more plaintext values.
99
+ *
100
+ * Returns `[]` rather than undefined for an empty input, so the field is
101
+ * always present and `array-contains` behaves predictably. An ABSENT array
102
+ * field and an empty one are the same to `array-contains`, but they are not
103
+ * the same to a human reading the document and wondering whether the
104
+ * backfill ran.
105
+ */
106
+ export function buildTokensIndex(...values) {
107
+ const tokens = new Set();
108
+ for (const v of values) {
109
+ if (!v)
110
+ continue;
111
+ for (const t of tokensOf(v))
112
+ tokens.add(t);
113
+ }
114
+ return [...tokens].slice(0, BLIND_INDEX_MAX_TOKENS).map((t) => hmacBlindIndex(t));
115
+ }
116
+ /**
117
+ * The digest to pass to `array-contains` for one search term.
118
+ *
119
+ * Returns null when the term is too short to have been indexed — the caller
120
+ * must then return NOTHING rather than fall back to an unfiltered query.
121
+ * A two-character admin search that quietly listed every user would be the
122
+ * `plan.empty` bug (a query that normalises away matching everything) on
123
+ * the one surface where the result set is people.
124
+ */
125
+ export function tokensIndexQueryValue(term) {
126
+ const t = normaliseToken(term);
127
+ if (t.length < BLIND_INDEX_MIN_TOKEN)
128
+ return null;
129
+ return hmacBlindIndex(t);
130
+ }
131
+ /**
132
+ * Which key version wrote a given index.
133
+ *
134
+ * 🛑 Rotating `PII_HMAC_KEY` invalidates every digest written before it, and
135
+ * the failure is silent: searches simply stop matching, which reads as "no
136
+ * such user" rather than as a broken index. Recording the version means a
137
+ * backfill can tell what it still has to rewrite instead of rewriting
138
+ * everything, and a mismatch is detectable rather than invisible.
139
+ */
140
+ export const BLIND_INDEX_KEY_VERSION_FIELD = "blindIndexKeyVersion";
141
+ /**
142
+ * The version every NEW write stamps. Bump by hand when `PII_HMAC_KEY`
143
+ * rotates — never computed, because a value derived from the key itself
144
+ * would be constant across every rotation and the whole point is to tell
145
+ * two rotations apart.
146
+ *
147
+ * Read from `PII_HMAC_KEY_VERSION` so the repository write path (which runs
148
+ * inside the Next.js/Functions runtime) and `backfill-blind-index.mjs`
149
+ * (which runs as a standalone script before `appkit/dist` is necessarily
150
+ * current) agree without importing from each other.
151
+ */
152
+ export const CURRENT_BLIND_INDEX_KEY_VERSION = Number((typeof process !== "undefined" ? process.env?.PII_HMAC_KEY_VERSION : undefined) ?? "1");
@@ -10,4 +10,4 @@ export { encryptValue, decryptValue, hmacBlindIndex, encryptPiiFields, decryptPi
10
10
  export { revealPii, maskPii, revealPiiAll, maskPiiAll } from "./pii-accessors";
11
11
  export { isPiiEncrypted, maskName, maskEmail, maskPhone, maskPublicReview, maskPublicBid, maskPublicEventEntry, maskOfferForSeller, ENC_PREFIX, HMAC_PREFIX, } from "./pii-mask";
12
12
  export { USER_PII_FIELDS, USER_PII_INDEX_MAP, ADDRESS_PII_FIELDS, ORDER_PII_FIELDS, PAYOUT_PII_FIELDS, PAYOUT_PII_INDEX_MAP, BID_PII_FIELDS, TOKEN_PII_FIELDS, TOKEN_PII_INDEX_MAP, REVIEW_PII_FIELDS, REVIEW_PII_INDEX_MAP, OFFER_PII_FIELDS, EVENT_ENTRY_PII_FIELDS, LOTTERY_ENTRY_PII_FIELDS, PAYMENT_METHOD_PII_FIELDS, CONVERSATION_PII_FIELDS, MESSAGE_PII_FIELDS, } from "./pii-schemas";
13
- export { encryptSecret, decryptSecret, isSecretEncrypted, maskSecret, } from "./settings-encryption";
13
+ export { encryptSecret, decryptSecret, isSecretEncrypted, maskSecret, encryptBuffer, decryptBuffer, isBufferEncrypted, } from "./settings-encryption";
@@ -22,7 +22,7 @@ export { revealPii, maskPii, revealPiiAll, maskPiiAll } from "./pii-accessors.js
22
22
  // universal client+server index.ts. See pii-mask.ts's header comment.
23
23
  export { isPiiEncrypted, maskName, maskEmail, maskPhone, maskPublicReview, maskPublicBid, maskPublicEventEntry, maskOfferForSeller, ENC_PREFIX, HMAC_PREFIX, } from "./pii-mask.js";
24
24
  export { USER_PII_FIELDS, USER_PII_INDEX_MAP, ADDRESS_PII_FIELDS, ORDER_PII_FIELDS, PAYOUT_PII_FIELDS, PAYOUT_PII_INDEX_MAP, BID_PII_FIELDS, TOKEN_PII_FIELDS, TOKEN_PII_INDEX_MAP, REVIEW_PII_FIELDS, REVIEW_PII_INDEX_MAP, OFFER_PII_FIELDS, EVENT_ENTRY_PII_FIELDS, LOTTERY_ENTRY_PII_FIELDS, PAYMENT_METHOD_PII_FIELDS, CONVERSATION_PII_FIELDS, MESSAGE_PII_FIELDS, } from "./pii-schemas.js";
25
- export { encryptSecret, decryptSecret, isSecretEncrypted, maskSecret, } from "./settings-encryption.js";
25
+ export { encryptSecret, decryptSecret, isSecretEncrypted, maskSecret, encryptBuffer, decryptBuffer, isBufferEncrypted, } from "./settings-encryption.js";
26
26
  // RBAC system — DELETED 2026-08-29.
27
27
  //
28
28
  // `security/rbac/**` was a complete second permission system: DEFAULT_ROLES,
@@ -1,4 +1,39 @@
1
1
  export declare function encryptSecret(plaintext: string): string;
2
2
  export declare function decryptSecret(encrypted: string): string;
3
3
  export declare function isSecretEncrypted(value: string): boolean;
4
+ /**
5
+ * AES-256-GCM a file's bytes under `SETTINGS_ENCRYPTION_KEY`.
6
+ *
7
+ * Throws when the key is unset — deliberately, and identically to
8
+ * `encryptSecret`. A document store that silently writes plaintext when
9
+ * misconfigured is worse than one that refuses, because nothing downstream can
10
+ * tell the two apart afterwards.
11
+ */
12
+ export declare function encryptBuffer(plaintext: Buffer): Buffer;
13
+ /**
14
+ * Reverse `encryptBuffer`.
15
+ *
16
+ * 🛑 Unlike `decryptSecret`, a buffer with no `enc:v1:` prefix is REJECTED
17
+ * rather than passed through. That asymmetry is intentional. `decryptSecret`
18
+ * tolerates plaintext because the settings collection genuinely holds
19
+ * unencrypted placeholders that predate encryption, so passing them through is
20
+ * the migration path. Here there is no such legacy: every object this reads was
21
+ * written by `encryptBuffer`, so an unprefixed buffer means the wrong object,
22
+ * a truncated download, or an upload that bypassed encryption — and returning
23
+ * it verbatim would serve one of those to an admin as though it were fine.
24
+ *
25
+ * GCM authentication also means `final()` throws on any tampering or on the
26
+ * wrong key, so a corrupted object fails loudly instead of yielding garbage.
27
+ */
28
+ export declare function decryptBuffer(encrypted: Buffer): Buffer;
29
+ /**
30
+ * True when `buf` carries the binary envelope AND is long enough to hold a
31
+ * complete one.
32
+ *
33
+ * The length check is not pedantry: without it a 7-byte buffer containing only
34
+ * the prefix passes, and `decryptBuffer` then hands `createDecipheriv` a
35
+ * zero-length IV, which throws `Invalid initialization vector` — an error that
36
+ * describes the crypto call rather than the truncated download that caused it.
37
+ */
38
+ export declare function isBufferEncrypted(buf: Buffer): boolean;
4
39
  export declare function maskSecret(value: string): string;