@mohasinac/appkit 4.62.1 → 4.63.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 (261) hide show
  1. package/dist/.build-stamp.json +3 -3
  2. package/dist/_internal/client/features/layout/DashboardLayoutClient.js +8 -29
  3. package/dist/_internal/client/features/layout/filterNavItems.d.ts +28 -0
  4. package/dist/_internal/client/features/layout/filterNavItems.js +35 -0
  5. package/dist/_internal/server/features/ads/booking.d.ts +118 -0
  6. package/dist/_internal/server/features/ads/booking.js +326 -0
  7. package/dist/_internal/server/features/checkout/actions.d.ts +51 -11
  8. package/dist/_internal/server/features/checkout/actions.js +335 -80
  9. package/dist/_internal/server/features/checkout/expand-order-items.d.ts +1 -2
  10. package/dist/_internal/server/features/checkout/expand-order-items.js +32 -0
  11. package/dist/_internal/server/features/checkout/freeze-parts.d.ts +50 -0
  12. package/dist/_internal/server/features/checkout/freeze-parts.js +94 -0
  13. package/dist/_internal/server/features/checkout/value-otp-gate.d.ts +55 -0
  14. package/dist/_internal/server/features/checkout/value-otp-gate.js +60 -0
  15. package/dist/_internal/server/features/dashboard/attention.d.ts +128 -0
  16. package/dist/_internal/server/features/dashboard/attention.js +183 -0
  17. package/dist/_internal/server/features/dashboard/data.d.ts +47 -0
  18. package/dist/_internal/server/features/dashboard/data.js +82 -0
  19. package/dist/_internal/server/features/inventory/reservations.d.ts +99 -0
  20. package/dist/_internal/server/features/inventory/reservations.js +273 -0
  21. package/dist/_internal/server/features/offers/destinations.d.ts +40 -0
  22. package/dist/_internal/server/features/offers/destinations.js +65 -0
  23. package/dist/_internal/server/features/orders/adapters.js +21 -0
  24. package/dist/_internal/server/features/orders/amend-delivery.d.ts +56 -0
  25. package/dist/_internal/server/features/orders/amend-delivery.js +124 -0
  26. package/dist/_internal/server/features/orders/balance.d.ts +89 -0
  27. package/dist/_internal/server/features/orders/balance.js +256 -0
  28. package/dist/_internal/server/features/pricing/actions.d.ts +58 -0
  29. package/dist/_internal/server/features/pricing/actions.js +144 -0
  30. package/dist/_internal/server/features/shipping/book-split.d.ts +86 -0
  31. package/dist/_internal/server/features/shipping/book-split.js +130 -0
  32. package/dist/_internal/server/features/shipping/book.d.ts +61 -0
  33. package/dist/_internal/server/features/shipping/book.js +176 -0
  34. package/dist/_internal/server/features/shipping/courier-block.js +26 -1
  35. package/dist/_internal/server/features/site-settings/adapters.d.ts +1 -1
  36. package/dist/_internal/server/features/site-settings/adapters.js +14 -0
  37. package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
  38. package/dist/_internal/server/features/stores/adapters.js +14 -0
  39. package/dist/_internal/server/functions/scheduled.d.ts +2 -1
  40. package/dist/_internal/server/functions/scheduled.js +57 -1
  41. package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +2 -0
  42. package/dist/_internal/server/jobs/core/jobRunners.js +45 -0
  43. package/dist/_internal/server/jobs/core/onOrderStatusChange.js +4 -1
  44. package/dist/_internal/server/jobs/core/reservationExpiry.d.ts +17 -0
  45. package/dist/_internal/server/jobs/core/reservationExpiry.js +40 -0
  46. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +15 -0
  47. package/dist/_internal/server/jobs/handlers/index.d.ts +1 -0
  48. package/dist/_internal/server/jobs/handlers/index.js +1 -0
  49. package/dist/_internal/server/jobs/handlers/reservationExpiry.d.ts +2 -0
  50. package/dist/_internal/server/jobs/handlers/reservationExpiry.js +2 -0
  51. package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
  52. package/dist/_internal/shared/actions/action-registry.js +268 -0
  53. package/dist/_internal/shared/checkout/order-math.d.ts +31 -2
  54. package/dist/_internal/shared/checkout/order-math.js +22 -36
  55. package/dist/_internal/shared/checkout/rules/index.d.ts +1 -1
  56. package/dist/_internal/shared/checkout/rules/index.js +1 -1
  57. package/dist/_internal/shared/checkout/rules/payment-gate.d.ts +18 -0
  58. package/dist/_internal/shared/checkout/rules/payment-gate.js +25 -0
  59. package/dist/_internal/shared/checkout/split.d.ts +0 -12
  60. package/dist/_internal/shared/checkout/split.js +22 -2
  61. package/dist/_internal/shared/content/disclaimers.js +7 -7
  62. package/dist/_internal/shared/content/published-values.d.ts +6 -1
  63. package/dist/_internal/shared/content/published-values.js +8 -0
  64. package/dist/_internal/shared/features/admin/integrations.d.ts +32 -2
  65. package/dist/_internal/shared/features/admin/integrations.js +19 -9
  66. package/dist/_internal/shared/features/dashboard/hub-sections.d.ts +72 -0
  67. package/dist/_internal/shared/features/dashboard/hub-sections.js +75 -0
  68. package/dist/_internal/shared/features/emi/choice.d.ts +98 -0
  69. package/dist/_internal/shared/features/emi/choice.js +69 -0
  70. package/dist/_internal/shared/features/emi/group.d.ts +84 -0
  71. package/dist/_internal/shared/features/emi/group.js +126 -0
  72. package/dist/_internal/shared/features/ledger/posting.d.ts +107 -0
  73. package/dist/_internal/shared/features/ledger/posting.js +165 -0
  74. package/dist/_internal/shared/features/ledger/reports.d.ts +76 -0
  75. package/dist/_internal/shared/features/ledger/reports.js +127 -0
  76. package/dist/_internal/shared/features/ledger/rules.d.ts +170 -0
  77. package/dist/_internal/shared/features/ledger/rules.js +221 -0
  78. package/dist/_internal/shared/features/offers/coordination.d.ts +122 -0
  79. package/dist/_internal/shared/features/offers/coordination.js +80 -0
  80. package/dist/_internal/shared/features/orders/delivery-snapshot.d.ts +114 -0
  81. package/dist/_internal/shared/features/orders/delivery-snapshot.js +116 -0
  82. package/dist/_internal/shared/features/payouts/pay-period.d.ts +91 -0
  83. package/dist/_internal/shared/features/payouts/pay-period.js +104 -0
  84. package/dist/_internal/shared/features/points/accepts.d.ts +1 -8
  85. package/dist/_internal/shared/features/points/accepts.js +12 -6
  86. package/dist/_internal/shared/features/pricing/rate-registry.d.ts +150 -0
  87. package/dist/_internal/shared/features/pricing/rate-registry.js +246 -0
  88. package/dist/_internal/shared/features/shipping/parcel.d.ts +123 -0
  89. package/dist/_internal/shared/features/shipping/parcel.js +139 -0
  90. package/dist/_internal/shared/features/site-settings/fees.d.ts +16 -8
  91. package/dist/_internal/shared/features/site-settings/fees.js +12 -8
  92. package/dist/_internal/shared/fees/explain.d.ts +81 -0
  93. package/dist/_internal/shared/fees/explain.js +101 -0
  94. package/dist/_internal/shared/history/index.d.ts +1 -1
  95. package/dist/_internal/shared/history/index.js +1 -1
  96. package/dist/_internal/shared/history/types.d.ts +7 -1
  97. package/dist/_internal/shared/history/types.js +25 -0
  98. package/dist/client.d.ts +11 -1
  99. package/dist/client.js +13 -0
  100. package/dist/constants/api-endpoints.d.ts +72 -0
  101. package/dist/constants/api-endpoints.js +41 -0
  102. package/dist/constants/field-names.d.ts +41 -0
  103. package/dist/constants/field-names.js +47 -0
  104. package/dist/features/account/components/UserOrdersView.js +28 -2
  105. package/dist/features/admin/components/AdminIntegrationsView.d.ts +55 -0
  106. package/dist/features/admin/components/AdminIntegrationsView.js +74 -0
  107. package/dist/features/admin/components/AdminOrderEditorView.d.ts +16 -1
  108. package/dist/features/admin/components/AdminOrderEditorView.js +72 -3
  109. package/dist/features/admin/components/AdminOrdersView.js +20 -1
  110. package/dist/features/admin/schemas/firestore.d.ts +32 -0
  111. package/dist/features/ads/schemas/booking-write.d.ts +120 -0
  112. package/dist/features/ads/schemas/booking-write.js +75 -0
  113. package/dist/features/ads/schemas/creative-form.d.ts +18 -0
  114. package/dist/features/ads/schemas/creative-form.js +51 -0
  115. package/dist/features/ads/schemas/firestore.d.ts +140 -0
  116. package/dist/features/ads/schemas/firestore.js +109 -0
  117. package/dist/features/auctions/repository/bid.repository.js +3 -1
  118. package/dist/features/audit-log/schemas/firestore.d.ts +110 -0
  119. package/dist/features/audit-log/schemas/firestore.js +74 -0
  120. package/dist/features/auth/actions/profile-actions.d.ts +69 -1
  121. package/dist/features/auth/actions/profile-actions.js +62 -1
  122. package/dist/features/auth/schemas/firestore.d.ts +16 -2
  123. package/dist/features/auth/schemas/firestore.js +2 -1
  124. package/dist/features/blog/actions/blog-actions.d.ts +6 -0
  125. package/dist/features/blog/actions/blog-actions.js +17 -2
  126. package/dist/features/blog/api/route.js +4 -1
  127. package/dist/features/blog/columns/index.js +5 -0
  128. package/dist/features/blog/components/BlogIndexPageView.js +2 -1
  129. package/dist/features/blog/repository/blog.repository.d.ts +4 -0
  130. package/dist/features/blog/repository/blog.repository.js +5 -0
  131. package/dist/features/blog/schemas/blog-form.d.ts +3 -0
  132. package/dist/features/blog/schemas/blog-form.js +1 -0
  133. package/dist/features/blog/schemas/firestore.d.ts +38 -1
  134. package/dist/features/blog/schemas/firestore.js +23 -0
  135. package/dist/features/blog/schemas/index.d.ts +6 -0
  136. package/dist/features/blog/schemas/index.js +2 -0
  137. package/dist/features/blog/types/index.d.ts +2 -0
  138. package/dist/features/cart/components/CartPriceBreakdown.d.ts +12 -1
  139. package/dist/features/cart/components/CartPriceBreakdown.js +24 -5
  140. package/dist/features/cart/repository/cart.repository.d.ts +14 -0
  141. package/dist/features/cart/repository/cart.repository.js +20 -0
  142. package/dist/features/cart/schemas/firestore.d.ts +24 -0
  143. package/dist/features/dashboard/components/DashboardHubView.d.ts +83 -0
  144. package/dist/features/dashboard/components/DashboardHubView.js +56 -0
  145. package/dist/features/dashboard/components/DashboardSectionsClient.d.ts +23 -0
  146. package/dist/features/dashboard/components/DashboardSectionsClient.js +66 -0
  147. package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.d.ts +55 -0
  148. package/dist/features/dispute-reasons/components/AdminDisputeReasonsView.js +175 -0
  149. package/dist/features/dispute-reasons/repository/dispute-reasons.repository.d.ts +24 -0
  150. package/dist/features/dispute-reasons/repository/dispute-reasons.repository.js +28 -0
  151. package/dist/features/dispute-reasons/schemas/firestore.d.ts +3 -5
  152. package/dist/features/events/components/EventSaleBanner.js +1 -1
  153. package/dist/features/faq/components/FAQPageContent.js +2 -2
  154. package/dist/features/gateway-events/schemas/index.d.ts +2 -2
  155. package/dist/features/homepage/schemas/index.d.ts +8 -8
  156. package/dist/features/inventory/schemas/stock-reservation.d.ts +114 -0
  157. package/dist/features/inventory/schemas/stock-reservation.js +103 -0
  158. package/dist/features/layout/AppLayoutShell.d.ts +9 -1
  159. package/dist/features/layout/AppLayoutShell.js +12 -4
  160. package/dist/features/layout/BottomActions.js +2 -1
  161. package/dist/features/layout/BottomNavbar.d.ts +10 -2
  162. package/dist/features/layout/SideActionDock.js +52 -2
  163. package/dist/features/layout/TitleBarLayout.js +13 -4
  164. package/dist/features/layout/TitleBarLayout.style.css +59 -0
  165. package/dist/features/layout/useCtaReveal.d.ts +16 -1
  166. package/dist/features/layout/useCtaReveal.js +17 -26
  167. package/dist/features/ledger/repository/journal.repository.d.ts +110 -0
  168. package/dist/features/ledger/repository/journal.repository.js +312 -0
  169. package/dist/features/ledger/schemas/expenses.d.ts +87 -0
  170. package/dist/features/ledger/schemas/expenses.js +27 -0
  171. package/dist/features/ledger/schemas/firestore.d.ts +183 -0
  172. package/dist/features/ledger/schemas/firestore.js +69 -0
  173. package/dist/features/orders/components/BalancePaymentPanel.d.ts +12 -0
  174. package/dist/features/orders/components/BalancePaymentPanel.js +94 -0
  175. package/dist/features/orders/components/RaiseDisputeForm.js +19 -11
  176. package/dist/features/orders/repository/orders.repository.d.ts +28 -1
  177. package/dist/features/orders/repository/orders.repository.js +60 -6
  178. package/dist/features/orders/schemas/balance.d.ts +40 -0
  179. package/dist/features/orders/schemas/balance.js +47 -0
  180. package/dist/features/orders/schemas/firestore.d.ts +202 -0
  181. package/dist/features/orders/schemas/firestore.js +43 -0
  182. package/dist/features/orders/schemas/index.d.ts +2 -2
  183. package/dist/features/orders/types/index.d.ts +21 -0
  184. package/dist/features/payments/repository/payout.repository.js +3 -2
  185. package/dist/features/payments/schemas/firestore.d.ts +92 -1
  186. package/dist/features/payments/schemas/firestore.js +23 -0
  187. package/dist/features/pricing/components/AdminPricingView.d.ts +13 -0
  188. package/dist/features/pricing/components/AdminPricingView.js +157 -0
  189. package/dist/features/products/schemas/firestore.d.ts +26 -1
  190. package/dist/features/products/schemas/firestore.js +2 -0
  191. package/dist/features/products/schemas/index.d.ts +2 -2
  192. package/dist/features/reviews/repository/reviews.repository.d.ts +14 -0
  193. package/dist/features/reviews/repository/reviews.repository.js +16 -0
  194. package/dist/features/scams/repository/scammer.repository.js +2 -1
  195. package/dist/features/scams/schemas/firestore.d.ts +2 -1
  196. package/dist/features/scams/schemas/firestore.js +2 -1
  197. package/dist/features/seller/actions/offer-actions.js +56 -0
  198. package/dist/features/seller/actions/seller-actions.d.ts +1 -1
  199. package/dist/features/seller/actions/seller-actions.js +4 -0
  200. package/dist/features/seller/components/DispatchForm.d.ts +11 -0
  201. package/dist/features/seller/components/DispatchForm.js +190 -0
  202. package/dist/features/seller/components/SellerOrdersView.js +94 -2
  203. package/dist/features/seller/components/index.d.ts +1 -0
  204. package/dist/features/seller/components/index.js +1 -0
  205. package/dist/features/seller/repository/offer.repository.js +4 -3
  206. package/dist/features/seller/schemas/firestore.d.ts +23 -2
  207. package/dist/features/seller/schemas/firestore.js +3 -2
  208. package/dist/features/seller/schemas/index.d.ts +4 -4
  209. package/dist/features/seller/schemas/order-forms.d.ts +61 -4
  210. package/dist/features/seller/schemas/order-forms.js +41 -8
  211. package/dist/features/shipments/schemas/firestore.d.ts +25 -0
  212. package/dist/features/shipping-boxes/repository/shipping-boxes.repository.d.ts +39 -0
  213. package/dist/features/shipping-boxes/repository/shipping-boxes.repository.js +55 -0
  214. package/dist/features/shipping-boxes/schemas/firestore.d.ts +2 -4
  215. package/dist/features/stores/repository/store.repository.d.ts +18 -0
  216. package/dist/features/stores/repository/store.repository.js +27 -1
  217. package/dist/features/stores/schemas/firestore.d.ts +41 -0
  218. package/dist/features/stores/schemas/firestore.js +20 -0
  219. package/dist/features/stores/schemas/index.d.ts +6 -6
  220. package/dist/features/support/repository/support.repository.js +72 -6
  221. package/dist/features/support/schemas/firestore.d.ts +17 -0
  222. package/dist/features/support/schemas/index.d.ts +2 -2
  223. package/dist/index.d.ts +5 -0
  224. package/dist/index.js +19 -0
  225. package/dist/next/routing/route-map.d.ts +92 -0
  226. package/dist/next/routing/route-map.js +53 -0
  227. package/dist/react/contexts/SessionContext.d.ts +17 -1
  228. package/dist/schemas/registry.d.ts +22 -16
  229. package/dist/security/pii-schemas.d.ts +1 -1
  230. package/dist/security/pii-schemas.js +45 -0
  231. package/dist/server.d.ts +27 -1
  232. package/dist/server.js +144 -0
  233. package/dist/styles.css +349 -1
  234. package/dist/tailwind-utilities.css +1 -1
  235. package/dist/ui/components/Button.d.ts +10 -1
  236. package/dist/ui/components/Button.js +25 -3
  237. package/dist/ui/components/Chart.d.ts +63 -0
  238. package/dist/ui/components/Chart.js +169 -0
  239. package/dist/ui/components/Chart.style.css +214 -0
  240. package/dist/ui/components/Disclaimer.js +10 -1
  241. package/dist/ui/components/OverflowRow.js +54 -2
  242. package/dist/ui/components/OverflowRow.style.css +38 -0
  243. package/dist/ui/components/RichTextEditor.js +99 -8
  244. package/dist/ui/components/chart-spec.d.ts +68 -0
  245. package/dist/ui/components/chart-spec.js +140 -0
  246. package/dist/ui/components/index.style.css +1 -0
  247. package/dist/ui/components/surface-tokens.d.ts +1 -1
  248. package/dist/ui/components/surface-tokens.js +9 -0
  249. package/dist/ui/components/toolbar-collapse.d.ts +13 -0
  250. package/dist/ui/components/toolbar-collapse.js +10 -1
  251. package/dist/ui/index.d.ts +6 -0
  252. package/dist/ui/index.js +3 -0
  253. package/dist/ui/rich-text/RichText.d.ts +10 -1
  254. package/dist/ui/rich-text/RichText.js +33 -2
  255. package/dist/ui/rich-text/RichText.style.css +35 -0
  256. package/dist/ui/rich-text/RichTextRenderer.d.ts +30 -1
  257. package/dist/ui/rich-text/RichTextRenderer.js +34 -2
  258. package/dist/ui/rich-text/chart-blocks.d.ts +62 -0
  259. package/dist/ui/rich-text/chart-blocks.js +87 -0
  260. package/package.json +1 -1
  261. package/scripts/seed-cli.mjs +3 -0
