@mohasinac/appkit 4.53.1 → 4.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (384) hide show
  1. package/dist/.build-stamp.json +3 -3
  2. package/dist/_internal/client/theme/ThemeProvider.js +15 -1
  3. package/dist/_internal/server/features/auth/capabilities.js +7 -5
  4. package/dist/_internal/server/features/categories/price-guidance-resolve.d.ts +66 -0
  5. package/dist/_internal/server/features/categories/price-guidance-resolve.js +138 -0
  6. package/dist/_internal/server/features/checkout/actions.d.ts +22 -6
  7. package/dist/_internal/server/features/checkout/actions.js +96 -51
  8. package/dist/_internal/server/features/checkout/index.d.ts +1 -1
  9. package/dist/_internal/server/features/checkout/index.js +1 -1
  10. package/dist/_internal/server/features/checkout/supplier-identity.js +28 -6
  11. package/dist/_internal/server/features/orders/adapters.js +1 -3
  12. package/dist/_internal/server/features/price-index/market.d.ts +57 -0
  13. package/dist/_internal/server/features/price-index/market.js +120 -0
  14. package/dist/_internal/server/features/products/list-public.d.ts +12 -0
  15. package/dist/_internal/server/features/products/list-public.js +10 -1
  16. package/dist/_internal/server/features/products/listing-tab-counts.d.ts +25 -1
  17. package/dist/_internal/server/features/products/listing-tab-counts.js +184 -10
  18. package/dist/_internal/server/features/search/index-build/sources.js +43 -2
  19. package/dist/_internal/server/features/site-settings/adapters.js +1 -1
  20. package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
  21. package/dist/_internal/server/features/stores/adapters.js +0 -1
  22. package/dist/_internal/server/features/stores/tabs.d.ts +7 -2
  23. package/dist/_internal/server/features/stores/tabs.js +5 -3
  24. package/dist/_internal/server/jobs/core/analyticsAlertEvaluate.js +2 -5
  25. package/dist/_internal/server/jobs/core/jobRunners.js +0 -10
  26. package/dist/_internal/server/jobs/core/onOrderCreate.js +10 -104
  27. package/dist/_internal/server/jobs/core/onOrderStatusChange.d.ts +0 -2
  28. package/dist/_internal/server/jobs/core/onOrderStatusChange.js +0 -1
  29. package/dist/_internal/server/jobs/core/onScamReportCreate.js +0 -1
  30. package/dist/_internal/server/jobs/core/onScamReportRejected.js +0 -1
  31. package/dist/_internal/server/jobs/core/onScamReportVerified.js +0 -1
  32. package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +0 -1
  33. package/dist/_internal/server/jobs/core/pendingOrderTimeout.js +0 -1
  34. package/dist/_internal/server/notifications/channel-health.d.ts +7 -3
  35. package/dist/_internal/server/notifications/channel-health.js +2 -2
  36. package/dist/_internal/server/notifications/send-guard.d.ts +1 -1
  37. package/dist/_internal/server/notifications/send-guard.js +2 -4
  38. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  39. package/dist/_internal/shared/actions/action-registry.js +128 -28
  40. package/dist/_internal/shared/checkout/order-math.d.ts +1 -1
  41. package/dist/_internal/shared/checkout/order-math.js +1 -1
  42. package/dist/_internal/shared/features/categories/bundle-copy.d.ts +1 -1
  43. package/dist/_internal/shared/features/checkout/config.d.ts +0 -2
  44. package/dist/_internal/shared/features/checkout/config.js +0 -2
  45. package/dist/_internal/shared/features/messaging/config.d.ts +7 -5
  46. package/dist/_internal/shared/features/messaging/config.js +1 -4
  47. package/dist/_internal/shared/features/site-settings/fees.d.ts +0 -2
  48. package/dist/_internal/shared/features/site-settings/fees.js +0 -2
  49. package/dist/_internal/shared/features/site-settings/supplier-of-record.d.ts +56 -0
  50. package/dist/_internal/shared/features/site-settings/supplier-of-record.js +57 -0
  51. package/dist/_internal/shared/fees/calculator.d.ts +0 -8
  52. package/dist/_internal/shared/fees/calculator.js +0 -7
  53. package/dist/_internal/shared/listing-types/tiers.d.ts +94 -0
  54. package/dist/_internal/shared/listing-types/tiers.js +150 -0
  55. package/dist/_internal/shared/search/match.js +28 -2
  56. package/dist/cli/index.js +0 -2
  57. package/dist/client.d.ts +25 -4
  58. package/dist/client.js +36 -5
  59. package/dist/constants/api-endpoints.d.ts +28 -15
  60. package/dist/constants/api-endpoints.js +14 -8
  61. package/dist/constants/field-names.d.ts +1 -0
  62. package/dist/constants/field-names.js +1 -0
  63. package/dist/constants/notification-types.d.ts +1 -1
  64. package/dist/constants/notification-types.js +1 -1
  65. package/dist/core/integration-keys.d.ts +5 -5
  66. package/dist/core/integration-keys.js +21 -10
  67. package/dist/features/about/components/FeesView.js +0 -6
  68. package/dist/features/about/components/GuidesHubView.js +15 -2
  69. package/dist/features/account/components/NotificationPreferencesPanel.js +3 -4
  70. package/dist/features/account/components/UserOrdersView.js +26 -7
  71. package/dist/features/account/types/index.d.ts +0 -2
  72. package/dist/features/addresses/utils/postal-autofill.d.ts +39 -0
  73. package/dist/features/addresses/utils/postal-autofill.js +54 -0
  74. package/dist/features/admin/actions/notification-actions.d.ts +2 -8
  75. package/dist/features/admin/actions/notification-actions.js +9 -104
  76. package/dist/features/admin/components/AdminGuideHubView.js +1 -8
  77. package/dist/features/admin/components/AdminOrderEditorView.d.ts +1 -1
  78. package/dist/features/admin/components/AdminOrdersView.js +0 -2
  79. package/dist/features/admin/components/AdminSectionsView.js +3 -2
  80. package/dist/features/admin/components/AdminSiteSettingsView.js +22 -68
  81. package/dist/features/admin/components/AdminStoreEditorView.js +72 -34
  82. package/dist/features/admin/components/OwnerQuickActions.d.ts +29 -0
  83. package/dist/features/admin/components/OwnerQuickActions.js +142 -0
  84. package/dist/features/admin/components/sections/adminSectionsTypes.js +13 -4
  85. package/dist/features/admin/components/sections/icon-options.d.ts +21 -0
  86. package/dist/features/admin/components/sections/icon-options.js +23 -0
  87. package/dist/features/admin/components/sections/sectionTemplates.js +4 -1
  88. package/dist/features/admin/constants/site-settings-tabs.d.ts +7 -12
  89. package/dist/features/admin/constants/site-settings-tabs.js +6 -12
  90. package/dist/features/admin/repository/site-settings.repository.js +1 -1
  91. package/dist/features/admin/schemas/admin-editor-forms.d.ts +1 -1
  92. package/dist/features/admin/schemas/admin-editor-forms.js +4 -1
  93. package/dist/features/admin/schemas/admin-user-form.d.ts +0 -61
  94. package/dist/features/admin/schemas/admin-user-form.js +3 -44
  95. package/dist/features/admin/schemas/firestore.d.ts +28 -54
  96. package/dist/features/admin/schemas/firestore.js +40 -18
  97. package/dist/features/auctions/components/AuctionDetailPageView.js +12 -10
  98. package/dist/features/auctions/components/MarketplaceAuctionCard.d.ts +11 -1
  99. package/dist/features/auctions/components/MarketplaceAuctionCard.js +9 -2
  100. package/dist/features/auth/checkout-value-otp.d.ts +1 -1
  101. package/dist/features/auth/checkout-value-otp.js +1 -1
  102. package/dist/features/auth/permissions/constants.d.ts +29 -2
  103. package/dist/features/auth/permissions/constants.js +67 -1
  104. package/dist/features/blog/components/BlogFeaturedCard.d.ts +11 -1
  105. package/dist/features/blog/components/BlogFeaturedCard.js +9 -2
  106. package/dist/features/cart/components/CartDrawer.js +3 -2
  107. package/dist/features/cart/components/CartGroupLineRow.js +2 -1
  108. package/dist/features/cart/components/CartPriceBreakdown.d.ts +0 -2
  109. package/dist/features/cart/components/CartPriceBreakdown.js +1 -1
  110. package/dist/features/cart/components/StoreAddonsPicker.d.ts +2 -5
  111. package/dist/features/cart/components/StoreAddonsPicker.js +4 -5
  112. package/dist/features/cart/hooks/useAddToCart.js +10 -5
  113. package/dist/features/cart/repository/cart.repository.js +1 -2
  114. package/dist/features/cart/schemas/firestore.d.ts +1 -2
  115. package/dist/features/cart/utils/pending-ops.d.ts +11 -1
  116. package/dist/features/cart/utils/pending-ops.js +14 -2
  117. package/dist/features/categories/api/[id]/price-guidance/route.js +1 -24
  118. package/dist/features/categories/components/BrandDetailPageView.js +15 -6
  119. package/dist/features/categories/components/BrandDetailTabs.d.ts +7 -1
  120. package/dist/features/categories/components/BrandDetailTabs.js +18 -3
  121. package/dist/features/categories/components/BundleCollage.js +3 -2
  122. package/dist/features/categories/components/BundleDetailView.js +2 -1
  123. package/dist/features/categories/components/BundleItemsPicker.js +3 -4
  124. package/dist/features/categories/components/CategoryDetailPageView.js +19 -8
  125. package/dist/features/categories/components/CategoryDetailTabs.d.ts +7 -1
  126. package/dist/features/categories/components/CategoryDetailTabs.js +29 -7
  127. package/dist/features/categories/components/CategoryGrid.d.ts +11 -1
  128. package/dist/features/categories/components/CategoryGrid.js +9 -2
  129. package/dist/features/checkout/actions/checkout-value-otp-actions.d.ts +10 -5
  130. package/dist/features/checkout/actions/checkout-value-otp-actions.js +2 -88
  131. package/dist/features/classified/components/ClassifiedDetailPageView.js +12 -2
  132. package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +12 -2
  133. package/dist/features/events/components/EventCard.d.ts +11 -1
  134. package/dist/features/events/components/EventCard.js +9 -2
  135. package/dist/features/grouped/components/GroupedListingDetailView.js +3 -1
  136. package/dist/features/homepage/components/CTABannerSection.d.ts +3 -1
  137. package/dist/features/homepage/components/CTABannerSection.js +6 -3
  138. package/dist/features/homepage/components/HeroCarousel.js +8 -6
  139. package/dist/features/homepage/components/MarketplaceHomepageView.js +33 -7
  140. package/dist/features/homepage/components/SectionCarousel.js +13 -5
  141. package/dist/features/homepage/components/SecurityHighlightsSection.d.ts +8 -3
  142. package/dist/features/homepage/components/SecurityHighlightsSection.js +2 -2
  143. package/dist/features/homepage/components/StatsCounterSection.d.ts +9 -4
  144. package/dist/features/homepage/components/StatsCounterSection.js +2 -2
  145. package/dist/features/homepage/components/TestimonialsCarousel.js +1 -1
  146. package/dist/features/homepage/components/TrustFeaturesSection.d.ts +18 -4
  147. package/dist/features/homepage/components/TrustFeaturesSection.js +5 -5
  148. package/dist/features/homepage/components/WelcomeSection.d.ts +13 -2
  149. package/dist/features/homepage/components/WelcomeSection.js +3 -3
  150. package/dist/features/homepage/components/WhatsAppCommunitySection.d.ts +28 -0
  151. package/dist/features/homepage/components/WhatsAppCommunitySection.js +42 -6
  152. package/dist/features/homepage/components/WhatsAppGlyph.d.ts +20 -0
  153. package/dist/features/homepage/components/WhatsAppGlyph.js +20 -0
  154. package/dist/features/homepage/constants/hero-carousel-styles.d.ts +8 -6
  155. package/dist/features/homepage/constants/hero-carousel-styles.js +8 -6
  156. package/dist/features/homepage/constants/section-copy.d.ts +12 -10
  157. package/dist/features/homepage/constants/section-copy.js +28 -6
  158. package/dist/features/homepage/constants/stat-icons.d.ts +12 -0
  159. package/dist/features/homepage/constants/stat-icons.js +17 -0
  160. package/dist/features/homepage/constants/trust-icon-aliases.d.ts +8 -0
  161. package/dist/features/homepage/constants/trust-icon-aliases.js +75 -0
  162. package/dist/features/homepage/lib/section-defaults.d.ts +16 -1
  163. package/dist/features/homepage/lib/section-defaults.js +24 -4
  164. package/dist/features/homepage/lib/section-renderer.js +48 -8
  165. package/dist/features/homepage/schemas/firestore.d.ts +18 -1
  166. package/dist/features/layout/AppLayoutShell.js +2 -1
  167. package/dist/features/layout/BottomActions.d.ts +1 -0
  168. package/dist/features/layout/BottomActions.js +330 -0
  169. package/dist/features/layout/BottomChrome.d.ts +45 -0
  170. package/dist/features/layout/BottomChrome.js +5 -17
  171. package/dist/features/layout/SideActionDock.js +36 -13
  172. package/dist/features/layout/index.d.ts +2 -7
  173. package/dist/features/layout/index.js +7 -7
  174. package/dist/features/layout/useIsDesktop.d.ts +36 -0
  175. package/dist/features/layout/useIsDesktop.js +48 -0
  176. package/dist/features/live/components/LiveItemDetailPageView.js +12 -2
  177. package/dist/features/orders/actions/refund-actions.js +0 -1
  178. package/dist/features/orders/components/OrderAddonBadges.d.ts +1 -3
  179. package/dist/features/orders/components/OrderAddonBadges.js +3 -4
  180. package/dist/features/orders/components/OrderPaymentSummary.js +15 -2
  181. package/dist/features/orders/components/YourPurchaseStrip.d.ts +24 -0
  182. package/dist/features/orders/components/YourPurchaseStrip.js +77 -0
  183. package/dist/features/orders/components/index.d.ts +2 -1
  184. package/dist/features/orders/components/index.js +1 -1
  185. package/dist/features/orders/repository/orders.repository.d.ts +0 -8
  186. package/dist/features/orders/repository/orders.repository.js +0 -2
  187. package/dist/features/orders/schemas/firestore.d.ts +17 -9
  188. package/dist/features/orders/types/index.d.ts +2 -5
  189. package/dist/features/orders/utils/order-announcement-message.d.ts +18 -0
  190. package/dist/features/orders/utils/order-announcement-message.js +16 -0
  191. package/dist/features/orders/utils/payment-proof-message.d.ts +20 -0
  192. package/dist/features/orders/utils/payment-proof-message.js +17 -0
  193. package/dist/features/parts/components/PartDetailPageView.js +96 -1
  194. package/dist/features/parts/schemas/firestore.d.ts +247 -0
  195. package/dist/features/parts/schemas/firestore.js +6 -6
  196. package/dist/features/pre-orders/components/MarketplacePreorderCard.d.ts +11 -1
  197. package/dist/features/pre-orders/components/MarketplacePreorderCard.js +10 -3
  198. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +12 -10
  199. package/dist/features/price-index/components/PriceIndexToolView.d.ts +21 -0
  200. package/dist/features/price-index/components/PriceIndexToolView.js +230 -27
  201. package/dist/features/price-index/lookup-target.d.ts +48 -0
  202. package/dist/features/price-index/lookup-target.js +107 -0
  203. package/dist/features/products/api/[id]/route.js +8 -1
  204. package/dist/features/products/api/route.js +16 -4
  205. package/dist/features/products/components/AvailabilityScopeHint.d.ts +22 -0
  206. package/dist/features/products/components/AvailabilityScopeHint.js +27 -0
  207. package/dist/features/products/components/CompareOverlay.d.ts +2 -1
  208. package/dist/features/products/components/CompareOverlay.js +2 -1
  209. package/dist/features/products/components/GroupSettingsPanel.js +2 -1
  210. package/dist/features/products/components/InteractiveProductCard.d.ts +7 -1
  211. package/dist/features/products/components/InteractiveProductCard.js +16 -4
  212. package/dist/features/products/components/MarketplaceBundleCard.d.ts +11 -1
  213. package/dist/features/products/components/MarketplaceBundleCard.js +9 -2
  214. package/dist/features/products/components/MarketplacePrizeDrawCard.d.ts +11 -1
  215. package/dist/features/products/components/MarketplacePrizeDrawCard.js +9 -2
  216. package/dist/features/products/components/PrizeDrawDetailPageView.js +2 -1
  217. package/dist/features/products/components/ProductDetailPageView.js +34 -4
  218. package/dist/features/products/components/ProductGrid.d.ts +14 -1
  219. package/dist/features/products/components/ProductGrid.js +22 -5
  220. package/dist/features/products/components/ProductsIndexListing.js +2 -2
  221. package/dist/features/products/components/SublistingCarouselSection.js +2 -1
  222. package/dist/features/products/repository/products.repository.d.ts +1 -0
  223. package/dist/features/products/repository/products.repository.js +5 -1
  224. package/dist/features/products/utils/group-member-image.d.ts +9 -2
  225. package/dist/features/products/utils/group-member-image.js +2 -1
  226. package/dist/features/reviews/api/[id]/route.js +83 -23
  227. package/dist/features/reviews/components/PurchaseReviewAffordance.d.ts +6 -0
  228. package/dist/features/reviews/components/PurchaseReviewAffordance.js +42 -0
  229. package/dist/features/reviews/components/ReviewFormDrawer.d.ts +34 -0
  230. package/dist/features/reviews/components/ReviewFormDrawer.js +127 -0
  231. package/dist/features/reviews/components/index.d.ts +4 -0
  232. package/dist/features/reviews/components/index.js +2 -0
  233. package/dist/features/scams/schemas/index.d.ts +10 -10
  234. package/dist/features/search/action-index/settings-entries.js +0 -9
  235. package/dist/features/seller/actions/seller-actions.d.ts +1 -1
  236. package/dist/features/seller/actions/seller-actions.js +49 -3
  237. package/dist/features/seller/components/SellerPayoutSettingsView.js +30 -2
  238. package/dist/features/seller/components/SellerProductShell.d.ts +17 -1
  239. package/dist/features/seller/components/SellerProductsView.js +3 -2
  240. package/dist/features/seller/hooks/useStoreListingEntitlements.d.ts +8 -0
  241. package/dist/features/seller/hooks/useStoreListingEntitlements.js +70 -0
  242. package/dist/features/store-extensions/repository/store-extensions.repositories.d.ts +1 -6
  243. package/dist/features/store-extensions/repository/store-extensions.repositories.js +1 -10
  244. package/dist/features/store-extensions/schemas/firestore.d.ts +1 -17
  245. package/dist/features/store-extensions/schemas/firestore.js +0 -10
  246. package/dist/features/stores/components/InteractiveStoreCard.d.ts +11 -1
  247. package/dist/features/stores/components/InteractiveStoreCard.js +9 -2
  248. package/dist/features/stores/components/StoreAuctionsListing.js +2 -1
  249. package/dist/features/stores/components/StoreCapabilitiesGuideView.js +0 -1
  250. package/dist/features/stores/components/StoreGuideHubView.js +2 -8
  251. package/dist/features/stores/components/StoreSettingsGuideView.js +2 -6
  252. package/dist/features/stores/components/index.d.ts +0 -2
  253. package/dist/features/stores/components/index.js +0 -1
  254. package/dist/features/stores/repository/store.repository.d.ts +1 -26
  255. package/dist/features/stores/repository/store.repository.js +5 -60
  256. package/dist/features/stores/schemas/firestore.d.ts +6 -25
  257. package/dist/features/stores/schemas/firestore.js +6 -3
  258. package/dist/features/stores/schemas/index.d.ts +1 -87
  259. package/dist/features/stores/schemas/index.js +10 -15
  260. package/dist/features/tester/seed-data/authored/admin__site-system.js +0 -48
  261. package/dist/features/tester/seed-data/authored/buying__buying-checkout.js +0 -40
  262. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.js +114 -2
  263. package/dist/features/tester/seed-data/authored/selling__quick-add-minimum-details.js +0 -16
  264. package/dist/features/tester/seed-data/authored/selling__seller-guide.js +1 -1
  265. package/dist/features/tester/seed-data/authored/selling__seller-marketing-extras.js +0 -79
  266. package/dist/features/tester/seed-data/authored/selling__seller-orders.js +1 -1
  267. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +427 -69
  268. package/dist/index.d.ts +20 -32
  269. package/dist/index.js +34 -43
  270. package/dist/next/routing/route-map.d.ts +2 -8
  271. package/dist/next/routing/route-map.js +21 -4
  272. package/dist/providers/db-firebase/base.repository.d.ts +1 -1
  273. package/dist/providers/db-firebase/base.repository.js +1 -1
  274. package/dist/providers/payment-razorpay/index.d.ts +125 -0
  275. package/dist/providers/payment-razorpay/index.js +232 -0
  276. package/dist/providers/payment-razorpay/signature.d.ts +53 -0
  277. package/dist/providers/payment-razorpay/signature.js +71 -0
  278. package/dist/providers/shipping-shiprocket/index.d.ts +98 -0
  279. package/dist/providers/shipping-shiprocket/index.js +356 -0
  280. package/dist/providers.d.ts +3 -0
  281. package/dist/providers.js +3 -0
  282. package/dist/react/hooks/useCanSeePrices.d.ts +0 -27
  283. package/dist/react/hooks/useCanSeePrices.js +25 -0
  284. package/dist/repositories/index.d.ts +1 -1
  285. package/dist/repositories/index.js +1 -1
  286. package/dist/schemas/registry.d.ts +10 -115
  287. package/dist/schemas/registry.js +1 -2
  288. package/dist/security/pii-encrypt.js +1 -1
  289. package/dist/seed/_helpers/category-forest.js +27 -0
  290. package/dist/seed/_helpers/category-parts-glossary-map.js +1816 -86
  291. package/dist/seed/_helpers/category-parts.d.ts +1 -1
  292. package/dist/seed/_helpers/category-parts.js +13412 -3020
  293. package/dist/seed/carousel-slides-seed-data.js +47 -10
  294. package/dist/seed/categories-seed-data.js +48 -6
  295. package/dist/seed/faq-seed-data.js +2 -2
  296. package/dist/seed/homepage-sections-seed-data.js +286 -54
  297. package/dist/seed/index.d.ts +1 -1
  298. package/dist/seed/index.js +1 -1
  299. package/dist/seed/manifest.d.ts +1 -1
  300. package/dist/seed/manifest.js +1 -2
  301. package/dist/seed/model-composition-seed-data.js +6 -8
  302. package/dist/seed/part-glossary/chunk0.d.ts +9 -0
  303. package/dist/seed/part-glossary/chunk0.js +35448 -0
  304. package/dist/seed/part-glossary/chunk1.d.ts +9 -0
  305. package/dist/seed/part-glossary/chunk1.js +40494 -0
  306. package/dist/seed/part-glossary/chunk2.d.ts +9 -0
  307. package/dist/seed/part-glossary/chunk2.js +51242 -0
  308. package/dist/seed/part-glossary/chunk3.d.ts +9 -0
  309. package/dist/seed/part-glossary/chunk3.js +53337 -0
  310. package/dist/seed/part-glossary/chunk4.d.ts +9 -0
  311. package/dist/seed/part-glossary/chunk4.js +51454 -0
  312. package/dist/seed/part-glossary-seed-data.d.ts +1 -1
  313. package/dist/seed/part-glossary-seed-data.js +23 -47483
  314. package/dist/seed/products-beyblade-x-seed-data.js +36 -1
  315. package/dist/seed/site-settings-seed-data.js +34 -35
  316. package/dist/seed/store-extensions-seed-data.d.ts +1 -2
  317. package/dist/seed/store-extensions-seed-data.js +1 -23
  318. package/dist/seed/stores-seed-data.js +0 -1
  319. package/dist/server-entry.d.ts +1 -1
  320. package/dist/server-entry.js +1 -1
  321. package/dist/server.d.ts +10 -10
  322. package/dist/server.js +24 -22
  323. package/dist/styles.css +392 -43
  324. package/dist/tailwind-utilities.css +1 -1
  325. package/dist/tokens/themes/default-dark.js +1 -1
  326. package/dist/tokens/themes/default-light.js +2 -1
  327. package/dist/tokens/tokens.css +6 -2
  328. package/dist/ui/components/Button.d.ts +11 -0
  329. package/dist/ui/components/Button.js +11 -0
  330. package/dist/ui/components/Button.style.css +29 -0
  331. package/dist/ui/components/CarouselNav.d.ts +57 -0
  332. package/dist/ui/components/CarouselNav.js +25 -0
  333. package/dist/ui/components/CarouselNav.style.css +265 -0
  334. package/dist/ui/components/GatedPrice.js +30 -3
  335. package/dist/ui/components/GatedPrice.style.css +43 -40
  336. package/dist/ui/components/HorizontalScroller.d.ts +12 -1
  337. package/dist/ui/components/HorizontalScroller.js +43 -3
  338. package/dist/ui/components/ImageMosaic.d.ts +8 -1
  339. package/dist/ui/components/ImageMosaic.js +3 -2
  340. package/dist/ui/components/ImageMosaic.style.css +22 -0
  341. package/dist/ui/components/Layout.style.css +6 -0
  342. package/dist/ui/components/Semantic.d.ts +3 -2
  343. package/dist/ui/components/Semantic.js +1 -0
  344. package/dist/ui/components/Typography.d.ts +2 -0
  345. package/dist/ui/components/Typography.js +2 -0
  346. package/dist/ui/components/Typography.style.css +19 -0
  347. package/dist/ui/components/index.style.css +1 -0
  348. package/dist/ui/index.d.ts +3 -1
  349. package/dist/ui/index.js +4 -0
  350. package/package.json +3 -2
  351. package/scripts/seed-cli.mjs +133 -27
  352. package/dist/_internal/server/jobs/core/whatsappCatalogImport.d.ts +0 -27
  353. package/dist/_internal/server/jobs/core/whatsappCatalogImport.js +0 -172
  354. package/dist/_internal/server/jobs/core/whatsappNotify.d.ts +0 -35
  355. package/dist/_internal/server/jobs/core/whatsappNotify.js +0 -140
  356. package/dist/features/admin/components/AdminWhatsAppGuideView.d.ts +0 -2
  357. package/dist/features/admin/components/AdminWhatsAppGuideView.js +0 -35
  358. package/dist/features/orders/components/MarketplaceOrderCard.d.ts +0 -36
  359. package/dist/features/orders/components/MarketplaceOrderCard.js +0 -57
  360. package/dist/features/stores/components/StoreWhatsAppGuideView.d.ts +0 -3
  361. package/dist/features/stores/components/StoreWhatsAppGuideView.js +0 -12
  362. package/dist/features/whatsapp-bot/api/send-status/route.d.ts +0 -12
  363. package/dist/features/whatsapp-bot/api/send-status/route.js +0 -38
  364. package/dist/features/whatsapp-bot/api/webhook/route.d.ts +0 -12
  365. package/dist/features/whatsapp-bot/api/webhook/route.js +0 -43
  366. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.d.ts +0 -6
  367. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +0 -270
  368. package/dist/features/whatsapp-bot/components/WhatsAppChatButton.d.ts +0 -9
  369. package/dist/features/whatsapp-bot/components/WhatsAppChatButton.js +0 -7
  370. package/dist/features/whatsapp-bot/components/index.d.ts +0 -3
  371. package/dist/features/whatsapp-bot/components/index.js +0 -2
  372. package/dist/features/whatsapp-bot/helpers/payment-proof-message.d.ts +0 -14
  373. package/dist/features/whatsapp-bot/helpers/payment-proof-message.js +0 -17
  374. package/dist/features/whatsapp-bot/helpers/whatsapp.d.ts +0 -52
  375. package/dist/features/whatsapp-bot/helpers/whatsapp.js +0 -283
  376. package/dist/features/whatsapp-bot/index.d.ts +0 -3
  377. package/dist/features/whatsapp-bot/index.js +0 -3
  378. package/dist/features/whatsapp-bot/manifest.d.ts +0 -2
  379. package/dist/features/whatsapp-bot/manifest.js +0 -13
  380. package/dist/features/whatsapp-bot/messages/en.json +0 -7
  381. package/dist/features/whatsapp-bot/server.d.ts +0 -7
  382. package/dist/features/whatsapp-bot/server.js +0 -7
  383. package/dist/features/whatsapp-bot/types/index.d.ts +0 -126
  384. package/dist/features/whatsapp-bot/types/index.js +0 -1
