@mohasinac/appkit 4.52.5 → 4.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (630) hide show
  1. package/dist/.build-stamp.json +4 -4
  2. package/dist/_internal/client/features/sticker-trace/canvas-codec.d.ts +2 -0
  3. package/dist/_internal/client/features/sticker-trace/canvas-codec.js +148 -0
  4. package/dist/_internal/server/features/auctions/actions.js +1 -1
  5. package/dist/_internal/server/features/categories/data.js +23 -7
  6. package/dist/_internal/server/features/checkout/actions.js +10 -3
  7. package/dist/_internal/server/features/checkout/data.d.ts +15 -0
  8. package/dist/_internal/server/features/checkout/data.js +20 -3
  9. package/dist/_internal/server/features/lottery/actions.js +9 -1
  10. package/dist/_internal/server/features/lottery/og.d.ts +40 -0
  11. package/dist/_internal/server/features/lottery/og.js +79 -0
  12. package/dist/_internal/server/features/messages/actions.js +4 -0
  13. package/dist/_internal/server/features/offers/adapters.js +17 -3
  14. package/dist/_internal/server/features/orders/actions.js +7 -2
  15. package/dist/_internal/server/features/raffle/actions.d.ts +19 -0
  16. package/dist/_internal/server/features/raffle/actions.js +25 -0
  17. package/dist/_internal/server/features/reviews/actions.js +1 -1
  18. package/dist/_internal/server/features/reviews/data.d.ts +1 -1
  19. package/dist/_internal/server/features/search/index-build/artifact-store.d.ts +89 -0
  20. package/dist/_internal/server/features/search/index-build/artifact-store.js +208 -0
  21. package/dist/_internal/server/features/search/index-build/build.d.ts +57 -0
  22. package/dist/_internal/server/features/search/index-build/build.js +285 -0
  23. package/dist/_internal/server/features/search/index-build/sources.d.ts +53 -0
  24. package/dist/_internal/server/features/search/index-build/sources.js +385 -0
  25. package/dist/_internal/server/features/search/search-sources.d.ts +0 -15
  26. package/dist/_internal/server/features/search/search-sources.js +142 -7
  27. package/dist/_internal/server/features/seo/robots.js +21 -1
  28. package/dist/_internal/server/features/seo/sitemap.js +1 -1
  29. package/dist/_internal/server/features/shared/listing-data-factory.js +16 -4
  30. package/dist/_internal/server/features/site-settings/adapters.d.ts +1 -1
  31. package/dist/_internal/server/features/site-settings/adapters.js +26 -0
  32. package/dist/_internal/server/features/sticker-trace/actions.d.ts +109 -0
  33. package/dist/_internal/server/features/sticker-trace/actions.js +172 -0
  34. package/dist/_internal/server/features/sticker-trace/adapters.d.ts +80 -0
  35. package/dist/_internal/server/features/sticker-trace/adapters.js +174 -0
  36. package/dist/_internal/server/features/sticker-trace/build-cut-file.d.ts +26 -0
  37. package/dist/_internal/server/features/sticker-trace/build-cut-file.js +127 -0
  38. package/dist/_internal/server/features/sticker-trace/coordinator.d.ts +27 -0
  39. package/dist/_internal/server/features/sticker-trace/coordinator.js +169 -0
  40. package/dist/_internal/server/features/sticker-trace/fanout.d.ts +43 -0
  41. package/dist/_internal/server/features/sticker-trace/fanout.js +180 -0
  42. package/dist/_internal/server/features/sticker-trace/finalizer.d.ts +25 -0
  43. package/dist/_internal/server/features/sticker-trace/finalizer.js +123 -0
  44. package/dist/_internal/server/features/sticker-trace/mosaic-inputs.d.ts +30 -0
  45. package/dist/_internal/server/features/sticker-trace/mosaic-inputs.js +112 -0
  46. package/dist/_internal/server/features/sticker-trace/progress.d.ts +81 -0
  47. package/dist/_internal/server/features/sticker-trace/progress.js +198 -0
  48. package/dist/_internal/server/features/sticker-trace/promote.d.ts +23 -0
  49. package/dist/_internal/server/features/sticker-trace/promote.js +193 -0
  50. package/dist/_internal/server/features/sticker-trace/shard.d.ts +50 -0
  51. package/dist/_internal/server/features/sticker-trace/shard.js +174 -0
  52. package/dist/_internal/server/features/sticker-trace/sheet-actions.d.ts +141 -0
  53. package/dist/_internal/server/features/sticker-trace/sheet-actions.js +279 -0
  54. package/dist/_internal/server/features/sticker-trace/storage.d.ts +135 -0
  55. package/dist/_internal/server/features/sticker-trace/storage.js +282 -0
  56. package/dist/_internal/server/functions/scheduled.d.ts +2 -1
  57. package/dist/_internal/server/functions/scheduled.js +25 -1
  58. package/dist/_internal/server/jobs/core/_event-ref.d.ts +51 -0
  59. package/dist/_internal/server/jobs/core/_event-ref.js +63 -0
  60. package/dist/_internal/server/jobs/core/assignSpinPrize.d.ts +18 -0
  61. package/dist/_internal/server/jobs/core/assignSpinPrize.js +77 -16
  62. package/dist/_internal/server/jobs/core/auctionSettlement.js +13 -4
  63. package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +44 -15
  64. package/dist/_internal/server/jobs/core/bundleStockSync.js +3 -4
  65. package/dist/_internal/server/jobs/core/cleanupRtdbEvents.js +44 -0
  66. package/dist/_internal/server/jobs/core/event-draw-reasons.d.ts +78 -0
  67. package/dist/_internal/server/jobs/core/event-draw-reasons.js +133 -0
  68. package/dist/_internal/server/jobs/core/listingProcessor.js +28 -8
  69. package/dist/_internal/server/jobs/core/onOrderCreate.js +12 -1
  70. package/dist/_internal/server/jobs/core/onScamReportCreate.js +13 -2
  71. package/dist/_internal/server/jobs/core/onScamReportRejected.js +8 -2
  72. package/dist/_internal/server/jobs/core/onScamReportVerified.js +8 -2
  73. package/dist/_internal/server/jobs/core/onStoreWrite.js +11 -4
  74. package/dist/_internal/server/jobs/core/prizeDrawAssignWinner.js +5 -4
  75. package/dist/_internal/server/jobs/core/prizeDrawExpiryReveal.js +1 -4
  76. package/dist/_internal/server/jobs/core/prizeDrawSoldOutReveal.js +1 -2
  77. package/dist/_internal/server/jobs/core/promotions.js +7 -4
  78. package/dist/_internal/server/jobs/core/searchIndexBuild.d.ts +7 -0
  79. package/dist/_internal/server/jobs/core/searchIndexBuild.js +211 -0
  80. package/dist/_internal/server/jobs/core/triggerEventRaffle.d.ts +35 -0
  81. package/dist/_internal/server/jobs/core/triggerEventRaffle.js +213 -31
  82. package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +20 -14
  83. package/dist/_internal/server/jobs/handlers/assignSpinPrize.d.ts +8 -0
  84. package/dist/_internal/server/jobs/handlers/assignSpinPrize.js +15 -15
  85. package/dist/_internal/server/jobs/handlers/index.d.ts +1 -0
  86. package/dist/_internal/server/jobs/handlers/index.js +1 -0
  87. package/dist/_internal/server/jobs/handlers/onCategoryWrite.js +18 -0
  88. package/dist/_internal/server/jobs/handlers/onProductWrite.js +18 -0
  89. package/dist/_internal/server/jobs/handlers/onReviewWrite.js +18 -0
  90. package/dist/_internal/server/jobs/handlers/onScamReportUpdate.js +18 -0
  91. package/dist/_internal/server/jobs/handlers/onStoreWrite.js +18 -0
  92. package/dist/_internal/server/jobs/handlers/searchIndexBuild.d.ts +2 -0
  93. package/dist/_internal/server/jobs/handlers/searchIndexBuild.js +2 -0
  94. package/dist/_internal/server/jobs/handlers/triggerEventRaffle.d.ts +8 -0
  95. package/dist/_internal/server/jobs/handlers/triggerEventRaffle.js +15 -6
  96. package/dist/_internal/shared/actions/action-registry.js +29 -0
  97. package/dist/_internal/shared/cache/revalidate-targets.d.ts +0 -1
  98. package/dist/_internal/shared/cache/revalidate-targets.js +10 -8
  99. package/dist/_internal/shared/features/events/config.d.ts +14 -0
  100. package/dist/_internal/shared/features/events/config.js +14 -0
  101. package/dist/_internal/shared/features/notifications/action-url.js +8 -0
  102. package/dist/_internal/shared/features/site-settings/types.d.ts +11 -0
  103. package/dist/_internal/shared/features/sticker-trace/codec.d.ts +81 -0
  104. package/dist/_internal/shared/features/sticker-trace/codec.js +30 -0
  105. package/dist/_internal/shared/features/sticker-trace/config.d.ts +81 -0
  106. package/dist/_internal/shared/features/sticker-trace/config.js +177 -0
  107. package/dist/_internal/shared/features/sticker-trace/cut-contour.d.ts +20 -0
  108. package/dist/_internal/shared/features/sticker-trace/cut-contour.js +60 -0
  109. package/dist/_internal/shared/features/sticker-trace/export/build-export-set.d.ts +65 -0
  110. package/dist/_internal/shared/features/sticker-trace/export/build-export-set.js +176 -0
  111. package/dist/_internal/shared/features/sticker-trace/export/cut-svg.d.ts +56 -0
  112. package/dist/_internal/shared/features/sticker-trace/export/cut-svg.js +120 -0
  113. package/dist/_internal/shared/features/sticker-trace/export/machine-profiles.d.ts +92 -0
  114. package/dist/_internal/shared/features/sticker-trace/export/machine-profiles.js +153 -0
  115. package/dist/_internal/shared/features/sticker-trace/export/nesting.d.ts +51 -0
  116. package/dist/_internal/shared/features/sticker-trace/export/nesting.js +110 -0
  117. package/dist/_internal/shared/features/sticker-trace/export/page-sizes.d.ts +68 -0
  118. package/dist/_internal/shared/features/sticker-trace/export/page-sizes.js +223 -0
  119. package/dist/_internal/shared/features/sticker-trace/export/part-tiling.d.ts +51 -0
  120. package/dist/_internal/shared/features/sticker-trace/export/part-tiling.js +178 -0
  121. package/dist/_internal/shared/features/sticker-trace/export/simplify-budget.d.ts +26 -0
  122. package/dist/_internal/shared/features/sticker-trace/export/simplify-budget.js +134 -0
  123. package/dist/_internal/shared/features/sticker-trace/export/vectorise-art.d.ts +40 -0
  124. package/dist/_internal/shared/features/sticker-trace/export/vectorise-art.js +195 -0
  125. package/dist/_internal/shared/features/sticker-trace/index.d.ts +2 -0
  126. package/dist/_internal/shared/features/sticker-trace/index.js +59 -0
  127. package/dist/_internal/shared/features/sticker-trace/math/catmull-rom.d.ts +11 -0
  128. package/dist/_internal/shared/features/sticker-trace/math/catmull-rom.js +66 -0
  129. package/dist/_internal/shared/features/sticker-trace/math/edt.d.ts +27 -0
  130. package/dist/_internal/shared/features/sticker-trace/math/edt.js +165 -0
  131. package/dist/_internal/shared/features/sticker-trace/math/label.d.ts +15 -0
  132. package/dist/_internal/shared/features/sticker-trace/math/label.js +156 -0
  133. package/dist/_internal/shared/features/sticker-trace/math/marching-squares.d.ts +16 -0
  134. package/dist/_internal/shared/features/sticker-trace/math/marching-squares.js +242 -0
  135. package/dist/_internal/shared/features/sticker-trace/math/morphology.d.ts +46 -0
  136. package/dist/_internal/shared/features/sticker-trace/math/morphology.js +168 -0
  137. package/dist/_internal/shared/features/sticker-trace/math/rasterize-path.d.ts +88 -0
  138. package/dist/_internal/shared/features/sticker-trace/math/rasterize-path.js +286 -0
  139. package/dist/_internal/shared/features/sticker-trace/math/rdp.d.ts +10 -0
  140. package/dist/_internal/shared/features/sticker-trace/math/rdp.js +74 -0
  141. package/dist/_internal/shared/features/sticker-trace/resume.d.ts +50 -0
  142. package/dist/_internal/shared/features/sticker-trace/resume.js +160 -0
  143. package/dist/_internal/shared/features/sticker-trace/trace/cluster.d.ts +20 -0
  144. package/dist/_internal/shared/features/sticker-trace/trace/cluster.js +132 -0
  145. package/dist/_internal/shared/features/sticker-trace/trace/cross-profile.d.ts +28 -0
  146. package/dist/_internal/shared/features/sticker-trace/trace/cross-profile.js +120 -0
  147. package/dist/_internal/shared/features/sticker-trace/trace/flood.d.ts +21 -0
  148. package/dist/_internal/shared/features/sticker-trace/trace/flood.js +104 -0
  149. package/dist/_internal/shared/features/sticker-trace/trace/geometry.d.ts +3 -0
  150. package/dist/_internal/shared/features/sticker-trace/trace/geometry.js +140 -0
  151. package/dist/_internal/shared/features/sticker-trace/trace/line-filter.d.ts +15 -0
  152. package/dist/_internal/shared/features/sticker-trace/trace/line-filter.js +138 -0
  153. package/dist/_internal/shared/features/sticker-trace/trace/merge.d.ts +27 -0
  154. package/dist/_internal/shared/features/sticker-trace/trace/merge.js +187 -0
  155. package/dist/_internal/shared/features/sticker-trace/trace/paper.d.ts +32 -0
  156. package/dist/_internal/shared/features/sticker-trace/trace/paper.js +147 -0
  157. package/dist/_internal/shared/features/sticker-trace/trace/prefilter.d.ts +30 -0
  158. package/dist/_internal/shared/features/sticker-trace/trace/prefilter.js +125 -0
  159. package/dist/_internal/shared/features/sticker-trace/trace/quantise.d.ts +10 -0
  160. package/dist/_internal/shared/features/sticker-trace/trace/quantise.js +153 -0
  161. package/dist/_internal/shared/features/sticker-trace/trace/ridge.d.ts +88 -0
  162. package/dist/_internal/shared/features/sticker-trace/trace/ridge.js +344 -0
  163. package/dist/_internal/shared/features/sticker-trace/trace/segment.d.ts +10 -0
  164. package/dist/_internal/shared/features/sticker-trace/trace/segment.js +251 -0
  165. package/dist/_internal/shared/features/sticker-trace/types.d.ts +197 -0
  166. package/dist/_internal/shared/features/sticker-trace/types.js +49 -0
  167. package/dist/_internal/shared/listing-types/_registry.d.ts +11 -0
  168. package/dist/_internal/shared/listing-types/art/config.d.ts +1 -0
  169. package/dist/_internal/shared/listing-types/art/config.js +1 -0
  170. package/dist/_internal/shared/listing-types/auction/config.d.ts +1 -0
  171. package/dist/_internal/shared/listing-types/auction/config.js +1 -0
  172. package/dist/_internal/shared/listing-types/classified/config.d.ts +1 -0
  173. package/dist/_internal/shared/listing-types/classified/config.js +1 -0
  174. package/dist/_internal/shared/listing-types/digital-code/config.d.ts +1 -0
  175. package/dist/_internal/shared/listing-types/digital-code/config.js +1 -0
  176. package/dist/_internal/shared/listing-types/feature-flags.d.ts +7 -0
  177. package/dist/_internal/shared/listing-types/feature-flags.js +9 -0
  178. package/dist/_internal/shared/listing-types/live/config.d.ts +1 -0
  179. package/dist/_internal/shared/listing-types/live/config.js +1 -0
  180. package/dist/_internal/shared/listing-types/pre-order/config.d.ts +1 -0
  181. package/dist/_internal/shared/listing-types/pre-order/config.js +1 -0
  182. package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +1 -0
  183. package/dist/_internal/shared/listing-types/prize-draw/config.js +1 -0
  184. package/dist/_internal/shared/listing-types/standard/config.d.ts +1 -0
  185. package/dist/_internal/shared/listing-types/standard/config.js +1 -0
  186. package/dist/_internal/shared/listing-types/stickers/config.d.ts +1 -0
  187. package/dist/_internal/shared/listing-types/stickers/config.js +1 -0
  188. package/dist/_internal/shared/media/limits.d.ts +12 -2
  189. package/dist/_internal/shared/media/limits.js +12 -2
  190. package/dist/_internal/shared/search/artifact-url.d.ts +35 -0
  191. package/dist/_internal/shared/search/artifact-url.js +119 -0
  192. package/dist/_internal/shared/search/index-record.d.ts +68 -0
  193. package/dist/_internal/shared/search/index-record.js +96 -0
  194. package/dist/_internal/shared/search/match.d.ts +65 -0
  195. package/dist/_internal/shared/search/match.js +263 -0
  196. package/dist/client.d.ts +8 -7
  197. package/dist/client.js +12 -5
  198. package/dist/configs/eslint.js +22 -2
  199. package/dist/constants/api-endpoints.d.ts +68 -0
  200. package/dist/constants/api-endpoints.js +32 -0
  201. package/dist/constants/field-names.d.ts +7 -1
  202. package/dist/constants/field-names.js +36 -1
  203. package/dist/contracts/repository.d.ts +8 -7
  204. package/dist/contracts/search.d.ts +2 -2
  205. package/dist/contracts/table.d.ts +3 -3
  206. package/dist/contracts/table.js +3 -3
  207. package/dist/core/contact-submissions.repository.js +2 -2
  208. package/dist/core/integration-keys.js +7 -1
  209. package/dist/core/newsletter.repository.js +2 -2
  210. package/dist/core/site-config.js +1 -1
  211. package/dist/errors/error-codes.d.ts +30 -0
  212. package/dist/errors/error-codes.js +30 -0
  213. package/dist/errors/error-display-map.js +40 -1
  214. package/dist/features/account/api/[userId]/addresses/route.js +1 -1
  215. package/dist/features/account/components/UserBidsView.js +1 -1
  216. package/dist/features/account/components/index.d.ts +0 -8
  217. package/dist/features/account/components/index.js +0 -4
  218. package/dist/features/addresses/repository/addresses.repository.d.ts +17 -6
  219. package/dist/features/addresses/repository/addresses.repository.js +65 -9
  220. package/dist/features/addresses/schemas/firestore.d.ts +17 -6
  221. package/dist/features/admin/actions/notification-actions.js +15 -6
  222. package/dist/features/admin/api/bids/route.js +1 -1
  223. package/dist/features/admin/api/coupons/route.js +1 -1
  224. package/dist/features/admin/api/products/route.js +1 -1
  225. package/dist/features/admin/api/reviews/route.js +1 -1
  226. package/dist/features/admin/components/AdminAdEditorView.js +19 -5
  227. package/dist/features/admin/components/AdminAuditLogView.js +1 -1
  228. package/dist/features/admin/components/AdminBlogEditorView.js +0 -1
  229. package/dist/features/admin/components/AdminBlogView.js +1 -1
  230. package/dist/features/admin/components/AdminBrandsView.js +17 -1
  231. package/dist/features/admin/components/AdminCategoryEditorView.js +0 -1
  232. package/dist/features/admin/components/AdminContactView.js +1 -1
  233. package/dist/features/admin/components/AdminEmployeeEditorView.js +1 -3
  234. package/dist/features/admin/components/AdminNewsletterView.js +1 -1
  235. package/dist/features/admin/components/AdminOrdersView.js +9 -2
  236. package/dist/features/admin/components/AdminPayoutsView.js +1 -1
  237. package/dist/features/admin/components/AdminPrizeDrawsView.js +11 -0
  238. package/dist/features/admin/components/AdminProductEditorView.d.ts +10 -1
  239. package/dist/features/admin/components/AdminProductEditorView.js +24 -37
  240. package/dist/features/admin/components/AdminProductsView.js +10 -3
  241. package/dist/features/admin/components/AdminScammersView.js +1 -1
  242. package/dist/features/admin/components/AdminSectionsView.js +21 -5
  243. package/dist/features/admin/components/AdminSessionsView.js +1 -1
  244. package/dist/features/admin/components/AdminSublistingCategoriesView.js +22 -1
  245. package/dist/features/admin/components/AdminTeamView.js +1 -1
  246. package/dist/features/admin/components/AdminTesterChecklistItemEditorView.js +0 -1
  247. package/dist/features/admin/components/AdminUsersView.js +1 -1
  248. package/dist/features/admin/components/DataListingView.d.ts +2 -1
  249. package/dist/features/admin/components/DataListingView.js +9 -4
  250. package/dist/features/admin/components/analytics/AdminPageViewsReportView.js +0 -2
  251. package/dist/features/admin/hooks/useAdminListing.d.ts +1 -1
  252. package/dist/features/admin/repository/site-settings.repository.js +8 -3
  253. package/dist/features/admin/schemas/firestore.d.ts +62 -1
  254. package/dist/features/admin/schemas/firestore.js +32 -0
  255. package/dist/features/admin/types/index.d.ts +1 -1
  256. package/dist/features/auctions/actions/bid-actions.d.ts +2 -2
  257. package/dist/features/auctions/actions/bid-actions.js +16 -4
  258. package/dist/features/auctions/api/route.js +1 -1
  259. package/dist/features/auctions/components/AuctionBottomActions.js +4 -0
  260. package/dist/features/auctions/repository/bid.repository.d.ts +46 -4
  261. package/dist/features/auctions/repository/bid.repository.js +114 -13
  262. package/dist/features/auctions/schemas/firestore.d.ts +24 -4
  263. package/dist/features/auctions/schemas/firestore.js +1 -0
  264. package/dist/features/auth/actions/profile-actions.js +30 -4
  265. package/dist/features/auth/components/index.d.ts +0 -1
  266. package/dist/features/auth/components/index.js +0 -1
  267. package/dist/features/auth/repository/session.repository.d.ts +17 -3
  268. package/dist/features/auth/repository/session.repository.js +46 -5
  269. package/dist/features/auth/repository/token.repository.d.ts +27 -4
  270. package/dist/features/auth/repository/token.repository.js +65 -11
  271. package/dist/features/auth/repository/user.repository.d.ts +33 -7
  272. package/dist/features/auth/repository/user.repository.js +100 -15
  273. package/dist/features/auth/schemas/firestore.d.ts +63 -12
  274. package/dist/features/auth/schemas/firestore.js +11 -0
  275. package/dist/features/before-after/api/route.js +1 -1
  276. package/dist/features/blog/components/BlogListView.js +16 -3
  277. package/dist/features/blog/components/BlogPostView.js +1 -1
  278. package/dist/features/blog/schemas/index.d.ts +2 -2
  279. package/dist/features/cart/api/route.js +1 -1
  280. package/dist/features/catalogue/repository/catalogue.repository.d.ts +7 -7
  281. package/dist/features/catalogue/repository/catalogue.repository.js +28 -10
  282. package/dist/features/catalogue/schemas/firestore.d.ts +11 -0
  283. package/dist/features/categories/api/route.js +10 -10
  284. package/dist/features/categories/components/CategoryDetailPageView.js +35 -5
  285. package/dist/features/categories/components/CategorySelectorCreate.js +0 -1
  286. package/dist/features/categories/components/index.d.ts +0 -2
  287. package/dist/features/categories/components/index.js +0 -1
  288. package/dist/features/categories/repository/categories.repository.d.ts +1 -0
  289. package/dist/features/categories/repository/categories.repository.js +31 -1
  290. package/dist/features/categories/schemas/index.d.ts +2 -2
  291. package/dist/features/categories/utils/taxonomy-visual.d.ts +21 -0
  292. package/dist/features/categories/utils/taxonomy-visual.js +58 -0
  293. package/dist/features/checkout/actions/checkout-value-otp-actions.js +8 -1
  294. package/dist/features/collections/api/[slug]/route.js +3 -3
  295. package/dist/features/collections/api/route.js +1 -1
  296. package/dist/features/consultation/api/route.js +1 -1
  297. package/dist/features/consultation/repository/consultations.repository.js +1 -1
  298. package/dist/features/consultation/types/index.d.ts +1 -1
  299. package/dist/features/contact/components/ContactForm.js +1 -3
  300. package/dist/features/corporate/api/route.js +1 -1
  301. package/dist/features/corporate/repository/corporate.repository.js +1 -1
  302. package/dist/features/corporate/types/index.d.ts +1 -1
  303. package/dist/features/cron/jobs/auction-expiry.job.js +1 -1
  304. package/dist/features/cron/jobs/preorder-reminder.job.js +1 -1
  305. package/dist/features/events/actions/event-actions.d.ts +14 -0
  306. package/dist/features/events/actions/event-actions.js +82 -3
  307. package/dist/features/events/api/[id]/route.js +2 -2
  308. package/dist/features/events/components/AdminEventEditorView.js +22 -3
  309. package/dist/features/events/components/AdminEventsView.js +32 -8
  310. package/dist/features/events/components/EventRafflesSection.d.ts +34 -1
  311. package/dist/features/events/components/EventRafflesSection.js +52 -3
  312. package/dist/features/events/components/SpinWheelView.d.ts +2 -2
  313. package/dist/features/events/components/SpinWheelView.js +41 -4
  314. package/dist/features/events/repository/event-entry.repository.d.ts +14 -2
  315. package/dist/features/events/repository/event-entry.repository.js +41 -7
  316. package/dist/features/events/schemas/firestore.d.ts +17 -4
  317. package/dist/features/events/types/index.d.ts +37 -0
  318. package/dist/features/faq/repository/faqs.repository.js +1 -1
  319. package/dist/features/faq/schemas/index.d.ts +5 -2
  320. package/dist/features/faq/schemas/index.js +6 -0
  321. package/dist/features/faq/types/index.d.ts +0 -1
  322. package/dist/features/grouped/components/GroupedListingEditorView.js +17 -2
  323. package/dist/features/homepage/api/carousel/[id]/route.js +1 -1
  324. package/dist/features/homepage/api/carousel/route.js +4 -4
  325. package/dist/features/homepage/api/route.js +2 -2
  326. package/dist/features/homepage/api/sections/route.js +1 -1
  327. package/dist/features/homepage/components/AnnouncementBar.d.ts +1 -9
  328. package/dist/features/homepage/components/AnnouncementBar.js +13 -19
  329. package/dist/features/homepage/components/MarketplaceHomepageView.js +6 -1
  330. package/dist/features/homepage/components/index.d.ts +0 -2
  331. package/dist/features/homepage/components/index.js +0 -1
  332. package/dist/features/homepage/repository/homepage.repository.js +1 -1
  333. package/dist/features/homepage/schemas/firestore.d.ts +6 -0
  334. package/dist/features/homepage/schemas/index.d.ts +10 -10
  335. package/dist/features/layout/AppLayoutShell.d.ts +11 -0
  336. package/dist/features/layout/AppLayoutShell.js +64 -12
  337. package/dist/features/layout/BottomActionsContext.d.ts +16 -0
  338. package/dist/features/layout/BottomActionsContext.js +5 -0
  339. package/dist/features/layout/BottomChrome.js +48 -9
  340. package/dist/features/layout/BottomNavbar.d.ts +14 -0
  341. package/dist/features/layout/BottomNavbar.js +43 -3
  342. package/dist/features/layout/MainNavbar.d.ts +11 -0
  343. package/dist/features/layout/NavbarLayout.d.ts +3 -0
  344. package/dist/features/layout/NavbarLayout.js +88 -11
  345. package/dist/features/layout/SideActionDock.d.ts +1 -0
  346. package/dist/features/layout/SideActionDock.js +219 -0
  347. package/dist/features/layout/TitleBarLayout.js +1 -1
  348. package/dist/features/layout/cta-anchor.d.ts +31 -0
  349. package/dist/features/layout/cta-anchor.js +31 -0
  350. package/dist/features/layout/hooks/useBottomActions.d.ts +7 -0
  351. package/dist/features/layout/hooks/useBottomActions.js +6 -1
  352. package/dist/features/layout/index.d.ts +9 -1
  353. package/dist/features/layout/index.js +9 -1
  354. package/dist/features/layout/useCtaReveal.d.ts +24 -0
  355. package/dist/features/layout/useCtaReveal.js +82 -0
  356. package/dist/features/layout/useHoldToOpen.d.ts +41 -0
  357. package/dist/features/layout/useHoldToOpen.js +84 -0
  358. package/dist/features/lottery/repository/lottery-entry.repository.d.ts +18 -3
  359. package/dist/features/lottery/repository/lottery-entry.repository.js +48 -6
  360. package/dist/features/lottery/schemas/firestore.d.ts +33 -5
  361. package/dist/features/loyalty/api/balance/route.js +1 -1
  362. package/dist/features/loyalty/api/history/route.js +1 -1
  363. package/dist/features/media/MediaImage.js +0 -1
  364. package/dist/features/media/MediaPickerModal.js +7 -1
  365. package/dist/features/media/modals/ImageEditor.js +5 -1
  366. package/dist/features/media/modals/VideoThumbnailSelector.js +17 -1
  367. package/dist/features/media/repository/media-assets.repository.d.ts +19 -0
  368. package/dist/features/media/upload/CameraCapture.js +16 -1
  369. package/dist/features/media/upload/ImageUpload.js +42 -4
  370. package/dist/features/media/upload/MediaUploadField.js +69 -13
  371. package/dist/features/media/upload/downscale-image.d.ts +56 -0
  372. package/dist/features/media/upload/downscale-image.js +150 -0
  373. package/dist/features/messages/components/ConversationThreadView.js +45 -2
  374. package/dist/features/messages/components/MessageSellerButton.d.ts +15 -1
  375. package/dist/features/messages/components/MessageSellerButton.js +10 -2
  376. package/dist/features/messages/schemas/firestore.d.ts +15 -0
  377. package/dist/features/orders/hooks/useOrders.js +4 -2
  378. package/dist/features/orders/repository/orders.repository.d.ts +15 -4
  379. package/dist/features/orders/repository/orders.repository.js +52 -20
  380. package/dist/features/orders/schemas/firestore.d.ts +15 -4
  381. package/dist/features/orders/schemas/index.d.ts +8 -8
  382. package/dist/features/orders/types/index.d.ts +2 -2
  383. package/dist/features/payments/repository/payments.repository.js +2 -2
  384. package/dist/features/payments/repository/payout.repository.d.ts +23 -6
  385. package/dist/features/payments/repository/payout.repository.js +63 -23
  386. package/dist/features/payments/repository/saved-payment-methods.repository.d.ts +17 -6
  387. package/dist/features/payments/repository/saved-payment-methods.repository.js +59 -11
  388. package/dist/features/payments/schemas/firestore.d.ts +14 -3
  389. package/dist/features/payments/schemas/saved-methods-firestore.d.ts +12 -1
  390. package/dist/features/pre-orders/api/[slug]/route.js +1 -1
  391. package/dist/features/pre-orders/api/admin/route.js +1 -1
  392. package/dist/features/pre-orders/api/route.js +1 -1
  393. package/dist/features/pre-orders/repository/pre-orders.repository.d.ts +3 -3
  394. package/dist/features/pre-orders/repository/pre-orders.repository.js +6 -6
  395. package/dist/features/products/api/[id]/route.js +1 -1
  396. package/dist/features/products/components/ListingBottomActions.js +4 -0
  397. package/dist/features/products/components/ProductDetailPageView.js +2 -1
  398. package/dist/features/products/components/ProductGalleryClient.js +2 -2
  399. package/dist/features/products/components/ProductGrid.js +12 -1
  400. package/dist/features/products/components/index.d.ts +0 -2
  401. package/dist/features/products/components/index.js +0 -1
  402. package/dist/features/products/config/listing-type-listing-config.d.ts +0 -3
  403. package/dist/features/products/config/listing-type-listing-config.js +27 -2
  404. package/dist/features/products/constants/listing-tabs.d.ts +9 -0
  405. package/dist/features/products/constants/listing-tabs.js +3 -2
  406. package/dist/features/products/hooks/useProducts.js +2 -2
  407. package/dist/features/products/repository/products.repository.js +13 -1
  408. package/dist/features/products/schemas/index.d.ts +2 -2
  409. package/dist/features/products/types/index.d.ts +1 -1
  410. package/dist/features/promotions/api/route.js +1 -1
  411. package/dist/features/reviews/actions/review-actions.d.ts +6 -6
  412. package/dist/features/reviews/actions/review-actions.js +22 -8
  413. package/dist/features/reviews/components/ReviewDetailPageView.js +13 -1
  414. package/dist/features/reviews/components/ReviewsIndexPageView.js +21 -4
  415. package/dist/features/reviews/repository/reviews.repository.d.ts +19 -7
  416. package/dist/features/reviews/repository/reviews.repository.js +63 -12
  417. package/dist/features/reviews/schemas/firestore.d.ts +13 -2
  418. package/dist/features/reviews/schemas/index.d.ts +2 -2
  419. package/dist/features/scams/actions/scam-actions.js +16 -4
  420. package/dist/features/search/components/SearchResultsPageView.js +2 -1
  421. package/dist/features/search/hooks/useSearchIndex.d.ts +34 -0
  422. package/dist/features/search/hooks/useSearchIndex.js +172 -0
  423. package/dist/features/search/repository/search.repository.js +2 -2
  424. package/dist/features/seller/actions/offer-actions.d.ts +5 -5
  425. package/dist/features/seller/actions/offer-actions.js +38 -8
  426. package/dist/features/seller/actions/seller-actions.js +34 -7
  427. package/dist/features/seller/api/coupons/route.js +1 -1
  428. package/dist/features/seller/api/products/route.js +1 -1
  429. package/dist/features/seller/api/store/route.js +1 -1
  430. package/dist/features/seller/components/SellerBidsView.js +1 -1
  431. package/dist/features/seller/components/SellerCouponsView.js +1 -1
  432. package/dist/features/seller/components/SellerListingTypeView.js +9 -1
  433. package/dist/features/seller/components/SellerOrdersView.js +1 -1
  434. package/dist/features/seller/components/SellerPayoutSettingsView.js +0 -1
  435. package/dist/features/seller/components/SellerPayoutsView.js +1 -1
  436. package/dist/features/seller/components/SellerProductShell.js +0 -1
  437. package/dist/features/seller/components/SellerProductsView.js +1 -1
  438. package/dist/features/seller/components/SellerShippingView.js +0 -1
  439. package/dist/features/seller/components/SellerStorefrontView.js +0 -1
  440. package/dist/features/seller/components/index.d.ts +0 -4
  441. package/dist/features/seller/components/index.js +0 -2
  442. package/dist/features/seller/repository/offer.repository.d.ts +15 -3
  443. package/dist/features/seller/repository/offer.repository.js +43 -7
  444. package/dist/features/seller/schemas/firestore.d.ts +14 -3
  445. package/dist/features/seller/schemas/index.d.ts +4 -4
  446. package/dist/features/seller/schemas/order-forms.d.ts +39 -0
  447. package/dist/features/seller/schemas/order-forms.js +37 -0
  448. package/dist/features/shell/FormShell.js +6 -2
  449. package/dist/features/shell/QuickFormDrawer.js +15 -1
  450. package/dist/features/shipments/components/AdminShipmentEditorView.js +0 -1
  451. package/dist/features/shipments/components/AdminShipmentsView.js +1 -1
  452. package/dist/features/sticker-trace/components/StickerCommitPanel.d.ts +30 -0
  453. package/dist/features/sticker-trace/components/StickerCommitPanel.js +93 -0
  454. package/dist/features/sticker-trace/components/StickerPrintPanel.d.ts +33 -0
  455. package/dist/features/sticker-trace/components/StickerPrintPanel.js +104 -0
  456. package/dist/features/sticker-trace/components/StickerRetryPanel.d.ts +20 -0
  457. package/dist/features/sticker-trace/components/StickerRetryPanel.js +128 -0
  458. package/dist/features/sticker-trace/components/StickerRunHistoryPanel.d.ts +45 -0
  459. package/dist/features/sticker-trace/components/StickerRunHistoryPanel.js +84 -0
  460. package/dist/features/sticker-trace/components/StickerTraceStudio.d.ts +27 -0
  461. package/dist/features/sticker-trace/components/StickerTraceStudio.js +171 -0
  462. package/dist/features/sticker-trace/constants/help-content.d.ts +23 -0
  463. package/dist/features/sticker-trace/constants/help-content.js +172 -0
  464. package/dist/features/sticker-trace/hooks/useLiveTrace.d.ts +27 -0
  465. package/dist/features/sticker-trace/hooks/useLiveTrace.js +160 -0
  466. package/dist/features/sticker-trace/hooks/useStickerTraceProgress.d.ts +22 -0
  467. package/dist/features/sticker-trace/hooks/useStickerTraceProgress.js +106 -0
  468. package/dist/features/sticker-trace/repository/sticker-sheets.repository.d.ts +113 -0
  469. package/dist/features/sticker-trace/repository/sticker-sheets.repository.js +146 -0
  470. package/dist/features/sticker-trace/repository/sticker-trace-runs.repository.d.ts +132 -0
  471. package/dist/features/sticker-trace/repository/sticker-trace-runs.repository.js +174 -0
  472. package/dist/features/sticker-trace/schemas/firestore.d.ts +248 -0
  473. package/dist/features/sticker-trace/schemas/firestore.js +79 -0
  474. package/dist/features/sticker-trace/server.d.ts +8 -0
  475. package/dist/features/sticker-trace/server.js +51 -0
  476. package/dist/features/stores/actions/store-query-actions.d.ts +2 -2
  477. package/dist/features/stores/actions/store-query-actions.js +7 -2
  478. package/dist/features/stores/api/[storeSlug]/auctions/route.js +3 -3
  479. package/dist/features/stores/api/[storeSlug]/products/route.js +3 -3
  480. package/dist/features/stores/api/[storeSlug]/reviews/route.js +1 -1
  481. package/dist/features/stores/api/[storeSlug]/route.js +1 -1
  482. package/dist/features/stores/components/StoreNavTabs.js +17 -2
  483. package/dist/features/stores/manifest.js +8 -4
  484. package/dist/features/support/repository/support.repository.d.ts +14 -3
  485. package/dist/features/support/repository/support.repository.js +93 -13
  486. package/dist/features/support/schemas/firestore.d.ts +16 -5
  487. package/dist/features/tester/seed-data/authored/admin__events-raffles-spin.js +61 -19
  488. package/dist/features/tester/seed-data/authored/buying__browsing-search.js +19 -3
  489. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.d.ts +2 -0
  490. package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.js +243 -0
  491. package/dist/features/tester/seed-data/authored/content-discovery__events.js +36 -10
  492. package/dist/features/tester/seed-data/authored/content-discovery__overflowing-pill-rows.d.ts +2 -0
  493. package/dist/features/tester/seed-data/authored/content-discovery__overflowing-pill-rows.js +209 -0
  494. package/dist/features/tester/seed-data/authored/design-ux__header-brand-mark-centring.d.ts +2 -0
  495. package/dist/features/tester/seed-data/authored/design-ux__header-brand-mark-centring.js +90 -0
  496. package/dist/features/tester/seed-data/authored/index.js +8 -0
  497. package/dist/features/tester/seed-data/authored/selling__media-limits.js +19 -17
  498. package/dist/features/tester/seed-data/authored/selling__product-upload-details.js +10 -5
  499. package/dist/features/tester/seed-data/authored/tools__sticker-tracer.d.ts +2 -0
  500. package/dist/features/tester/seed-data/authored/tools__sticker-tracer.js +283 -0
  501. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +192 -22
  502. package/dist/index.d.ts +10 -23
  503. package/dist/index.js +27 -19
  504. package/dist/next/api/routeHandler.js +9 -0
  505. package/dist/next/routing/require-record.d.ts +13 -0
  506. package/dist/next/routing/require-record.js +62 -0
  507. package/dist/next/routing/route-map.d.ts +4 -4
  508. package/dist/next/routing/route-map.js +25 -3
  509. package/dist/providers/db-firebase/base.d.ts +4 -2
  510. package/dist/providers/db-firebase/base.js +21 -5
  511. package/dist/providers/db-firebase/base.repository.d.ts +11 -9
  512. package/dist/providers/db-firebase/base.repository.js +19 -0
  513. package/dist/providers/db-firebase/rtdb-paths.d.ts +12 -0
  514. package/dist/providers/db-firebase/rtdb-paths.js +12 -0
  515. package/dist/react/ErrorBoundary.js +6 -1
  516. package/dist/react/hooks/realtime-event-constants.d.ts +1 -0
  517. package/dist/react/hooks/realtime-event-constants.js +8 -0
  518. package/dist/react/hooks/useEntityDelete.js +5 -1
  519. package/dist/react/hooks/useMessage.js +5 -1
  520. package/dist/repositories/index.d.ts +2 -2
  521. package/dist/repositories/index.js +6 -1
  522. package/dist/schemas/registry.d.ts +13 -20
  523. package/dist/schemas/registry.js +31 -14
  524. package/dist/schemas/webhooks/google-oauth.d.ts +2 -2
  525. package/dist/security/encrypted.d.ts +117 -0
  526. package/dist/security/encrypted.js +100 -0
  527. package/dist/security/index.d.ts +5 -2
  528. package/dist/security/index.js +16 -2
  529. package/dist/security/pii-accessors.d.ts +71 -0
  530. package/dist/security/pii-accessors.js +150 -0
  531. package/dist/security/pii-encrypt.d.ts +0 -8
  532. package/dist/security/pii-encrypt.js +22 -15
  533. package/dist/security/pii-mask.d.ts +18 -0
  534. package/dist/security/pii-mask.js +27 -0
  535. package/dist/seed/_helpers/search-txt-wrappers.d.ts +6 -6
  536. package/dist/seed/_helpers/search-txt-wrappers.js +22 -0
  537. package/dist/seed/addresses-seed-data.d.ts +2 -2
  538. package/dist/seed/authenticity-knowledge-seed-data.d.ts +34 -0
  539. package/dist/seed/authenticity-knowledge-seed-data.js +1277 -0
  540. package/dist/seed/bids-seed-data.d.ts +2 -2
  541. package/dist/seed/bids-seed-data.js +23 -2
  542. package/dist/seed/events-seed-data.d.ts +2 -2
  543. package/dist/seed/events-seed-data.js +5 -0
  544. package/dist/seed/faq-seed-data.js +175 -5
  545. package/dist/seed/homepage-sections-seed-data.js +39 -23
  546. package/dist/seed/index.d.ts +1 -0
  547. package/dist/seed/index.js +1 -0
  548. package/dist/seed/lottery-entries-seed-data.d.ts +2 -2
  549. package/dist/seed/offers-seed-data.d.ts +2 -2
  550. package/dist/seed/offers-seed-data.js +1 -1
  551. package/dist/seed/orders-seed-data.d.ts +2 -2
  552. package/dist/seed/payouts-seed-data.d.ts +2 -2
  553. package/dist/seed/payouts-seed-data.js +1 -1
  554. package/dist/seed/reviews-seed-data.d.ts +1 -2
  555. package/dist/seed/seed-purpose.js +7 -0
  556. package/dist/seed/sessions-seed-data.d.ts +2 -2
  557. package/dist/seed/sessions-seed-data.js +5 -0
  558. package/dist/seed/site-settings-seed-data.js +1 -1
  559. package/dist/seed/support-tickets-seed-data.d.ts +2 -2
  560. package/dist/seed/support-tickets-seed-data.js +1 -1
  561. package/dist/seed/users-seed-data.d.ts +2 -2
  562. package/dist/seed/users-seed-data.js +1 -1
  563. package/dist/seo/json-ld.js +5 -1
  564. package/dist/server.d.ts +18 -3
  565. package/dist/server.js +59 -3
  566. package/dist/styles.css +237 -1
  567. package/dist/tailwind-utilities.css +1 -1
  568. package/dist/ui/components/Button.js +7 -1
  569. package/dist/ui/components/FilterChipGroup.d.ts +11 -0
  570. package/dist/ui/components/FilterChipGroup.js +1 -1
  571. package/dist/ui/components/ImageGallery.js +6 -1
  572. package/dist/ui/components/ListingLayout.js +14 -8
  573. package/dist/ui/components/OverflowRow.d.ts +92 -0
  574. package/dist/ui/components/OverflowRow.js +203 -0
  575. package/dist/ui/components/OverflowRow.style.css +235 -0
  576. package/dist/ui/components/RecordDetailModal.js +14 -1
  577. package/dist/ui/components/RowActionMenu.js +5 -1
  578. package/dist/ui/components/SideDrawer.js +5 -1
  579. package/dist/ui/components/SideModal.js +9 -1
  580. package/dist/ui/components/TabBarShell.d.ts +12 -1
  581. package/dist/ui/components/TabBarShell.js +3 -2
  582. package/dist/ui/components/Tabs.js +36 -24
  583. package/dist/ui/components/Toast.d.ts +3 -24
  584. package/dist/ui/components/Toast.js +2 -19
  585. package/dist/ui/components/TopBannerPortal.d.ts +15 -0
  586. package/dist/ui/components/TopBannerPortal.js +19 -0
  587. package/dist/ui/components/UnsavedChangesModal.js +5 -1
  588. package/dist/ui/components/index.style.css +1 -0
  589. package/dist/ui/components/row-collapse.d.ts +15 -0
  590. package/dist/ui/components/row-collapse.js +127 -0
  591. package/dist/ui/components/toast-context.d.ts +63 -0
  592. package/dist/ui/components/toast-context.js +48 -0
  593. package/dist/ui/components/top-banner-slot.d.ts +37 -0
  594. package/dist/ui/components/top-banner-slot.js +45 -0
  595. package/dist/ui/icons/icon-registry.d.ts +6 -0
  596. package/dist/ui/icons/icon-registry.js +17 -1
  597. package/dist/ui/index.d.ts +2 -0
  598. package/dist/ui/index.js +1 -0
  599. package/dist/utils/array.helper.d.ts +2 -2
  600. package/dist/utils/array.helper.js +5 -5
  601. package/dist/utils/id-generators.d.ts +6 -0
  602. package/dist/utils/id-generators.js +10 -0
  603. package/dist/utils/media-url.js +0 -2
  604. package/dist/utils/search-txt-builders.d.ts +28 -4
  605. package/dist/utils/search-txt-builders.js +41 -1
  606. package/dist/validation/schemas.d.ts +8 -8
  607. package/package.json +6 -2
  608. package/scripts/seed-cli.mjs +3 -0
  609. package/dist/features/account/components/UserAddressesView.d.ts +0 -13
  610. package/dist/features/account/components/UserAddressesView.js +0 -5
  611. package/dist/features/account/components/UserNotificationsView.d.ts +0 -15
  612. package/dist/features/account/components/UserNotificationsView.js +0 -12
  613. package/dist/features/account/components/UserSettingsView.d.ts +0 -16
  614. package/dist/features/account/components/UserSettingsView.js +0 -13
  615. package/dist/features/account/components/UserSupportView.d.ts +0 -3
  616. package/dist/features/account/components/UserSupportView.js +0 -166
  617. package/dist/features/admin/components/DemoSeedView.d.ts +0 -11
  618. package/dist/features/admin/components/DemoSeedView.js +0 -5
  619. package/dist/features/auth/components/AuthStatusPanel.d.ts +0 -10
  620. package/dist/features/auth/components/AuthStatusPanel.js +0 -22
  621. package/dist/features/categories/components/CategoryProductsView.d.ts +0 -45
  622. package/dist/features/categories/components/CategoryProductsView.js +0 -21
  623. package/dist/features/homepage/components/HowItWorksInfoView.d.ts +0 -36
  624. package/dist/features/homepage/components/HowItWorksInfoView.js +0 -10
  625. package/dist/features/layout/BottomActions.d.ts +0 -1
  626. package/dist/features/layout/BottomActions.js +0 -311
  627. package/dist/features/products/components/ProductsView.d.ts +0 -6
  628. package/dist/features/products/components/ProductsView.js +0 -5
  629. package/dist/features/seller/components/SellerStoreView.d.ts +0 -8
  630. package/dist/features/seller/components/SellerStoreView.js +0 -8