@@ -66,6 +66,20 @@ export const PUBLIC_SITE_SETTINGS_FIELDS = [
66
66
  ];
67
67
  /** Everything else, with the reason it stays server-side. */
68
68
  export const PRIVATE_SITE_SETTINGS_FIELDS = [
69
+ /*
70
+ * 🛑 `rateChanges` — the rate-change log behind /admin/pricing.
71
+ *
72
+ * Every entry names an internal rate, who moved it and why. The WHY is the
73
+ * worst of it: a reason reads "undercutting X" or "margin too thin on
74
+ * bundles", which is commercial strategy typed by an admin who was told it
75
+ * was an internal note.
76
+ *
77
+ * Half the rates are already private (`gatewayFeePercent`,
78
+ * `payoutHoldDays`, `minPayoutAmount`), so publishing their history would
79
+ * also publish the values themselves — the current figure is the newest
80
+ * entry's `newValue`.
81
+ */
82
+ "rateChanges",
69
83
  "id", // singleton bookkeeping
70
84
  "createdAt", // bookkeeping
71
85
  "updatedAt", // bookkeeping
@@ -27,7 +27,7 @@ import type { StoreDetail, StoreListItem } from "../../../../features/stores/typ
27
27
  */
28
28
  export declare const PUBLIC_STORE_FIELDS: readonly ["id", "storeSlug", "ownerId", "storeName", "storeDescription", "storeCategory", "storeLogoURL", "storeBannerURL", "status", "isPublic", "stats", "bio", "location", "website", "socialLinks", "returnPolicy", "shippingPolicy", "isVacationMode", "vacationMessage", "supportsShippingProtection", "supportsSaleProtection", "allowSharedPurchase", "sharedPurchaseHandlingFee", "sharedPurchaseExtraShippingPerDestination", "createdAt"];
29
29
  /** Everything else, with the reason it stays server-side. */
30
- export declare const PRIVATE_STORE_FIELDS: readonly ["acceptsPoints", "searchTxt", "updatedAt", "adminNotes", "statusHistory", "statusHistoryTruncated", "isVerified", "suspensionReason", "capabilities", "customCommissionRate", "googleReviews", "shippingConfig", "emiEnabled", "pricesIncludeGst", "shippingPricing", "returnsDirectToSeller", "isFeatured", "vacationReturnDate", "isTestData", "testDataExpiresAt", "gstin", "legalName", "registeredAddress"];
30
+ export declare const PRIVATE_STORE_FIELDS: readonly ["trustedSeller", "acceptsPoints", "searchTxt", "updatedAt", "adminNotes", "statusHistory", "statusHistoryTruncated", "isVerified", "suspensionReason", "capabilities", "customCommissionRate", "googleReviews", "shippingConfig", "emiEnabled", "pricesIncludeGst", "shippingPricing", "returnsDirectToSeller", "isFeatured", "vacationReturnDate", "isTestData", "testDataExpiresAt", "gstin", "legalName", "registeredAddress"];
31
31
  /**
32
32
  * Accepted input: a `StoreDocument` (the common case) or a loosely-typed
33
33
  * Firestore row. The legacy top-level counters below predate `stats` and are
@@ -53,6 +53,20 @@ export const PUBLIC_STORE_FIELDS = [
53
53
  ];
54
54
  /** Everything else, with the reason it stays server-side. */
55
55
  export const PRIVATE_STORE_FIELDS = [
56
+ /*
57
+ * 🛑 `trustedSeller` — OUR RISK POSTURE, not a badge.
58
+ *
59
+ * It means we pay this store before the parcel is delivered, so the platform
60
+ * carries a lost parcel and a non-delivery dispute. That is a statement
61
+ * about what we are willing to lose, and a buyer has no use for it: it says
62
+ * nothing about the goods, the seller's rating or their dispatch record.
63
+ *
64
+ * Published, it would read as an endorsement — "LetItRip trusts this store"
65
+ * — which is both a claim we never made and an incentive for sellers to
66
+ * compete for the flag. It is admin-granted on risk grounds and revocable;
67
+ * neither survives being visible.
68
+ */
69
+ "trustedSeller",
56
70
  /*
57
71
  * 🛑 PRIVATE, and it was briefly classified PUBLIC on a mistaken argument
58
72
  * worth recording so nobody re-makes it.
@@ -5,6 +5,7 @@ export declare const hardBanReinstatement: import("./types").ScheduledFunctionDe
5
5
  export declare const paymentReviewAutoApprove: import("./types").ScheduledFunctionDefinition;
6
6
  export declare const couponExpiry: import("./types").ScheduledFunctionDefinition;
7
7
  export declare const offerExpiry: import("./types").ScheduledFunctionDefinition;
8
+ export declare const reservationExpiry: import("./types").ScheduledFunctionDefinition;
8
9
  export declare const productStatsSync: import("./types").ScheduledFunctionDefinition;
9
10
  export declare const revenueRollup: import("./types").ScheduledFunctionDefinition;
10
11
  export declare const searchIndexBuild: import("./types").ScheduledFunctionDefinition;
@@ -99,4 +100,4 @@ export declare const prizeDrawExpiryReveal: import("./types").ScheduledFunctionD
99
100
  export declare const bundleStockSync: import("./types").ScheduledFunctionDefinition;
100
101
  export declare const emiInstallmentReminder: import("./types").ScheduledFunctionDefinition;
101
102
  export declare const catalogueImageStalenessReminder: import("./types").ScheduledFunctionDefinition;
102
- export declare const SCHEDULED_FUNCTIONS: readonly [import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition];
103
+ export declare const SCHEDULED_FUNCTIONS: readonly [import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition, import("./types").ScheduledFunctionDefinition];
@@ -1,6 +1,6 @@
1
1
  // Scheduled function definitions (Cloud Scheduler triggers).
2
2
  // Cron syntax accepts both Firebase shorthand and standard cron expressions.
3
- import { auctionSettlementHandler, autoPayoutEligibilityHandler, bundleStockSyncHandler, cartPruneHandler, cleanupRtdbEventsHandler, countersReconcileHandler, boxRollupReconcileHandler, couponExpiryHandler, dailyDataCleanupHandler, draftPruneHandler, emiInstallmentReminderHandler, catalogueImageStalenessReminderHandler, mediaTmpCleanupHandler, notificationPruneHandler, offerExpiryHandler, obligationSweepHandler, paymentReconcileHandler, paymentWindowTimeoutHandler, hardBanReinstatementHandler, paymentReviewAutoApproveHandler, pendingOrderTimeoutHandler, positionsReconcileHandler, prizeDrawExpiryRevealHandler, productStatsSyncHandler, revenueRollupHandler, priceIndexRollupHandler, marketPriceRollupHandler, searchIndexBuildHandler, analyticsAlertEvaluateHandler, pageViewRollupHandler, pageViewPruneHandler, dailyStatusDigestHandler, weeklyPayoutEligibilityHandler, testDataCleanupHandler, } from "../jobs/handlers/index.js";
3
+ import { auctionSettlementHandler, autoPayoutEligibilityHandler, bundleStockSyncHandler, cartPruneHandler, cleanupRtdbEventsHandler, countersReconcileHandler, boxRollupReconcileHandler, couponExpiryHandler, dailyDataCleanupHandler, draftPruneHandler, emiInstallmentReminderHandler, catalogueImageStalenessReminderHandler, mediaTmpCleanupHandler, notificationPruneHandler, offerExpiryHandler, reservationExpiryHandler, obligationSweepHandler, paymentReconcileHandler, paymentWindowTimeoutHandler, hardBanReinstatementHandler, paymentReviewAutoApproveHandler, pendingOrderTimeoutHandler, positionsReconcileHandler, prizeDrawExpiryRevealHandler, productStatsSyncHandler, revenueRollupHandler, priceIndexRollupHandler, marketPriceRollupHandler, searchIndexBuildHandler, analyticsAlertEvaluateHandler, pageViewRollupHandler, pageViewPruneHandler, dailyStatusDigestHandler, weeklyPayoutEligibilityHandler, testDataCleanupHandler, } from "../jobs/handlers/index.js";
4
4
  import { defineFunction } from "./define.js";
5
5
  const REGION = "asia-south1";
6
6
  const EVERY_5_MIN = "every 5 minutes";
@@ -54,6 +54,40 @@ export const pendingOrderTimeout = defineFunction({
54
54
  *
55
55
  * Whoever takes the retirement: pick a different host for the retry sweep
56
56
  * first, or keep `paymentWindowTimeout` and retire only the other two.
57
+ *
58
+ * ── 🛑 MEASURED 2026-10-23: RETIRE NEITHER OF THE OTHER TWO EITHER ─────────
59
+ *
60
+ * The paragraph above asks for a measurement rather than an inference —
61
+ * *"whether [`obligationSweep`'s act tier] covers these three is a
62
+ * measurement"* — so here it is. **It does not cover either of them, and the
63
+ * answer is a single predicate.**
64
+ *
65
+ * `OBLIGATION_POLICIES["seller-accept"]` is the only candidate for
66
+ * `pendingOrderTimeout`, and its precondition opens with:
67
+ *
68
+ * precondition: (o) => isPaid(o) && notTerminal(o) && !o.acceptedAt && …
69
+ * duration: { value: 3, unit: "days" }
70
+ *
71
+ * with `const isPaid = (o) => o.paymentStatus === "paid"`. A pending COD order
72
+ * is **not paid** — that is the entire point of COD — so the policy EXCLUDES
73
+ * exactly the orders this sweep exists for, and waits three days where the
74
+ * sweep acts at 24 hours. Pairwise disjoint, which is the same failure shape
75
+ * the obligations collection was built to end (Root Cause #27: three sweeps,
76
+ * pairwise disjoint, an order holding stock forever).
77
+ *
78
+ * `paymentReviewAutoApprove` has no candidate at all. The ONLY policy
79
+ * mentioning `paymentReviewOutcome` is `proof-reupload`, keyed on
80
+ * `=== "reupload_requested"` — the BUYER re-uploading, not staff failing to
81
+ * review. Nothing in the twelve kinds means "a proof nobody looked at".
82
+ *
83
+ * **Retiring them would therefore**: leave unpaid COD orders holding real
84
+ * stock forever, and leave an uploaded proof nobody reviewed in limbo forever.
85
+ * Both silent — an order that is never cancelled raises nothing.
86
+ *
87
+ * So the correct state is THREE sweeps kept, not one. The plan's "retire the
88
+ * other two" was an inference from a coverage claim that measurement does not
89
+ * support, and this note exists so the next reader does not re-derive it from
90
+ * the same plan line.
57
91
  */
58
92
  export const paymentWindowTimeout = defineFunction({
59
93
  name: "paymentWindowTimeout",
@@ -90,6 +124,27 @@ export const offerExpiry = defineFunction({
90
124
  handler: offerExpiryHandler,
91
125
  options: { region: REGION, timeoutSeconds: 120, memory: "256MiB", maxInstances: 1 },
92
126
  });
127
+ /*
128
+ * 🛑 The ONLY bound on a leaked stock hold.
129
+ *
130
+ * Every other way a reservation ends is an action somebody takes; this is
131
+ * what happens when nobody does. Without it a hold is permanent, and a
132
+ * permanent hold is indistinguishable from stock the seller no longer has —
133
+ * with no error anywhere, because a lower `availableQuantity` is just a
134
+ * number.
135
+ *
136
+ * Every 15 minutes rather than daily: the default hold is 72 hours, so the
137
+ * cadence is not about precision, it is about the WORST case. A daily sweep
138
+ * means "expired at 09:01, buyable again tomorrow", and a buyer told an item
139
+ * is sold out for a day after the hold lapsed is the failure this prevents.
140
+ */
141
+ export const reservationExpiry = defineFunction({
142
+ name: "reservationExpiry",
143
+ description: "Expire stock reservations past their TTL and restore availableQuantity (every 15 minutes).",
144
+ trigger: { kind: "schedule", cron: "every 15 minutes" },
145
+ handler: reservationExpiryHandler,
146
+ options: { region: REGION, timeoutSeconds: 300, memory: "256MiB", maxInstances: 1 },
147
+ });
93
148
  export const productStatsSync = defineFunction({
94
149
  name: "productStatsSync",
95
150
  description: "Recompute aggregated product statistics (daily 01:00 UTC).",
@@ -444,6 +499,7 @@ export const SCHEDULED_FUNCTIONS = [
444
499
  paymentReviewAutoApprove,
445
500
  couponExpiry,
446
501
  offerExpiry,
502
+ reservationExpiry,
447
503
  productStatsSync,
448
504
  revenueRollup,
449
505
  priceIndexRollup,
@@ -129,6 +129,8 @@ export async function runAutoPayoutEligibility(ctx) {
129
129
  */
130
130
  ordersPointsBorneByStore(orders.map((o) => o.data)));
131
131
  const payoutInput = {
132
+ /* Every row this job writes settles a SELLER liability. */
133
+ payeeType: "store",
132
134
  storeId,
133
135
  // `displayName` is plaintext by D1; the email fallback must be revealed.
134
136
  sellerName: (seller.displayName ?? sellerPlain.email ?? sellerId),
@@ -14,6 +14,7 @@ import { runResetOtpVerification } from "./resetOtpVerification.js";
14
14
  import { runNewsletterExport } from "./newsletterExport.js";
15
15
  import { runStoreNameBackfill } from "./storeNameBackfill.js";
16
16
  import { runCategoryTaxonomyBackfill } from "./categoryTaxonomyBackfill.js";
17
+ import { bookShipment } from "../../features/shipping/book.js";
17
18
  async function runPayoutsWeeklyJob(_payload, ctx) {
18
19
  const { payoutsCreated, ordersProcessed, payoutIds } = await runWeeklyPayoutEligibility(ctx);
19
20
  return {
@@ -56,7 +57,51 @@ async function runCategoryTaxonomyBackfillJob(payload, ctx) {
56
57
  const kind = payload.kind === "rename" ? "rename" : "reparent";
57
58
  return runCategoryTaxonomyBackfill({ categoryId: String(payload.categoryId ?? ""), kind }, ctx);
58
59
  }
60
+ /**
61
+ * Book a parcel through the platform's carrier account.
62
+ *
63
+ * 🛑 A JOB rather than a synchronous route, and the reason is Rule #6. A
64
+ * booking is an outbound carrier call on a path the seller is waiting on,
65
+ * against a 10s sync-function ceiling — and a timeout there is the worst
66
+ * outcome available: the carrier may have accepted, so retrying double-books
67
+ * and not retrying leaves a parcel nobody collects.
68
+ *
69
+ * The runner's own failure is recoverable: `bookShipment` refuses an order
70
+ * that already has a tracking number, so a retried job is a no-op rather
71
+ * than a second parcel.
72
+ */
73
+ async function runBookShipmentJob(payload, _ctx) {
74
+ const dims = (payload.dimensions ?? {});
75
+ const result = await bookShipment({
76
+ orderId: String(payload.orderId ?? ""),
77
+ pickupAddressId: String(payload.pickupAddressId ?? ""),
78
+ dimensions: {
79
+ weight: Number(dims.weight ?? 0),
80
+ length: Number(dims.length ?? 0),
81
+ width: Number(dims.width ?? 0),
82
+ height: Number(dims.height ?? 0),
83
+ },
84
+ });
85
+ const orderId = String(payload.orderId ?? "");
86
+ return {
87
+ summary: { total: 1, succeeded: 1, skipped: 0, failed: 0 },
88
+ succeeded: [orderId],
89
+ skipped: [],
90
+ failed: [],
91
+ /*
92
+ * The tracking id goes in `data`, which `useBulkEvent` surfaces — the
93
+ * seller's next question after "did it book" is "what is the number",
94
+ * and making them reload the order to find it is a wasted round trip.
95
+ */
96
+ data: {
97
+ trackingId: result.trackingId,
98
+ ...(result.courier ? { courier: result.courier } : {}),
99
+ ...(result.estimatedDelivery ? { estimatedDelivery: result.estimatedDelivery } : {}),
100
+ },
101
+ };
102
+ }
59
103
  export const JOB_RUNNERS = {
104
+ bookShipment: runBookShipmentJob,
60
105
  payoutsWeekly: runPayoutsWeeklyJob,
61
106
  hardBanCascade: runHardBanCascadeJob,
62
107
  resetOtpVerification: runResetOtpVerificationJob,
@@ -1,3 +1,4 @@
1
+ import { normalizeError } from "../../../../errors/normalize.js";
1
2
  import { decryptPii } from "../../../../security/index.js";
2
3
  import { sendNotification } from "../../../../features/admin/actions/notification-actions.js";
3
4
  import { orderRepository } from "../../../../features/orders/repository/orders.repository.js";
@@ -90,7 +91,9 @@ export async function handleOrderStatusChange(input, ctx) {
90
91
  * demand. Throwing here would also make the Firestore trigger retry the
91
92
  * whole handler, re-sending the notification.
92
93
  */
93
- ctx.logger.error("Invoice allocation failed", error, { orderId });
94
+ ctx.logger.error("Invoice allocation failed", normalizeError(error), {
95
+ orderId,
96
+ });
94
97
  }
95
98
  }
96
99
  if (before.status === after.status)
@@ -0,0 +1,17 @@
1
+ import type { JobContext } from "../runtime/types";
2
+ /**
3
+ * Return expired stock holds to the shelf.
4
+ *
5
+ * 🛑 This sweep is the ONLY thing that bounds a leaked hold. Everything else
6
+ * that ends a reservation is an action somebody takes — a release, a
7
+ * consume — and the entire reason `expiresAt` exists is that nobody takes
8
+ * those when they close the tab. Without this job a hold is permanent, and a
9
+ * permanent hold is indistinguishable from stock the seller no longer has.
10
+ *
11
+ * 🛑 Runs every 15 minutes, which is the real resolution of a TTL. The
12
+ * default hold is 72 hours, so the cadence does not need to be tight — but a
13
+ * daily sweep would make the worst case "expires at 09:01, returns tomorrow",
14
+ * and a buyer told an item is sold out for 24 hours after it stopped being
15
+ * held is the failure this exists to prevent.
16
+ */
17
+ export declare function runReservationExpiry(ctx: JobContext): Promise<void>;
@@ -0,0 +1,40 @@
1
+ import { expireDueReservations } from "../../features/inventory/reservations.js";
2
+ import { normalizeError } from "../../../../errors/normalize.js";
3
+ /**
4
+ * Return expired stock holds to the shelf.
5
+ *
6
+ * 🛑 This sweep is the ONLY thing that bounds a leaked hold. Everything else
7
+ * that ends a reservation is an action somebody takes — a release, a
8
+ * consume — and the entire reason `expiresAt` exists is that nobody takes
9
+ * those when they close the tab. Without this job a hold is permanent, and a
10
+ * permanent hold is indistinguishable from stock the seller no longer has.
11
+ *
12
+ * 🛑 Runs every 15 minutes, which is the real resolution of a TTL. The
13
+ * default hold is 72 hours, so the cadence does not need to be tight — but a
14
+ * daily sweep would make the worst case "expires at 09:01, returns tomorrow",
15
+ * and a buyer told an item is sold out for 24 hours after it stopped being
16
+ * held is the failure this exists to prevent.
17
+ */
18
+ export async function runReservationExpiry(ctx) {
19
+ ctx.logger.info("Starting stock-reservation expiry sweep");
20
+ let result;
21
+ try {
22
+ result = await expireDueReservations();
23
+ }
24
+ catch (err) {
25
+ const normalized = normalizeError(err);
26
+ ctx.logger.error("Reservation expiry sweep failed", { message: normalized.message });
27
+ throw err;
28
+ }
29
+ /*
30
+ * `truncated` is logged rather than swallowed, and is the signal that the
31
+ * bound was reached: a run that hits its cap left real holds in place, and
32
+ * reading "expired 200" as "all done" is the same mistake a truncated
33
+ * recount invites (Root Cause #102).
34
+ */
35
+ ctx.logger.info("Reservation expiry sweep complete", {
36
+ scanned: result.scanned,
37
+ expired: result.expired,
38
+ truncated: result.truncated,
39
+ });
40
+ }
@@ -33,8 +33,21 @@ export async function runWeeklyPayoutEligibility(ctx) {
33
33
  holdSource: hold.source,
34
34
  cutoff: cutoff.toISOString(),
35
35
  });
36
+ /*
37
+ * 🛑 Resolved BEFORE the sweep, not per group.
38
+ *
39
+ * The widened query needs the whole set up front — the grouping by store
40
+ * happens after the rows come back, so a per-group lookup would arrive too
41
+ * late to have admitted the shipped rows in the first place. One bounded
42
+ * read against a hand-granted flag.
43
+ */
44
+ const trustedStoreIds = await storeRepository.findTrustedStoreIds();
45
+ if (trustedStoreIds.size > 0) {
46
+ ctx.logger.info(`${trustedStoreIds.size} trusted store(s) — their SHIPPED orders are eligible without waiting for delivery`, { trustedStoreCount: trustedStoreIds.size });
47
+ }
36
48
  const eligible = await orderRepository.getEligibleAutomatic(cutoff, {
37
49
  onWarn: (m, meta) => ctx.logger.warn(m, meta),
50
+ trustedStoreIds,
38
51
  });
39
52
  if (eligible.length === 0) {
40
53
  ctx.logger.info("No eligible delivered orders found");
@@ -93,6 +106,8 @@ export async function runWeeklyPayoutEligibility(ctx) {
93
106
  */
94
107
  const sellerPlain = userRepository.revealUser(seller);
95
108
  const payoutInput = {
109
+ /* Every row this job writes settles a SELLER liability. */
110
+ payeeType: "store",
96
111
  storeId,
97
112
  // `displayName` is plaintext by D1; the email fallback must be revealed.
98
113
  sellerName: (seller.displayName ?? sellerPlain.email ?? store.ownerId),
@@ -9,6 +9,7 @@
9
9
  */
10
10
  export { couponExpiryHandler } from "./couponExpiry";
11
11
  export { offerExpiryHandler } from "./offerExpiry";
12
+ export { reservationExpiryHandler } from "./reservationExpiry";
12
13
  export { cartPruneHandler } from "./cartPrune";
13
14
  export { notificationPruneHandler } from "./notificationPrune";
14
15
  export { dailyDataCleanupHandler } from "./dailyDataCleanup";
@@ -9,6 +9,7 @@
9
9
  */
10
10
  export { couponExpiryHandler } from "./couponExpiry.js";
11
11
  export { offerExpiryHandler } from "./offerExpiry.js";
12
+ export { reservationExpiryHandler } from "./reservationExpiry.js";
12
13
  export { cartPruneHandler } from "./cartPrune.js";
13
14
  export { notificationPruneHandler } from "./notificationPrune.js";
14
15
  export { dailyDataCleanupHandler } from "./dailyDataCleanup.js";
@@ -0,0 +1,2 @@
1
+ import type { ScheduleHandler } from "../runtime/types";
2
+ export declare const reservationExpiryHandler: ScheduleHandler;
@@ -0,0 +1,2 @@
1
+ import { runReservationExpiry } from "../core/reservationExpiry.js";
2
+ export const reservationExpiryHandler = runReservationExpiry;
@@ -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" | "PART" | "BEY" | "FAQ" | "SUBLISTING" | "STORE" | "BLOG" | "EVENT" | "REVIEW" | "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" | "ADS" | "PART" | "BEY" | "FAQ" | "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 {