@@ -1,77 +1,7 @@
1
1
  import { normalizeError } from "../../../../errors/normalize.js";
2
2
  import { ORDER_PII_FIELDS, revealPii } from "../../../../security/index.js";
3
- import { adminNotificationsRepository, storeRepository, userRepository } from "../../../../repositories/index.js";
4
- import { decryptPii } from "../../../../security/index.js";
5
- import { sendWhatsAppBusinessMessage, buildPurchaseAnnouncementMessage, } from "../../../../features/whatsapp-bot/server.js";
6
- import { resolveKeys } from "../../../../core/integration-keys.js";
7
- import { guardSend, logSuppressedSend } from "../../notifications/send-guard.js";
8
- async function sendAnnouncement(ctx, toPhone, message, phoneNumberId, accessToken, label, orderId) {
9
- try {
10
- const sent = await sendWhatsAppBusinessMessage({
11
- toPhone,
12
- message,
13
- phoneNumberId,
14
- accessToken,
15
- });
16
- if (sent) {
17
- ctx.logger.info(`Announcement sent to ${label}`, {
18
- orderId,
19
- toPhone: `...${toPhone.slice(-4)}`,
20
- });
21
- }
22
- else {
23
- ctx.logger.error(`Announcement delivery failed for ${label} (non-fatal)`, null, { orderId });
24
- }
25
- }
26
- catch (err) {
27
- void normalizeError(err);
28
- ctx.logger.error(`Announcement send threw for ${label} (non-fatal)`, err, { orderId });
29
- }
30
- }
31
- async function notifyStoreOwner(ctx, storeId, message, phoneNumberId, accessToken, orderId) {
32
- try {
33
- const store = await storeRepository.findBySlug(storeId);
34
- if (!store?.ownerId)
35
- return;
36
- const owner = await userRepository.findById(store.ownerId);
37
- const encryptedPhone = owner?.phoneNumber;
38
- if (!encryptedPhone)
39
- return;
40
- const ownerPhone = decryptPii(encryptedPhone);
41
- if (ownerPhone) {
42
- await sendAnnouncement(ctx, ownerPhone, message, phoneNumberId, accessToken, "store-owner", orderId);
43
- }
44
- }
45
- catch (err) {
46
- void normalizeError(err);
47
- ctx.logger.error("Store owner lookup failed (non-fatal)", err, { orderId, storeId });
48
- }
49
- }
50
- /**
51
- * Seeded credentials are `*_PLACEHOLDER` strings rather than empty, so an
52
- * emptiness test alone would happily send with a fake token. Mirrors the guard
53
- * in checkout-value-otp-actions.ts.
54
- */
55
- function usable(value) {
56
- const v = value?.trim() ?? "";
57
- return v && !v.includes("PLACEHOLDER") ? v : "";
58
- }
59
- async function resolveWhatsAppCredentials(ctx, orderId) {
60
- let db = {};
61
- try {
62
- db = await resolveKeys();
63
- }
64
- catch (err) {
65
- void normalizeError(err);
66
- // Firestore unreachable from the Functions runtime — env-only is still a
67
- // valid configuration, so this is a warning, not a failure.
68
- ctx.logger.warn("Credential lookup failed — falling back to env", { orderId });
69
- }
70
- return {
71
- phoneNumberId: usable(db.whatsappPhoneNumberId) || usable(ctx.env("WHATSAPP_PHONE_NUMBER_ID")),
72
- accessToken: usable(db.whatsappCloudApiToken) || usable(ctx.env("WHATSAPP_CLOUD_API_TOKEN")),
73
- };
74
- }
3
+ import { adminNotificationsRepository } from "../../../../repositories/index.js";
4
+ import { buildPurchaseAnnouncementMessage } from "../../../../features/orders/utils/order-announcement-message.js";
75
5
  export async function handleOrderCreate(input, ctx) {
76
6
  const { orderId, order } = input;
77
7
  const items = order.items ?? [];
@@ -140,37 +70,13 @@ export async function handleOrderCreate(input, ctx) {
140
70
  ctx.logger.error("Failed to write admin order notification (non-fatal)", err, { orderId });
141
71
  }
142
72
  /*
143
- * Seller side keeps WhatsApp: it is ONE message to ONE person about their
144
- * own sale, which is the case the channel is good at. Credentials resolve
145
- * DB-first (Admin → Site Settings → WhatsApp) with an env fallback — this
146
- * read `ctx.env()` only until 2026-08-22, so credentials saved in Site
147
- * Settings never reached the announcement and it silently no-op'd.
73
+ * The seller is told about their own sale by the `order_placed`
74
+ * notification `createOrderForGroup` already sends (in-app + email). This
75
+ * handler used to ALSO push a WhatsApp Cloud API message here — a duplicate
76
+ * channel for the same event, and the only thing in this file that needed a
77
+ * Meta token, a registered number and a billing relationship. Removed with
78
+ * the rest of the WhatsApp integration on 2026-10-20; no signal was lost,
79
+ * because the notification path is independent and unchanged.
148
80
  */
149
- const storeId = order.storeId;
150
- if (!storeId) {
151
- ctx.logger.info("Order has no storeId — nothing to announce to a seller", { orderId });
152
- return;
153
- }
154
- const { phoneNumberId, accessToken } = await resolveWhatsAppCredentials(ctx, orderId);
155
- if (!phoneNumberId || !accessToken) {
156
- ctx.logger.info("WhatsApp Cloud API not configured — skipping seller announcement", { orderId });
157
- return;
158
- }
159
- // Audience is "user": a seller receiving news of their own sale is a
160
- // marketplace participant, not an operator of the site. Staff exemption is
161
- // for the digest and the payout summary, and widening it to "anyone we think
162
- // ought to see this" would make the kill switch mean nothing.
163
- const guard = {
164
- channel: "whatsapp",
165
- feature: "order_placed_seller",
166
- audience: "user",
167
- };
168
- const decision = await guardSend(guard);
169
- if (!decision.allow) {
170
- logSuppressedSend(guard, decision);
171
- ctx.logger.info("Seller order announcement suppressed by messaging guard", { orderId, storeId });
172
- return;
173
- }
174
- await notifyStoreOwner(ctx, storeId, message, phoneNumberId, accessToken, orderId);
175
- ctx.logger.info(`Order announcement complete`, { orderId, storeId });
81
+ ctx.logger.info("Order announcement complete", { orderId, storeId: order.storeId ?? null });
176
82
  }