@@ -0,0 +1,283 @@
1
+ /*
2
+ * WHY: Authored six-part procedures for the sticker-sheet kiss-cut tracer.
3
+ * WHAT: 16 case(s), keyed by full checklist id.
4
+ *
5
+ * 🛑 EVERY CASE IS AN EXPLICIT BEFORE → AFTER, because almost every defect this
6
+ * feature can have returns HTTP 200 with plausible content. A case reading
7
+ * "check the tracer works" would pass against the bug. The first three restate
8
+ * the two failures that caused this feature to be built, as assertions.
9
+ *
10
+ * 🛑 THE FIXTURE IS /test-media/sticker-sheet-fixture.jpg AND ITS SIZE IS
11
+ * LOAD-BEARING. It is the real 5024x3024 scan, and shrinking it was measured
12
+ * and rejected: a 145 KB WebP traces into 237 fragments where the original
13
+ * gives 15 (public/test-media/README.md carries the table). A case asserting a
14
+ * part count against a shrunken fixture would fail for a reason that is not a
15
+ * bug. Do not "optimise" it.
16
+ *
17
+ * 🛑 PART COUNTS ARE DELIBERATELY NOT ASSERTED AS EXACT NUMBERS. The probe
18
+ * measured 15 at draft tier on this machine, but the count moves with tier and
19
+ * with any tuning of the ridge thresholds — so the cases assert RELATIONS
20
+ * ("more than one", "the same count twice", "fewer after raising the minimum")
21
+ * which stay true across tuning. An exact number here would be a case that
22
+ * fails every time somebody improves the detector.
23
+ *
24
+ * 🛑 The tracer is ADMIN-ONLY and /tools/sticker-tracer is server-gated, so the
25
+ * buyer and guest cases assert the redirect rather than a hidden control.
26
+ *
27
+ * @tag domain:tester
28
+ * @tag layer:seed
29
+ * @tag pattern:none
30
+ * @tag access:server-only
31
+ * @tag consumers:seed-data/authored/index.ts
32
+ * @tag sideEffects:none
33
+ */
34
+ const ADMIN_SIGNIN = "Sign in as admin@letitrip.in / TempPass123!.";
35
+ const FIXTURE = "/test-media/sticker-sheet-fixture.jpg";
36
+ export const authored = {
37
+ /* ---- the two reported failures, restated as assertions ---------------- */
38
+ "checklist-tools-sticker-tracer-enclosed-region-opaque": {
39
+ roles: ["admin"],
40
+ startPage: "/tools/sticker-tracer",
41
+ steps: [
42
+ ADMIN_SIGNIN,
43
+ `Download ${FIXTURE} and choose it with "Choose a scan".`,
44
+ "Wait for the outlines to draw over the preview.",
45
+ "Find a sticker that contains an enclosed area the same colour as the paper around the sheet — on the Driger G sheet the lighter interior panels.",
46
+ "Zoom the browser to 200% and look at whether that interior area is covered by the outline or cut out of it.",
47
+ ],
48
+ expectedBehaviour: "Opacity is decided by REACHABILITY from the sheet border, not by colour. The flood fills inward from the edge and a sticker is whatever the flood could not reach — so an enclosed region is inside the outline no matter what colour it is.",
49
+ expectedUiState: "The magenta outline runs around the sticker's silhouette only. It does not loop around interior light-coloured areas, and no interior region is excluded from the shape.",
50
+ endResult: "BEFORE: the prior Python attempt thresholded colour, so a region matching the background was made transparent even inside a sticker. AFTER: interior regions stay part of the sticker. Nothing is persisted — this is the in-browser tuner.",
51
+ },
52
+ "checklist-tools-sticker-tracer-white-on-white-edge": {
53
+ roles: ["admin"],
54
+ startPage: "/tools/sticker-tracer",
55
+ steps: [
56
+ ADMIN_SIGNIN,
57
+ `Choose ${FIXTURE}.`,
58
+ "Find the winder sticker — the one whose top edge is near-white against the near-white paper.",
59
+ "Zoom to 200% and check whether that top edge carries an outline.",
60
+ "Read the Result card's part count.",
61
+ ],
62
+ expectedBehaviour: "The cut line is found from the EMBOSS RIDGE, which the plan measured at 10-20x above noise precisely where colour carries none. No per-sticker parameter is involved.",
63
+ expectedUiState: "The white top edge has a magenta outline following it. The Result card shows more than one part.",
64
+ endResult: "BEFORE: a colour threshold ate that edge, and the old script needed a hand-authored --cap flag naming one sticker's coordinates on one sheet. AFTER: it is found with the default parameters and no per-sticker tuning.",
65
+ },
66
+ "checklist-tools-sticker-tracer-background-model-named": {
67
+ roles: ["admin"],
68
+ startPage: "/tools/sticker-tracer",
69
+ steps: [
70
+ ADMIN_SIGNIN,
71
+ `Choose ${FIXTURE}.`,
72
+ "Read the line under the Result heading that begins 'background:'.",
73
+ "Change 'Paper tolerance' from its default to 60 and watch the part count.",
74
+ "Set it back to its default.",
75
+ ],
76
+ expectedBehaviour: "The tool states which of the two segmentation models ran. Paper floods inward from the sheet edge; art partitions on cut lines because there is no background to flood. Paper tolerance only affects the paper model, which is why knowing which ran is the difference between a parameter that does nothing and one that is simply set wrong.",
77
+ expectedUiState: "The Result card reads 'background: paper' for this scan. Changing Paper tolerance changes the part count.",
78
+ endResult: "BEFORE: there was no way to tell which model ran, so an operator adjusting paper tolerance on an art sheet saw no effect and no explanation. AFTER: the model is named on screen.",
79
+ },
80
+ /* ---- the mandatory name ---------------------------------------------- */
81
+ "checklist-tools-sticker-tracer-name-required": {
82
+ roles: ["admin"],
83
+ startPage: "/tools/sticker-tracer",
84
+ steps: [
85
+ ADMIN_SIGNIN,
86
+ `Choose ${FIXTURE} and scroll to "Commit this as a run".`,
87
+ "Leave 'Name this sheet' EMPTY and try to press 'Upload and run'.",
88
+ "Type a single space into the name and try again.",
89
+ "Type 'QA tracer run 1' and press 'Upload and run'.",
90
+ ],
91
+ inputs: { name: "QA tracer run 1" },
92
+ expectedBehaviour: "A name is mandatory and is enforced in three places — the disabled button, the route's schema, and requireName in the action. No sheet document and no Storage object is created while the name is empty.",
93
+ expectedUiState: "'Upload and run' is disabled with the name empty and with a single space. It enables once real text is entered, then reads 'Uploading and starting…'.",
94
+ expectedData: { sheetsCreatedWhileNameEmpty: 0 },
95
+ endResult: "BEFORE: nothing stopped an unnamed attempt, and the whole point of keeping every run is being able to tell them apart later. AFTER: a run cannot exist without a name. The named run persists and appears under Attempts after a reload.",
96
+ },
97
+ /* ---- watermark + originals ------------------------------------------- */
98
+ "checklist-tools-sticker-tracer-no-watermark-on-original": {
99
+ roles: ["admin"],
100
+ startPage: "/tools/sticker-tracer",
101
+ steps: [
102
+ ADMIN_SIGNIN,
103
+ "Open a sheet whose run has finished and been accepted.",
104
+ "In Attempts, press 'Preview' on the accepted run — it opens a new tab.",
105
+ "Look at the opened image for a watermark, and copy its URL.",
106
+ "Check the URL's host: it should be a storage.googleapis.com signed link, NOT a /media/ path on this site.",
107
+ ],
108
+ expectedBehaviour: "Tracer artifacts live under private/sticker-sheets/ and are served by 5-minute signed GCS URLs, which bypass /api/media/[...slug] — the proxy that always watermarks. The printable original must stay clean or the cut-out is ruined.",
109
+ expectedUiState: "The opened image carries NO watermark. Its URL is on storage.googleapis.com with query parameters, not /media/<slug>.",
110
+ endResult: "BEFORE: every image through the media proxy was watermarked, which would ruin a cut-out and the printed mosaic. AFTER: originals are unwatermarked and reachable only through a short-lived signed link.",
111
+ },
112
+ /* ---- live progress ---------------------------------------------------- */
113
+ "checklist-tools-sticker-tracer-progress-names-stage": {
114
+ roles: ["admin"],
115
+ startPage: "/tools/sticker-tracer",
116
+ steps: [
117
+ ADMIN_SIGNIN,
118
+ `Choose ${FIXTURE}, name the run 'QA progress', pick tier Standard and press 'Upload and run'.`,
119
+ "Watch the card titled 'Running' without reloading.",
120
+ "Write down two different stage names you see.",
121
+ ],
122
+ expectedBehaviour: "Progress is pushed over the run's own RTDB channel, not polled. The label names the STAGE because that is what distinguishes a halftone scan stuck in the detector from one stuck in the upload.",
123
+ expectedUiState: "A 'Running' card shows text like 'ridge 22%' or 'parts 4/15' and ADVANCES. It is never a bare spinner and never only a percentage.",
124
+ endResult: "BEFORE: a trace took minutes with nothing to look at. AFTER: the current stage is visible throughout. The card disappears when the run ends; the outcome persists in Attempts.",
125
+ },
126
+ "checklist-tools-sticker-tracer-failure-names-stage": {
127
+ roles: ["admin"],
128
+ startPage: "/tools/sticker-tracer",
129
+ steps: [
130
+ ADMIN_SIGNIN,
131
+ "Find a sheet with a FAILED run in Attempts. If none exists, create one: commit a run with 'Minimum part area' set to 100000, which leaves nothing above the threshold.",
132
+ "Read the failed row.",
133
+ "Reload the page and read it again.",
134
+ ],
135
+ inputs: { minPartAreaMm2: 100000 },
136
+ expectedBehaviour: "A failure records the stage it died in and a user-safe message, and the row survives. The requirement was 'even if we fail we know'.",
137
+ expectedUiState: "The row shows a red 'failed' badge and a line beginning 'Failed at <stage>' with a readable message — never 'Something went wrong', and never a raw server error or a stack trace.",
138
+ endResult: "BEFORE: a failed trace was indistinguishable from a hang. AFTER: the stage is named and the failed attempt stays in history after a reload.",
139
+ },
140
+ /* ---- history ---------------------------------------------------------- */
141
+ "checklist-tools-sticker-tracer-runs-never-overwrite": {
142
+ roles: ["admin"],
143
+ startPage: "/tools/sticker-tracer",
144
+ steps: [
145
+ ADMIN_SIGNIN,
146
+ `Choose ${FIXTURE}, name the run 'QA attempt A', tier Standard, and commit it.`,
147
+ "Wait for it to finish.",
148
+ "Commit a SECOND run on the same sheet named 'QA attempt B' at tier Precise.",
149
+ "Reload the page and read the Attempts list.",
150
+ ],
151
+ inputs: { runA: "QA attempt A", runB: "QA attempt B" },
152
+ expectedBehaviour: "A retry or a second run creates a NEW run document. Nothing overwrites an earlier attempt, which is what makes comparing tiers on one sheet possible weeks later.",
153
+ expectedUiState: "Both 'QA attempt A' and 'QA attempt B' appear, newest first, each with its own tier label and its own part count. Both are still openable.",
154
+ endResult: "BEFORE: there was nothing listing runs at all — the documents existed with no reader. AFTER: every attempt is listed by the name that was typed, and both survive a reload.",
155
+ },
156
+ "checklist-tools-sticker-tracer-accepted-differs-from-succeeded": {
157
+ roles: ["admin"],
158
+ startPage: "/tools/sticker-tracer",
159
+ steps: [
160
+ ADMIN_SIGNIN,
161
+ "On a sheet with two successful runs, read the badges on both rows.",
162
+ "Press 'Accept & render' on the one that is not currently accepted.",
163
+ "Reload and read both rows again.",
164
+ ],
165
+ expectedBehaviour: "'succeeded' and 'accepted' are different facts: a run can succeed without being the sheet's current result, which is normal once three tiers have been tried. Accepting one moves the badge and starts the full-resolution render.",
166
+ expectedUiState: "Both rows show a green 'succeeded' badge; exactly ONE shows 'accepted'. After accepting the other, exactly one still shows 'accepted' and it is the one just pressed.",
167
+ expectedData: { acceptedRunsPerSheet: 1 },
168
+ endResult: "BEFORE: isPromoted and activeRunId were read by the UI and written by nothing — promoteRun had zero callers. AFTER: accepting a run is a real action and the badge reflects it after a reload.",
169
+ },
170
+ /* ---- promote gates full-res ------------------------------------------- */
171
+ "checklist-tools-sticker-tracer-fullres-only-after-accept": {
172
+ roles: ["admin"],
173
+ startPage: "/tools/sticker-tracer",
174
+ steps: [
175
+ ADMIN_SIGNIN,
176
+ "Commit a fresh run and wait for it to succeed WITHOUT accepting it.",
177
+ "Look for a 'Print & export' card on the page.",
178
+ "Press 'Accept & render' on that run.",
179
+ "Wait for the render, reload, and look again.",
180
+ ],
181
+ expectedBehaviour: "Full-resolution parts and the export surface exist only for an ACCEPTED run. An exploratory run costs about 1 MB; rendering full-res parts on every attempt costs roughly 500 MB a sheet — the difference between about 52 sheets inside 5 GB and about 8.",
182
+ expectedUiState: "No 'Print & export' card before accepting. After accepting it appears, with a machine and page picker.",
183
+ endResult: "BEFORE: nothing rendered full-resolution parts at all — the mode:\"full\" path had no caller. AFTER: they are rendered once, for the run actually chosen, and the export surface follows.",
184
+ },
185
+ /* ---- DPI honesty ------------------------------------------------------ */
186
+ "checklist-tools-sticker-tracer-no-dpi-no-mm": {
187
+ roles: ["admin"],
188
+ startPage: "/tools/sticker-tracer",
189
+ steps: [
190
+ ADMIN_SIGNIN,
191
+ "Open an accepted sheet whose scan declares no usable DPI — upload a screenshot or a web-saved image if none exists, since those declare 72 or 96.",
192
+ "Open 'Print & export' and read what it says.",
193
+ "Try to press 'Download cut file'.",
194
+ ],
195
+ expectedBehaviour: "Millimetres are WITHHELD when the DPI cannot be trusted. A cut file must be millimetre-true, so the export refuses rather than inventing a scale — a fabricated millimetre on a cut file is a physical production error, not a cosmetic one.",
196
+ expectedUiState: "A warning reading that the scan has no confirmed DPI and that confirming it makes the export available. The download buttons are DISABLED. No plausible-looking millimetre figure appears anywhere.",
197
+ endResult: "BEFORE: nothing distinguished a real DPI from the 72 that five of nine reference scans falsely declare. AFTER: the tool says so and refuses, naming the fix.",
198
+ },
199
+ /* ---- export refusals before download ---------------------------------- */
200
+ "checklist-tools-sticker-tracer-oversized-named-not-scaled": {
201
+ roles: ["admin"],
202
+ startPage: "/tools/sticker-tracer",
203
+ steps: [
204
+ ADMIN_SIGNIN,
205
+ "Open an accepted sheet with a confirmed DPI and scroll to 'Print & export'.",
206
+ "Set Machine to 'Cricut Joy 2 — Print Then Cut' and Page to A4.",
207
+ "Read the warning block listing parts.",
208
+ "Switch Machine to 'Print shop (Roland / Graphtec)' and read the same area again.",
209
+ ],
210
+ expectedBehaviour: "A part wider than the machine's cut area is NAMED before export, never scaled. The Joy 2's A4 Print-Then-Cut area is a column about 78 mm wide, and several stickers on a typical sheet exceed it. Scaling would produce a cut file that looks correct and yields stickers the wrong physical size.",
211
+ expectedUiState: "Under the Cricut PTC profile, a warning lists parts BY NAME with their measured width and a reason mentioning the cut width. Under the print-shop profile that warning is gone, because it has no width limit.",
212
+ endResult: "BEFORE: there was no way to learn a part was too wide except by cutting it. AFTER: the refusal is on screen before the download, and the print-shop profile is offered as the alternative.",
213
+ },
214
+ "checklist-tools-sticker-tracer-node-budget-reported": {
215
+ roles: ["admin"],
216
+ startPage: "/tools/sticker-tracer",
217
+ steps: [
218
+ ADMIN_SIGNIN,
219
+ "In 'Print & export', set Machine to a Cricut profile and read the badges under the pickers.",
220
+ "Switch to 'Print shop' and read them again.",
221
+ ],
222
+ expectedBehaviour: "Export simplification is a SEPARATE budget from the trace's. A Cricut profile re-simplifies to its node ceiling and reports the resulting deviation in millimetres; the print-shop profile has no ceiling and so does not simplify.",
223
+ expectedUiState: "A node-count badge is shown. Under a Cricut profile, when simplification occurred, a line reads 'Simplified from N nodes…' and states a worst-case deviation in mm. Under the print shop no deviation is claimed.",
224
+ endResult: "BEFORE: a max-tier trace could silently produce a file Design Space cannot open. AFTER: the node count and the cost of fitting it are both on screen before export.",
225
+ },
226
+ /* ---- retry clamp ------------------------------------------------------ */
227
+ "checklist-tools-sticker-tracer-retry-shows-clamp": {
228
+ roles: ["admin"],
229
+ startPage: "/tools/sticker-tracer",
230
+ steps: [
231
+ ADMIN_SIGNIN,
232
+ "In Attempts, press 'Retry from this' on any finished run.",
233
+ "In the retry form, open 'Where it restarts' and set 'Resume from' to 'parts'.",
234
+ "Change Tier to a different one — this changes ridge parameters, which belong to an earlier stage.",
235
+ "Read the message that appears in that section before submitting.",
236
+ ],
237
+ expectedBehaviour: "The resume point is clamped forward to the earliest stage whose parameters changed, and the clamp is SHOWN. Without it, a run resumed from 'parts' would carry artifacts generated under different parameters than the run records, with nothing anywhere contradicting it.",
238
+ expectedUiState: "A warning reading that a parameter from an earlier stage changed, so the run restarts from that stage rather than resuming from 'parts'. It names both stages.",
239
+ endResult: "BEFORE: explainResume() returned that sentence and nothing rendered it. AFTER: the operator sees the clamp before submitting, and the server applies the same decision.",
240
+ },
241
+ /* ---- access control ---------------------------------------------------- */
242
+ "checklist-tools-sticker-tracer-buyer-redirected": {
243
+ roles: ["buyer"],
244
+ startPage: "/tools/sticker-tracer",
245
+ steps: [
246
+ "Sign in as a normal buyer account (not admin).",
247
+ "Navigate directly to /tools/sticker-tracer by typing the URL.",
248
+ "Open the Tools entry in the main navigation and read its children.",
249
+ "Visit /tools and read the cards.",
250
+ ],
251
+ expectedBehaviour: "The guard is the layout's server-side session read, so a non-admin is redirected before any HTML is produced. The nav child is filtered out client-side, which is presentation only — the redirect is the real boundary.",
252
+ expectedUiState: "The tracer URL does not render; the browser lands elsewhere. The Tools dropdown does not list 'Sticker sheet tracer'. /tools itself renders normally with its other cards.",
253
+ endResult: "BEFORE/AFTER is unchanged for a buyer — this case exists to prove the gate holds. Nothing is created or persisted.",
254
+ },
255
+ "checklist-tools-sticker-tracer-guest-redirected": {
256
+ roles: ["guest"],
257
+ startPage: "/tools/sticker-tracer",
258
+ steps: [
259
+ "Sign out completely, or use a private window.",
260
+ "Navigate directly to /tools/sticker-tracer.",
261
+ "Then visit /tools.",
262
+ "View source on /tools/sticker-tracer's response and search for 'Choose a scan'.",
263
+ ],
264
+ expectedBehaviour: "A signed-out visitor is redirected to login. No part of the tracer UI is sent to the browser, because the layout redirects before rendering rather than hiding controls after.",
265
+ expectedUiState: "The login page, with a redirect back to the tracer. /tools renders normally and is unaffected. The phrase 'Choose a scan' appears nowhere in the response body.",
266
+ endResult: "BEFORE/AFTER unchanged for a guest — this proves the gate is server-side rather than a hidden control. Nothing is persisted.",
267
+ },
268
+ "checklist-tools-sticker-tracer-storage-meter-honest": {
269
+ roles: ["admin"],
270
+ startPage: "/tools/sticker-tracer",
271
+ steps: [
272
+ ADMIN_SIGNIN,
273
+ "Call GET /api/admin/sticker-sheets/usage in the browser address bar.",
274
+ "Read the per-sheet rows: each carries bytes AND an object count.",
275
+ "Compare the biggest sheet's byte figure against the number of runs it has.",
276
+ "Check whether the response carries a 'truncated' field and what it says.",
277
+ ],
278
+ expectedBehaviour: "The meter reports object COUNT beside bytes, because GCS meters them separately — which is the entire reason review thumbnails are one sprite atlas rather than sixty files. It measures at most 25 sheets per call and says when it truncated.",
279
+ expectedUiState: "JSON with rows sorted biggest-first, each having bytes and objects, plus totalBytes, totalObjects, measured and truncated.",
280
+ expectedData: { truncatedReportedExplicitly: true },
281
+ endResult: "BEFORE: storage cost was discoverable only in the GCP console, which is how the project was paused once before. AFTER: it is a route an operator can read, and a partial measurement says it is partial rather than understating the total.",
282
+ },
283
+ };
@@ -18,6 +18,7 @@
18
18
  * @tag consumers:seed/index.ts,seed/runner.ts