@@ -6,8 +6,6 @@ export type OrderAfter = {
6
6
  userEmail: string;
7
7
  productTitle: string;
8
8
  trackingNumber?: string;
9
- /** Buyer opted into the ₹10 WhatsApp order-updates addon at checkout. */
10
- whatsappNotifyAddon?: boolean;
11
9
  };
12
10
  export type OrderBefore = {
13
11
  status: OrderStatus;
@@ -54,7 +54,6 @@ export async function handleOrderStatusChange(input, ctx) {
54
54
  relatedId: orderId,
55
55
  relatedType: "order",
56
56
  userEmail,
57
- orderWhatsappAddonPaid: after.whatsappNotifyAddon === true,
58
57
  });
59
58
  // The RTDB mirror that used to live here has been removed. `sendNotification`
60
59
  // above is the real path (in-app + email + WhatsApp); the extra
@@ -30,7 +30,6 @@ export async function handleScamReportCreate(input, ctx) {
30
30
  relatedId: scammerId,
31
31
  relatedType: "scammer",
32
32
  userEmail: reporterPlain?.email ?? undefined,
33
- userPhone: reporterPlain?.phoneNumber ?? undefined,
34
33
  });
35
34
  }
36
35
  catch (err) {
@@ -28,7 +28,6 @@ export async function handleScamReportRejected(input, ctx) {
28
28
  relatedId: scammerId,
29
29
  relatedType: "scammer",
30
30
  userEmail: reporterPlain?.email ?? undefined,
31
- userPhone: reporterPlain?.phoneNumber ?? undefined,
32
31
  });
33
32
  }
34
33
  catch (err) {
@@ -28,7 +28,6 @@ export async function handleScamReportVerified(input, ctx) {
28
28
  relatedId: scammerId,
29
29
  relatedType: "scammer",
30
30
  userEmail: reporterPlain?.email ?? undefined,
31
- userPhone: reporterPlain?.phoneNumber ?? undefined,
32
31
  });
33
32
  }
34
33
  catch (err) {
@@ -56,7 +56,6 @@ export async function runPaymentWindowTimeout(ctx) {
56
56
  message: ORDER_MESSAGES.CANCELLED_PAYMENT_WINDOW_MESSAGE(entry.data.productTitle),
57
57
  relatedId: entry.id,
58
58
  relatedType: "order",
59
- orderWhatsappAddonPaid: entry.data.whatsappNotifyAddon === true,
60
59
  });
61
60
  }
62
61
  catch (err) {
@@ -67,7 +67,6 @@ export async function runPendingOrderTimeout(ctx) {
67
67
  message: ORDER_MESSAGES.CANCELLED_TIMEOUT_MESSAGE(entry.data.productTitle, timeoutHours),
68
68
  relatedId: entry.id,
69
69
  relatedType: "order",
70
- orderWhatsappAddonPaid: entry.data.whatsappNotifyAddon === true,
71
70
  });