19
19
  * @tag sideEffects:none
20
20
  */
21
+ import { PRODUCT_MAX_IMAGES, PRODUCT_MAX_VIDEOS, } from "../../../_internal/shared/media/limits.js";
21
22
  import { assignDefaultPhases } from "../utils/phases.js";
22
23
  import { happyPathPages } from "./_happy-path.js";
23
24
  import { moneyFlowsPages } from "./_money-flows.js";
@@ -2314,20 +2315,21 @@ const rawTesterChecklistItems = [
2314
2315
  /*
2315
2316
  * REMOVED 2026-09-11 — `media-upload-images-capped-at-5`.
2316
2317
  *
2317
- * It asserted the gallery caps at "5 images (not 10)". The cap was
2318
- * raised to 10 (`PRODUCT_MAX_IMAGES`, shared/media/limits.ts:37) and the
2319
- * `selling/media-limits` page asserts the opposite in its own label:
2320
- * "The 10th gallery image uploads — the 5th used to fail with a 400".
2321
- *
2322
- * So this case documented the OLD behaviour as the expectation. It
2323
- * would fail against correct code, and anyone "fixing" the product to
2324
- * satisfy it would re-break ten-image support. Its id encoded the wrong
2325
- * number too, so correcting the label alone would still mislead.
2318
+ * It asserted the gallery caps at "5 images (not 10)". The cap had been
2319
+ * raised (`PRODUCT_MAX_IMAGES`), so the case documented the OLD
2320
+ * behaviour as the expectation: it would fail against correct code, and
2321
+ * anyone "fixing" the product to satisfy it would re-break multi-image
2322
+ * support. Its id encoded the wrong number too, so correcting the label
2323
+ * alone would still mislead.
2326
2324
  *
2327
2325
  * The invariant it really tested — the stated limit equals the enforced
2328
- * limit — survives in `media-eleventh-image-refused-client-side`, which
2329
- * requires the refusal to name the limit ("You can upload up to 10
2330
- * images."). Nothing was lost.
2326
+ * limit — survives in `media-over-cap-image-refused-client-side`, which
2327
+ * requires the refusal to NAME the limit. Nothing was lost.
2328
+ *
2329
+ * 🛑 And the lesson got applied rather than just recorded: the cap moved
2330
+ * again on 2026-10-19 (10 -> 24), and the two cases that would have gone
2331
+ * stale now interpolate `PRODUCT_MAX_IMAGES` and carry no number in
2332
+ * their ids. See the note on the `media-limits` page below.
2331
2333
  */
2332
2334
  {
2333
2335
  key: "media-upload-video-duration",
@@ -2903,25 +2905,44 @@ const rawTesterChecklistItems = [
2903
2905
  },
2904
2906
  {
2905
2907
  pageKey: "media-limits",
2906
- pageLabel: "Media \u2014 ten images and one video, on every listing type",
2908
+ pageLabel: `Media \u2014 ${PRODUCT_MAX_IMAGES} images and ${PRODUCT_MAX_VIDEOS} video, on every listing type`,
2907
2909
  href: "/store/products/new",
2908
2910
  cases: [
2909
2911
  {
2910
2912
  key: "media-gallery-accepts-images-and-video",
2911
2913
  label: "The gallery takes BOTH images and a video, and shows a live per-type count",
2912
- description: "Changed 2026-09-04. BEFORE the single-media control on the listing form was video-only (`kind=\"video\"`), so the one \"add media\" affordance a seller saw refused photos. AFTER: the gallery accepts image files and a video file in the same control, and a counter under it reads \"N/10 images \u00b7 N/1 video\" as you add them.",
2914
+ description: `Changed 2026-09-04. BEFORE the single-media control on the listing form was video-only (\`kind="video"\`), so the one "add media" affordance a seller saw refused photos. AFTER: the gallery accepts image files and a video file in the same control, and a counter under it reads "N/${PRODUCT_MAX_IMAGES} images \u00b7 N/${PRODUCT_MAX_VIDEOS} video" as you add them.`,
2913
2915
  href: "/store/products/new",
2914
2916
  },
2917
+ /*
2918
+ * \ud83d\uded1 These two cases state the cap by INTERPOLATING `PRODUCT_MAX_IMAGES`,
2919
+ * and their keys no longer encode a number.
2920
+ *
2921
+ * The pair they replace (`media-tenth-image-uploads`,
2922
+ * `media-eleventh-image-refused-client-side`) hard-coded 10 in the key,
2923
+ * the label, the description and the authored procedure's `inputs` \u2014
2924
+ * so raising the cap to 24 on 2026-10-19 would have left four cases
2925
+ * asserting the OLD number and failing against correct code. That is
2926
+ * exactly what the removal note above this page records happening the
2927
+ * last time the cap moved, including its warning that "its id encoded
2928
+ * the wrong number too, so correcting the label alone would still
2929
+ * mislead".
2930
+ *
2931
+ * What is actually under test is the BOUNDARY, not the number: that the
2932
+ * last allowed image succeeds (the off-by-one), and that the first one
2933
+ * over is refused client-side. Both are stated cap-agnostically, so the
2934
+ * next change to the cap needs no edit here at all.
2935
+ */
2915
2936
  {
2916
- key: "media-tenth-image-uploads",
2917
- label: "The 10th gallery image uploads \u2014 the 5th used to fail with a 400",
2918
- description: "BEFORE: the gallery was capped at 5 and sent its Nth image as index N+1, while the server's signed-URL guard rejected any index above 5 \u2014 so the LAST slot of every product form returned a 400 that read as a random upload failure. AFTER: add ten images one at a time. All ten must succeed, including the tenth.",
2937
+ key: "media-last-allowed-image-uploads",
2938
+ label: "The LAST allowed gallery image uploads \u2014 the cap is inclusive of its own number",
2939
+ description: `Add images one at a time, counting previews, until the control refuses one. BEFORE: the gallery sent its Nth image as index N+1 while the server's signed-URL guard rejected any index above the cap \u2014 so the LAST slot of every product form returned a 400 that read as a random upload failure. AFTER: the count you reach before any refusal must be exactly ${PRODUCT_MAX_IMAGES}, not ${PRODUCT_MAX_IMAGES - 1}. An off-by-one here is the most likely error and the least likely to be noticed, because one short of the cap still looks like plenty.`,
2919
2940
  href: "/store/products/new",
2920
2941
  },
2921
2942
  {
2922
- key: "media-eleventh-image-refused-client-side",
2923
- label: "The 11th image is refused by the FORM with a clear message, not by the server",
2924
- description: "Try to add an 11th image. The control must refuse it before uploading, naming the limit (\"You can upload up to 10 images.\"). A server-side 400 arriving after the bytes have gone up is the wrong behaviour \u2014 the user has already waited.",
2943
+ key: "media-over-cap-image-refused-client-side",
2944
+ label: "The first image OVER the cap is refused by the FORM, not by the server",
2945
+ description: `With ${PRODUCT_MAX_IMAGES} images already added, attempt one more with the browser's Network panel open. The control must refuse it before requesting a signed URL, and the message must NAME the limit ("You can upload up to ${PRODUCT_MAX_IMAGES} images."). A server-side 400 arriving after the bytes have gone up is the wrong behaviour twice over \u2014 the seller has already waited, and an orphaned object is left in storage.`,
2925
2946
  href: "/store/products/new",
2926
2947
  },
2927
2948
  {
@@ -2932,8 +2953,8 @@ const rawTesterChecklistItems = [
2932
2953
  },
2933
2954
  {
2934
2955
  key: "media-caps-flat-across-types",
2935
- label: "The same 10 + 1 applies to an auction and a pre-order \u2014 there is no per-type table",
2936
- description: "Repeat the ten-image check on /store/auctions/new and /store/pre-orders/new. Both must allow ten. BEFORE the server carried separate AUCTION_IMAGE_MAX and PREORDER_IMAGE_MAX constants, both 5, disagreeing with everything else.",
2956
+ label: `The same ${PRODUCT_MAX_IMAGES} + ${PRODUCT_MAX_VIDEOS} applies to an auction and a pre-order \u2014 there is no per-type table`,
2957
+ description: `Repeat the boundary check on /store/auctions/new and /store/pre-orders/new. Both must allow ${PRODUCT_MAX_IMAGES}. BEFORE the server carried separate AUCTION_IMAGE_MAX and PREORDER_IMAGE_MAX constants, both 5, disagreeing with everything else.`,
2937
2958
  href: "/store/auctions/new",
2938
2959
  },
2939
2960
  {
@@ -3091,6 +3112,72 @@ const rawTesterChecklistItems = [
3091
3112
  { key: "brand-count-matches-its-listing", label: "A brand page's count equals what that brand page lists" },
3092
3113
  ],
3093
3114
  },
3115
+ {
3116
+ /*
3117
+ * Overflowing pill and tab rows — 2026-10-18.
3118
+ *
3119
+ * 🛑 Every case here is written as an explicit BEFORE → AFTER, because
3120
+ * the defect's symptom is not an error: a row that overflows renders
3121
+ * perfectly, returns HTTP 200, and simply puts some of its items past
3122
+ * the right edge where nothing indicates they exist. A case reading
3123
+ * "check the subcategories show" PASSES against the bug.
3124
+ *
3125
+ * The reported instance had 12 subcategory pills on a 1440px viewport
3126
+ * with the last four unreachable — no scrollbar, no arrow, no hint.
3127
+ *
3128
+ * Width is the thing under test, so every case NAMES A VIEWPORT. A run
3129
+ * at an unstated width cannot distinguish "collapsed correctly" from
3130
+ * "collapsed when it had room", which are opposite defects.
3131
+ */
3132
+ pageKey: "overflowing-pill-rows",
3133
+ pageLabel: "Pill and tab rows that do not fit collapse into a searchable dropdown",
3134
+ href: "/categories",
3135
+ cases: [
3136
+ { key: "wide-row-stays-pills", label: "A subcategory row that FITS still renders as pills, not a dropdown" },
3137
+ { key: "narrow-row-collapses", label: "The same row at a phone width collapses to one dropdown trigger" },
3138
+ { key: "collapsed-dropdown-is-searchable", label: "The collapsed dropdown has a search box that filters as you type" },
3139
+ { key: "collapsed-dropdown-keyboard", label: "Arrow keys and Enter pick an item without touching the mouse" },
3140
+ { key: "every-item-reachable-when-collapsed", label: "Every subcategory is reachable from the dropdown, including ones that used to be off-screen" },
3141
+ { key: "pills-carry-a-leading-image", label: "Subcategory pills and dropdown rows show the category's own cover image" },
3142
+ { key: "missing-image-falls-back-to-initial", label: "A subcategory with no cover image shows an initial, not a blank box or a broken image" },
3143
+ { key: "widening-restores-the-pills", label: "Widening the window back expands the dropdown into pills again" },
3144
+ { key: "subcategory-click-is-client-side", label: "Clicking a subcategory navigates without a full page reload" },
3145
+ { key: "tabs-collapse-by-width-not-count", label: "A tab bar with six short tabs stays a row on desktop instead of collapsing on a count" },
3146
+ { key: "event-tabs-do-not-jump-to-top", label: "Switching event tabs does not scroll the page back to the top" },
3147
+ ],
3148
+ },
3149
+ {
3150
+ /*
3151
+ * The authenticity checker — 2026-10-18.
3152
+ *
3153
+ * 🛑 Every case here asserts the presence of a HEDGE, or compares two
3154
+ * inputs, because this tool's failure mode is not a crash: it is a
3155
+ * confident, plausible, wrong answer served with HTTP 200. Code-matching
3156
+ * alone cannot detect a counterfeit (one crawled counterfeit catalogue
3157
+ * printed 900+ genuine Takara Tomy codes), the Metal Fight date-code
3158
+ * decoding is disputed with no manufacturer statement, and two of the
3159
+ * spellings a naive build would flag as fake tells are Takara Tomy's own
3160
+ * romanisation and a licensed Indian importer's name.
3161
+ */
3162
+ pageKey: "authenticity-checker",
3163
+ pageLabel: "Authenticity checker — box codes, per-generation checks and the sign-in gate",
3164
+ href: "/tools/authenticity",
3165
+ cases: [
3166
+ { key: "guest-sees-reference-not-a-wall", label: "Signed out, the generation table and universal checks still render — only the lookup is gated" },
3167
+ { key: "no-signin-flash-when-authenticated", label: "A signed-in user never sees 'Sign in to run a lookup' during a hard reload" },
3168
+ { key: "midfake-code-reads-as-batch-not-accusation", label: "A matched midfake code reports a batch, never a counterfeit accusation against the seller" },
3169
+ { key: "date-code-shows-both-readings", label: "A box date code shows BOTH circulating readings and says neither is official" },
3170
+ { key: "real-product-code-is-not-evidence", label: "A well-formed product code is marked neutral and states that real codes appear on fakes" },
3171
+ { key: "name-code-mismatch-asks-rather-than-accuses", label: "A name/code mismatch is a question, and ticking Random Booster re-reads it as expected" },
3172
+ { key: "ambiguous-name-asks-which-model", label: "An ambiguous name asks which release instead of confidently naming one" },
3173
+ { key: "takara-spelling-is-not-flagged", label: "'Storm Pegasis' (the Takara Tomy spelling) is not flagged, while 'Scythee' is" },
3174
+ { key: "funskool-is-not-a-fake-signal", label: "Funskool reads as a licensed importer; Rapidity reads as an unlicensed producer" },
3175
+ { key: "unknown-code-is-not-called-fake", label: "An unrecorded code says 'not recorded' and explicitly not 'fake'" },
3176
+ { key: "asks-generation-when-nothing-inferable", label: "With no generation inferable the tool asks instead of returning a verdict" },
3177
+ { key: "api-refuses-signed-out", label: "POST /api/tools/authenticity returns 401/403 signed out and leaks no assessment" },
3178
+ { key: "json-ld-declares-the-gate", label: "The WebApplication JSON-LD declares the gated region, and its cssSelector matches a real element" },
3179
+ ],
3180
+ },
3094
3181
  {
3095
3182
  /*
3096
3183
  * D12 — the parts database, the composition panel, and the part line in a
@@ -3935,6 +4022,49 @@ const rawTesterChecklistItems = [
3935
4022
  },
3936
4023
  ],
3937
4024
  },
4025
+ {
4026
+ pageKey: "header-brand-mark-centring",
4027
+ pageLabel: "Header — Centred Brand Mark Never Collides With the Icons",
4028
+ href: "/products",
4029
+ cases: [
4030
+ {
4031
+ key: "mark-clear-of-icons-across-the-lg-band",
4032
+ label: "Sweeping the window from 1024px to 1280px, the centred leaf mark never overlaps the notification, messages, wishlist or cart icons",
4033
+ description: "Fixed 2026-10-19. BEFORE: the mark was `position: absolute; left: 50%` inside the title row, so the row's `justify-between` reserved no space for it and the right-hand cluster grew leftward straight over it. The mark reveals at md (768px) and those four icons reveal at lg (1024px), so from 1024px to roughly 1150px the cluster's left edge crossed the row midpoint and the leaf painted across the bell and the heart. AFTER: resize in ~32px steps from 1024px to 1280px and watch the gap between the wordmark and the first icon. The leaf must sit in clear space at every single step — no part of it may touch an icon's 44px box.",
4034
+ href: "/products",
4035
+ },
4036
+ {
4037
+ key: "mark-clear-signed-out-worst-case",
4038
+ label: "SIGNED OUT at ~1100px — where 'Sign in' and 'Register' make the cluster widest — the mark is still clear of everything",
4039
+ description: "Signed out is the worst case, not the easiest: the two auth buttons (~160px together) stand in for a single 44px avatar, so the cluster reaches ~120px further left than it does signed in. This is the exact width and session the original screenshot was taken at. Compare the same width signed in and signed out; both must be clean, and if only one fails say which.",
4040
+ href: "/products",
4041
+ },
4042
+ {
4043
+ key: "mark-shifts-rather-than-overlapping",
4044
+ label: "When the cluster is too wide to leave room, the mark moves off-centre — it never ends up underneath an icon, and no control is clipped at the window edge",
4045
+ description: "The mark is now one of three in-flow tracks, so a crowded row makes it YIELD. Narrow past the point where a perfectly centred mark would no longer fit and confirm the degradation: the leaf slides toward the wordmark and stays fully visible, the icons keep their full 44px boxes, and nothing is cut off at the right edge. A leaf that vanishes under an icon, or a hamburger sliced by the edge, are both failures — record which.",
4046
+ href: "/products",
4047
+ },
4048
+ {
4049
+ key: "mark-centred-at-wide-widths",
4050
+ label: "At 1440px and wider the leaf is centred in the header, not nudged to one side",
4051
+ description: "With room to spare the two side tracks split the free space evenly, which should put the leaf on the header's midpoint. Maximise the window and eyeball it against the centre of the page — a mark that is visibly off-centre at a wide width means the tracks are no longer balanced, which is a different fault from the collision and should be reported separately.",
4052
+ href: "/products",
4053
+ },
4054
+ {
4055
+ key: "mark-absent-below-md",
4056
+ label: "At 767px and below there is no centred leaf, the wordmark keeps its own small leaf prefix, and the header has no odd empty gap",
4057
+ description: "The centred mark is `hidden` below md, which removes it as a layout item entirely — so the header should look exactly as it always has on mobile. Check 767px, 640px and 320px: no centred leaf, a small leaf immediately left of the 'LetItRip' wordmark, the action cluster still flush to the right edge with no stray gap, and the hamburger fully visible and tappable at 320px.",
4058
+ href: "/products",
4059
+ },
4060
+ {
4061
+ key: "mark-centred-in-left-hand-mode",
4062
+ label: "In left-hand mode the wordmark and the icons swap sides, the leaf stays centred, and it still overlaps nothing",
4063
+ description: "Hand mode mirrors the row, so this is where a layout fix most easily half-works. Turn on left-hand mode, then repeat the 1024px–1280px sweep: the wordmark must sit flush against the RIGHT edge with no gap, the icon cluster flush against the LEFT edge with the hamburger outermost, and the leaf still centred and untouched. A wordmark floating away from its edge means a side track lost its mirrored alignment.",
4064
+ href: "/products",
4065
+ },
4066
+ ],
4067
+ },
3938
4068
  {
3939
4069
  pageKey: "nav-reachability",
3940
4070
  pageLabel: "Navigation — Every Item Reachable at Every Width",
@@ -6711,6 +6841,46 @@ const rawTesterChecklistItems = [
6711
6841
  * tester reporting "I did the actions" as if it were "the outcome was right".
6712
6842
  * ══════════════════════════════════════════════════════════════════════════ */
6713
6843
  ...group("money-flows", "Money Flows (end to end)", moneyFlowsPages),
6844
+ /*
6845
+ * The sticker-sheet kiss-cut tracer. Admin-only, under a PUBLIC prefix.
6846
+ *
6847
+ * 🛑 `adminOnly` is a presentation flag for the checklist, not the gate. The
6848
+ * real boundary is the layout's server-side session read, which redirects a
6849
+ * non-admin before any HTML exists — which is exactly what the buyer and
6850
+ * guest cases below assert. Marking it admin-only here only keeps it out of a
6851
+ * non-admin tester's list.
6852
+ *
6853
+ * Every case is an explicit BEFORE -> AFTER, because almost every defect this
6854
+ * feature can have returns 200 with plausible content: a wrong part count, a
6855
+ * watermarked original, a millimetre derived from a DPI nobody confirmed. A
6856
+ * case reading "check the tracer works" would pass against all three.
6857
+ */
6858
+ ...group("tools", "Tools", [
6859
+ {
6860
+ pageKey: "sticker-tracer",
6861
+ pageLabel: "Sticker sheet tracer",
6862
+ href: "/tools/sticker-tracer",
6863
+ cases: [
6864
+ { key: "enclosed-region-opaque", label: "An enclosed region matching the paper colour stays OPAQUE inside its sticker" },
6865
+ { key: "white-on-white-edge", label: "A white sticker edge on white paper is found with no per-sticker parameter" },
6866
+ { key: "background-model-named", label: "The result names which background model ran (paper vs art)" },
6867
+ { key: "name-required", label: "A run cannot be committed without a name" },
6868
+ { key: "no-watermark-on-original", label: "A downloaded original carries NO watermark and comes from a signed GCS URL" },
6869
+ { key: "progress-names-stage", label: "Live progress names the current STAGE, not just a percentage" },
6870
+ { key: "failure-names-stage", label: "A failed run names the stage it died in and survives a reload" },
6871
+ { key: "runs-never-overwrite", label: "A second run never overwrites the first — both stay in history" },
6872
+ { key: "accepted-differs-from-succeeded", label: "'accepted' and 'succeeded' are distinct, and exactly one run is accepted" },
6873
+ { key: "fullres-only-after-accept", label: "Full-resolution parts and the export surface appear only after accepting" },
6874
+ { key: "no-dpi-no-mm", label: "With no confirmed DPI the export REFUSES rather than inventing a scale" },
6875
+ { key: "oversized-named-not-scaled", label: "A part too wide for the machine is NAMED before export, never scaled" },
6876
+ { key: "node-budget-reported", label: "The export node budget reports its cost in millimetres of deviation" },
6877
+ { key: "retry-shows-clamp", label: "A retry SHOWS the resume clamp before it is applied" },
6878
+ { key: "buyer-redirected", label: "A signed-in buyer is redirected and sees no Tools entry for it" },
6879
+ { key: "guest-redirected", label: "A signed-out visitor is redirected; /tools itself is unaffected" },
6880
+ { key: "storage-meter-honest", label: "The storage meter reports object COUNT beside bytes, and says when it truncated" },
6881
+ ],
6882
+ },
6883
+ ], { adminOnly: true }),
6714
6884
  ];
6715
6885
  const defaultPhases = assignDefaultPhases(rawTesterChecklistItems);
6716
6886
  export const testerChecklistSeedData = rawTesterChecklistItems.map((item, index) => ({