72
71
  }
73
72
  catch (err) {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Circuit breaker for outbound notification channels (email, WhatsApp).
2
+ * Circuit breaker for outbound notification channels.
3
3
  *
4
4
  * Persisted as a singleton Firestore doc `system/channelHealth` so the
5
5
  * "is this channel currently known-bad" state survives across requests and
@@ -9,7 +9,11 @@
9
9
  * provider). After the cooldown, the next attempt is a half-open probe:
10
10
  * its own outcome decides whether the circuit re-closes or re-opens.
11
11
  */
12
- export type NotificationChannel = "email" | "whatsapp";
12
+ /**
13
+ * Email is the only outbound channel with a transport. "whatsapp" was the
14
+ * other arm until 2026-10-20, when the Cloud API integration was removed.
15
+ */
16
+ export type NotificationChannel = "email";
13
17
  /**
14
18
  * Returns false only when the circuit is open and still within its cooldown
15
19
  * window. Any other state (closed, or open-but-cooldown-elapsed) is treated
@@ -20,7 +24,7 @@ export declare function recordChannelOutcome(channel: NotificationChannel, succe
20
24
  /**
21
25
  * Runs `fn` up to 3 times (500ms then 1.5s between attempts) and records the
22
26
  * final outcome against the channel's health state. `fn` must throw on
23
- * failure — for a helper that returns a boolean instead (e.g. the WhatsApp
27
+ * failure — for a helper that returns a boolean instead (e.g. a sender
24
28
  * Cloud API helpers), convert `false` into a thrown error at the call site
25
29
  * before passing it in.
26
30
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Circuit breaker for outbound notification channels (email, WhatsApp).
2
+ * Circuit breaker for outbound notification channels.
3
3
  *
4
4
  * Persisted as a singleton Firestore doc `system/channelHealth` so the
5
5
  * "is this channel currently known-bad" state survives across requests and
@@ -72,7 +72,7 @@ function delay(ms) {
72
72
  /**
73
73
  * Runs `fn` up to 3 times (500ms then 1.5s between attempts) and records the
74
74
  * final outcome against the channel's health state. `fn` must throw on
75
- * failure — for a helper that returns a boolean instead (e.g. the WhatsApp
75
+ * failure — for a helper that returns a boolean instead (e.g. a sender
76
76
  * Cloud API helpers), convert `false` into a thrown error at the call site
77
77
  * before passing it in.
78
78
  */
@@ -15,7 +15,7 @@
15
15
  * message.
16
16
  *
17
17
  * The guarantee that nothing bypasses this is STRUCTURAL instead: the guard
18
- * argument is REQUIRED on `sendEmail` and on both WhatsApp senders, so an
18
+ * argument is REQUIRED on `sendEmail`, so an
19
19
  * unguarded send does not typecheck, and `scripts/audit-unguarded-send.mjs`
20
20
  * fails the build on a raw `createResendProvider().send()`. Make the wrong
21
21
  * thing unrepresentable rather than adding a second layer of defence that has
@@ -15,7 +15,7 @@
15
15
  * message.
16
16
  *
17
17
  * The guarantee that nothing bypasses this is STRUCTURAL instead: the guard
18
- * argument is REQUIRED on `sendEmail` and on both WhatsApp senders, so an
18
+ * argument is REQUIRED on `sendEmail`, so an
19
19
  * unguarded send does not typecheck, and `scripts/audit-unguarded-send.mjs`
20
20
  * fails the build on a raw `createResendProvider().send()`. Make the wrong
21
21
  * thing unrepresentable rather than adding a second layer of defence that has
@@ -69,9 +69,7 @@ export async function guardSend(ctx) {
69
69
  if (ctx.audience === "user" && !ctx.transactional) {
70
70
  const channelEnabled = ctx.channel === "email"
71
71
  ? (messaging?.emailEnabled ?? MESSAGE_BUDGET_DEFAULTS.emailEnabled)
72
- : ctx.channel === "whatsapp"
73
- ? (messaging?.whatsappEnabled ?? MESSAGE_BUDGET_DEFAULTS.whatsappEnabled)
74
- : false; // sms has no sender; if one appears it starts disabled.
72
+ : false; // sms has no sender; if one appears it starts disabled.
75
73
  if (!channelEnabled) {
76
74
  return {
77
75
  allow: false,
@@ -29,7 +29,7 @@ import type { IconKey } from "../../../ui/icons/icon-registry";
29
29
  /** What KIND of action — drives default UI affordance (link vs button vs danger). */
30
30
  export type ActionKind = "primary" | "secondary" | "danger" | "ghost" | "link" | "chip";
31
31
  /** Resource bucket — keyed top-level in the ACTIONS tree. */
32
- export type ActionResource = "PRODUCT" | "AUCTION" | "PRE_ORDER" | "PRIZE_DRAW" | "DIGITAL_CODE" | "BUNDLE" | "GROUP" | "CATEGORY" | "BRAND" | "SUBLISTING" | "STORE" | "BLOG" | "EVENT" | "SHIPMENT" | "CATALOGUE" | "USER" | "SELLER" | "ADMIN" | "CART" | "CHECKOUT" | "NAV" | "MEDIA" | "SUPPORT" | "LOTTERY" | "TESTER";
32
+ export type ActionResource = "PRODUCT" | "AUCTION" | "PRE_ORDER" | "PRIZE_DRAW" | "DIGITAL_CODE" | "BUNDLE" | "GROUP" | "CATEGORY" | "BRAND" | "SUBLISTING" | "STORE" | "BLOG" | "EVENT" | "REVIEW" | "SHIPMENT" | "CATALOGUE" | "USER" | "SELLER" | "ADMIN" | "CART" | "CHECKOUT" | "NAV" | "MEDIA" | "SUPPORT" | "LOTTERY" | "TESTER";
33
33
  /** Confirmation modal config — when set, <Button action={...}> opens
34
34
  * a confirm dialog before firing the actual handler. */
35
35
  export interface ActionConfirmation {
@@ -111,6 +111,28 @@ export const ACTIONS = {
111
111
  confirmLabel: "Delete listing",
112
112
  },
113
113
  },
114
+ /*
115
+ * Clone — ADMIN ONLY, and no confirmation.
116
+ *
117
+ * `POST /api/store/products/[id]/duplicate` already strips identity,
118
+ * analytics, auction bid state and group membership, titles the copy
119
+ * "… (Copy)" and forces `status: "draft"`. So it creates a draft and
120
+ * destroys nothing: a confirm dialog on a non-destructive action trains
121
+ * people to dismiss confirm dialogs.
122
+ *
123
+ * 🛑 `permissions: ["admin"]` is narrower than `edit`/`delete` above on
124
+ * purpose. A seller editing or deleting their own listing is ordinary;
125
+ * duplicating across the catalogue is a staff tool.
126
+ */
127
+ duplicate: {
128
+ iconKey: "duplicate",
129
+ id: "product.duplicate",
130
+ label: "Duplicate",
131
+ ariaLabel: "Duplicate this listing as a draft",
132
+ description: "Copy this listing into a new draft, without its bids, analytics or group membership.",
133
+ kind: "secondary",
134
+ permissions: ["admin"],
135
+ },
114
136
  "add-to-cart": {
115
137
  iconKey: "cart",
116
138
  id: "product.add-to-cart",
@@ -321,6 +343,43 @@ export const ACTIONS = {
321
343
  kind: "primary",
322
344
  categoryTypeScope: ["bundle"],
323
345
  },
346
+ /*
347
+ * Edit and delete lived only in the ADMIN bucket (`delete-bundle`,
348
+ * `activate-bundle`, …), so a bundle's own surfaces had nothing
349
+ * resource-scoped to resolve against. Added here beside `buy-now` so the
350
+ * owner affordance keys on the resource it is acting on, like every other
351
+ * bucket.
352
+ *
353
+ * 🛑 No `duplicate`. A bundle's members, `bundleCategorySlugs` and
354
+ * `display.mosaicImages` are all resolved at WRITE time, so a copy would
355
+ * carry another bundle's resolved state.
356
+ */
357
+ edit: {
358
+ iconKey: "edit",
359
+ id: "bundle.edit",
360
+ label: "Edit",
361
+ ariaLabel: "Edit bundle",
362
+ description: "Edit this bundle.",
363
+ kind: "secondary",
364
+ permissions: ["admin", "seller"],
365
+ categoryTypeScope: ["bundle"],
366
+ },
367
+ delete: {
368
+ iconKey: "delete",
369
+ id: "bundle.delete",
370
+ label: "Delete",
371
+ ariaLabel: "Delete bundle",
372
+ description: "Permanently delete this bundle.",
373
+ kind: "danger",
374
+ permissions: ["admin", "seller"],
375
+ categoryTypeScope: ["bundle"],
376
+ confirmation: {
377
+ title: "Delete this bundle?",
378
+ body: "This cannot be undone. The products inside it are NOT deleted — only the bundle that groups them and its discounted price.",
379
+ confirmLabel: "Delete bundle",
380
+ confirmKind: "danger",
381
+ },
382
+ },
324
383
  },
325
384
  /*
326
385
  * These four buckets were literally `{}` for months while their editors
@@ -660,34 +719,6 @@ export const ACTIONS = {
660
719
  kind: "ghost",
661
720
  permissions: ["seller", "admin"],
662
721
  },
663
- // ── WhatsApp integration ────────────────────────────────────────────
664
- "whatsapp-connect": {
665
- iconKey: "link",
666
- id: "store.whatsapp-connect",
667
- label: "Save & Connect",
668
- ariaLabel: "Save WhatsApp credentials and connect",
669
- description: "Save WhatsApp Business credentials and establish connection.",
670
- kind: "primary",
671
- permissions: ["seller", "admin"],
672
- },
673
- "whatsapp-catalog-sync": {
674
- iconKey: "retry",
675
- id: "store.whatsapp-catalog-sync",
676
- label: "Push to WhatsApp",
677
- ariaLabel: "Sync products to WhatsApp catalog",
678
- description: "Push published standard products to WhatsApp Business Catalog.",
679
- kind: "secondary",
680
- permissions: ["seller", "admin"],
681
- },
682
- "whatsapp-catalog-import": {
683
- iconKey: "upload",
684
- id: "store.whatsapp-catalog-import",
685
- label: "Import from WhatsApp",
686
- ariaLabel: "Import products from WhatsApp catalog",
687
- description: "Import products from WhatsApp Catalog as drafts.",
688
- kind: "secondary",
689
- permissions: ["seller", "admin"],
690
- },
691
722
  // ── Google Reviews integration ──────────────────────────────────────
692
723
  "google-reviews-sync": {
693
724
  iconKey: "retry",
@@ -1042,7 +1073,76 @@ export const ACTIONS = {
1042
1073
  },
1043
1074
  },
1044
1075
  },
1076
+ /*
1077
+ * There was no REVIEW bucket at all, while review actions sat scattered
1078
+ * across three others — ADMIN (approve / reject / feature), STORE (reply /
1079
+ * contest) and USER (write-review) — and NOTHING anywhere for a reviewer
1080
+ * editing or deleting their own review. That is the gap a buyer hits on a
1081
+ * product page, so it is the one this bucket is for.
1082
+ */
1083
+ REVIEW: {
1084
+ edit: {
1085
+ iconKey: "edit",
1086
+ id: "review.edit",
1087
+ label: "Edit review",
1088
+ ariaLabel: "Edit your review",
1089
+ description: "Edit a review you wrote.",
1090
+ kind: "secondary",
1091
+ },
1092
+ delete: {
1093
+ iconKey: "delete",
1094
+ id: "review.delete",
1095
+ label: "Delete review",
1096
+ ariaLabel: "Delete your review",
1097
+ description: "Permanently delete a review you wrote.",
1098
+ kind: "danger",
1099
+ confirmation: {
1100
+ title: "Delete your review?",
1101
+ body: "This cannot be undone. The seller's reply to it goes too, and the product's rating is recalculated without your score.",
1102
+ confirmLabel: "Delete review",
1103
+ confirmKind: "danger",
1104
+ },
1105
+ },
1106
+ write: {
1107
+ iconKey: "review",
1108
+ id: "review.write",
1109
+ label: "Write a review",
1110
+ ariaLabel: "Write a review for this item",
1111
+ description: "Write a review for an item you bought.",
1112
+ kind: "primary",
1113
+ },
1114
+ },
1045
1115
  EVENT: {
1116
+ /*
1117
+ * This bucket had only register / cancel-registration / draw-raffle-winner
1118
+ * — no edit, no delete — so the owner affordance on an event card or detail
1119
+ * page had no registry entry to resolve its label and confirm copy from,
1120
+ * and Rule #7 forbids inlining them.
1121
+ */
1122
+ edit: {
1123
+ iconKey: "edit",
1124
+ id: "event.edit",
1125
+ label: "Edit",
1126
+ ariaLabel: "Edit event",
1127
+ description: "Edit this event.",
1128
+ kind: "secondary",
1129
+ permissions: ["admin"],
1130
+ },
1131
+ delete: {
1132
+ iconKey: "delete",
1133
+ id: "event.delete",
1134
+ label: "Delete",
1135
+ ariaLabel: "Delete event",
1136
+ description: "Permanently delete this event.",
1137
+ kind: "danger",
1138
+ permissions: ["admin"],
1139
+ confirmation: {
1140
+ title: "Delete this event?",
1141
+ body: "This cannot be undone. Entries already recorded against it are removed with it, so a participant loses their place.",
1142
+ confirmLabel: "Delete event",
1143
+ confirmKind: "danger",
1144
+ },
1145
+ },
1046
1146
  "register": {
1047
1147
  iconKey: "user",
1048
1148
  id: "event.register",
@@ -170,7 +170,7 @@ export interface PayableOrderLike {
170
170
  * money bug in all four payout paths (`autoPayoutEligibility`,
171
171
  * `weeklyPayoutEligibility`, and both `seller-actions` entry points). That
172
172
  * field is the GRAND TOTAL — `checkout/actions.ts` builds it as
173
- * `goods − coupon + shipping + codHandling + whatsappNotify + giftWrap +
173
+ * `goods − coupon + shipping + codHandling + giftWrap +
174
174
  * shipmentProtection + platformFee + platformFeeGst + emiSurcharge + gstAmount`
175
175
  * — so using it as the payout base did three wrong things at once:
176
176
  *
@@ -264,7 +264,7 @@ export function allocateAcrossMembers(total, weights) {
264
264
  * money bug in all four payout paths (`autoPayoutEligibility`,
265
265
  * `weeklyPayoutEligibility`, and both `seller-actions` entry points). That
266
266
  * field is the GRAND TOTAL — `checkout/actions.ts` builds it as
267
- * `goods − coupon + shipping + codHandling + whatsappNotify + giftWrap +
267
+ * `goods − coupon + shipping + codHandling + giftWrap +
268
268
  * shipmentProtection + platformFee + platformFeeGst + emiSurcharge + gstAmount`
269
269
  * — so using it as the payout base did three wrong things at once:
270
270
  *
@@ -72,7 +72,7 @@ export declare const BUNDLE_COPY: {
72
72
  readonly adminEditor: {
73
73
  readonly loading: "Loading bundle…";
74
74
  readonly saveButton: (saving: boolean, isEdit: boolean) => "Save changes" | "Saving…" | "Create bundle";
75
- readonly deleteButton: (deleting: boolean) => "Deleting…" | "Delete bundle";
75
+ readonly deleteButton: (deleting: boolean) => "Delete bundle" | "Deleting…";
76
76
  readonly deleteConfirm: "Delete this bundle? This action cannot be undone.";
77
77
  readonly fields: {
78
78
  readonly nameLabel: "Name *";
@@ -6,8 +6,6 @@ export declare const CHECKOUT_DEFAULT_COMMISSIONS: {
6
6
  readonly codDepositPercent: 10;
7
7
  readonly codHandlingFeeMin: 200;
8
8
  readonly codHandlingFeePercent: 10;
9
- readonly whatsappNotifyFeeEnabled: true;
10
- readonly whatsappNotifyFee: 10;
11
9
  readonly giftWrapFeeEnabled: true;
12
10
  readonly giftWrapFee: 49;
13
11
  readonly shipmentProtectionFeeEnabled: true;
@@ -13,8 +13,6 @@ export const CHECKOUT_DEFAULT_COMMISSIONS = {
13
13
  // Mirrors the SiteSettingsDocument defaults, which enable every add-on.
14
14
  // Consequence of the mirror: if the settings read fails, an add-on already
15
15
  // ticked on the cart document is still billed rather than silently dropped.
16
- whatsappNotifyFeeEnabled: true,
17
- whatsappNotifyFee: 10,
18
16
  giftWrapFeeEnabled: true,
19
17
  giftWrapFee: 49,
20
18
  shipmentProtectionFeeEnabled: true,
@@ -16,7 +16,12 @@
16
16
  * and find the budget already covers them. A channel that is born capped
17
17
  * cannot repeat what email did.
18
18
  */
19
- export type MessageChannel = "email" | "whatsapp" | "sms";
19
+ /**
20
+ * `whatsapp` was removed 2026-10-20 with the Cloud API integration. `sms`
21
+ * stays declared with no sender — the ceiling exists so one cannot ship
22
+ * uncapped — and `email` is the only channel with a live transport.
23
+ */
24
+ export type MessageChannel = "email" | "sms";
20
25
  /**
21
26
  * Who the message is FOR — which is what the kill switch keys on.
22
27
  *
@@ -76,13 +81,12 @@ export type SendDecision = {
76
81
  /**
77
82
  * Defaults, mirrored into `DEFAULT_SITE_SETTINGS_DATA.messaging`.
78
83
  *
79
- * 🛑 `emailEnabled` and `whatsappEnabled` default to FALSE. An install that
84
+ * 🛑 `emailEnabled` defaults to FALSE. An install that
80
85
  * has not made a decision should be quiet, not loud — the opposite default is
81
86
  * how a fresh deploy mails real people from a half-configured site.
82
87
  */
83
88
  export declare const MESSAGE_BUDGET_DEFAULTS: {
84
89
  readonly emailEnabled: false;
85
- readonly whatsappEnabled: false;
86
90
  readonly dailyCeiling: {
87
91
  /**
88
92
  * Resend's free tier is 100/day. 80 is not timidity — the counter is
@@ -92,8 +96,6 @@ export declare const MESSAGE_BUDGET_DEFAULTS: {
92
96
  * headroom is what stops "at the limit" from becoming "over it".
93
97
  */
94
98
  readonly email: 80;
95
- /** Meta's pricing is per-conversation, not per-message; this is a sanity bound, not a tier limit. */
96
- readonly whatsapp: 200;
97
99
  /** No sender exists yet. Present so one cannot ship uncapped. */
98
100
  readonly sms: 50;
99
101
  };
@@ -9,13 +9,12 @@
9
9
  /**
10
10
  * Defaults, mirrored into `DEFAULT_SITE_SETTINGS_DATA.messaging`.
11
11
  *
12
- * 🛑 `emailEnabled` and `whatsappEnabled` default to FALSE. An install that
12
+ * 🛑 `emailEnabled` defaults to FALSE. An install that
13
13
  * has not made a decision should be quiet, not loud — the opposite default is
14
14
  * how a fresh deploy mails real people from a half-configured site.
15
15
  */
16
16
  export const MESSAGE_BUDGET_DEFAULTS = {
17
17
  emailEnabled: false,
18
- whatsappEnabled: false,
19
18
  dailyCeiling: {
20
19
  /**
21
20
  * Resend's free tier is 100/day. 80 is not timidity — the counter is
@@ -25,8 +24,6 @@ export const MESSAGE_BUDGET_DEFAULTS = {
25
24
  * headroom is what stops "at the limit" from becoming "over it".
26
25
  */
27
26
  email: 80,
28
- /** Meta's pricing is per-conversation, not per-message; this is a sanity bound, not a tier limit. */
29
- whatsapp: 200,
30
27
  /** No sender exists yet. Present so one cannot ship uncapped. */
31
28
  sms: 50,
32
29
  },
@@ -27,8 +27,6 @@ import type { EmiSettings } from "../emi/schedule";
27
27
  * and each `compute*Fee` helper carries its own default.
28
28
  */
29
29
  export interface BuyerFacingFees {
30
- whatsappNotifyFeeEnabled?: boolean;
31
- whatsappNotifyFee?: number;
32
30
  giftWrapFeeEnabled?: boolean;
33
31
  giftWrapFee?: number;
34
32
  shipmentProtectionFeeEnabled?: boolean;
@@ -13,8 +13,6 @@ export function toBuyerFacingFees(commissions) {
13
13
  if (!commissions)
14
14
  return null;
15
15
  return {
16
- whatsappNotifyFeeEnabled: commissions.whatsappNotifyFeeEnabled,
17
- whatsappNotifyFee: commissions.whatsappNotifyFee,
18
16
  giftWrapFeeEnabled: commissions.giftWrapFeeEnabled,
19
17
  giftWrapFee: commissions.giftWrapFee,
20
18
  shipmentProtectionFeeEnabled: commissions.shipmentProtectionFeeEnabled,
@@ -0,0 +1,56 @@
1
+ /**
2
+ * The platform's own supplier-of-record identity, injected once at boot.
3
+ *
4
+ * ── Why this seam exists ──────────────────────────────────────────────────
5
+ *
6
+ * `appkit.config.js → business` is documented as "THE one owner of the
7
+ * business's statutory identity", and it records what it was created to end:
8
+ * the legal name, address, GSTIN and support channels had lived in five places
9
+ * that already disagreed — four different support addresses published, the
10
+ * registered address saying Solapur while the warehouse said Hyderabad.
11
+ *
12
+ * But that file belongs to the CONSUMER, and appkit has no runtime reader for
13
+ * it. `resolveSupplierIdentity` therefore read `siteSettings.gst.*` instead,
14
+ * which quietly made the invoice path a SIXTH owner — and the one that decides
15
+ * what a tax invoice says about who issued it.
16
+ *
17
+ * So the consumer injects it at boot, the same way `configureMarketDefaults`
18
+ * injects currency and locale: one call in `providers.config.ts`, values read
19
+ * from `src/constants/business.ts`, which reads `appkit.config.js`. One owner,
20
+ * one hop.
21
+ *
22
+ * 🛑 This is NOT a cache of site settings and must not become one. Whether to
23
+ * charge GST at all stays `siteSettings.gst.enabled` — an operational switch an
24
+ * admin owns. WHO the supplier is is a fact about the registered entity, is
25
+ * legally required to be published, and belongs in a committed file.
26
+ *
27
+ * @tag domain:site-settings
28
+ * @tag layer:shared
29
+ * @tag access:isomorphic
30
+ * @tag sideEffects:module-state
31
+ */
32
+ export interface PlatformSupplierIdentity {
33
+ gstin?: string;
34
+ legalName?: string;
35
+ /** One line, as it should appear in an invoice header. */
36
+ address?: string;
37
+ }
38
+ /**
39
+ * Register the platform's statutory identity. Call once, at boot.
40
+ *
41
+ * Merges rather than replaces, so a partial call cannot blank a field that was
42
+ * already supplied — the same shape `configureMarketDefaults` uses.
43
+ */
44
+ export declare function configurePlatformSupplier(identity: PlatformSupplierIdentity): void;
45
+ /**
46
+ * The registered identity, or an empty object when nothing was injected.
47
+ *
48
+ * 🛑 Returns `{}` rather than throwing, and the caller must treat a missing
49
+ * GSTIN as "not a tax invoice" — which `resolveSupplierIdentity` already does
50
+ * via `source: "none"`. Throwing here would turn a misconfigured deployment
51
+ * into a failed CHECKOUT, and an order that cannot be placed is worse than an
52
+ * invoice that correctly declines to call itself a tax invoice.
53
+ */
54
+ export declare function getPlatformSupplier(): PlatformSupplierIdentity;
55
+ /** Reset — for tests and for the seed CLI's isolated runs. */
56
+ export declare function resetPlatformSupplier(): void;