@open-mercato/core 0.6.7-develop.6788.1.c2a1520a30 → 0.6.7-develop.6814.1.0627c7e9f1

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 (394) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/generated/entities/customer_deal_person_link/index.js +2 -0
  3. package/dist/generated/entities/customer_deal_person_link/index.js.map +2 -2
  4. package/dist/generated/entities/customer_user_invitation/index.js +2 -0
  5. package/dist/generated/entities/customer_user_invitation/index.js.map +2 -2
  6. package/dist/generated/entities.ids.generated.js +1 -0
  7. package/dist/generated/entities.ids.generated.js.map +2 -2
  8. package/dist/generated/entity-fields-registry.js +2 -0
  9. package/dist/generated/entity-fields-registry.js.map +2 -2
  10. package/dist/modules/business_rules/api/openmercato-call-options/route.js +85 -0
  11. package/dist/modules/business_rules/api/openmercato-call-options/route.js.map +7 -0
  12. package/dist/modules/business_rules/api/rules/route.js +71 -4
  13. package/dist/modules/business_rules/api/rules/route.js.map +2 -2
  14. package/dist/modules/business_rules/components/ActionBuilder.js +47 -4
  15. package/dist/modules/business_rules/components/ActionBuilder.js.map +3 -3
  16. package/dist/modules/business_rules/components/ActionRow.js +106 -16
  17. package/dist/modules/business_rules/components/ActionRow.js.map +2 -2
  18. package/dist/modules/business_rules/components/utils/actionValidation.js +6 -0
  19. package/dist/modules/business_rules/components/utils/actionValidation.js.map +2 -2
  20. package/dist/modules/business_rules/lib/action-executor.js +148 -0
  21. package/dist/modules/business_rules/lib/action-executor.js.map +2 -2
  22. package/dist/modules/business_rules/lib/openmercato-call-options-types.js +5 -0
  23. package/dist/modules/business_rules/lib/openmercato-call-options-types.js.map +7 -0
  24. package/dist/modules/business_rules/lib/openmercato-call-options.js +231 -0
  25. package/dist/modules/business_rules/lib/openmercato-call-options.js.map +7 -0
  26. package/dist/modules/business_rules/lib/rule-engine.js +5 -1
  27. package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
  28. package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js +11 -1
  29. package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js.map +2 -2
  30. package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js +11 -6
  31. package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js.map +2 -2
  32. package/dist/modules/configs/lib/upgrade-actions.js +12 -0
  33. package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
  34. package/dist/modules/customer_accounts/api/admin/users/[id].js +10 -1
  35. package/dist/modules/customer_accounts/api/admin/users/[id].js.map +2 -2
  36. package/dist/modules/customer_accounts/api/admin/users-invite.js +61 -4
  37. package/dist/modules/customer_accounts/api/admin/users-invite.js.map +2 -2
  38. package/dist/modules/customer_accounts/api/portal/users-invite.js +20 -2
  39. package/dist/modules/customer_accounts/api/portal/users-invite.js.map +2 -2
  40. package/dist/modules/customer_accounts/data/entities.js +3 -0
  41. package/dist/modules/customer_accounts/data/entities.js.map +2 -2
  42. package/dist/modules/customer_accounts/data/validators.js +1 -0
  43. package/dist/modules/customer_accounts/data/validators.js.map +2 -2
  44. package/dist/modules/customer_accounts/emails/CustomerInvitationEmail.js +26 -0
  45. package/dist/modules/customer_accounts/emails/CustomerInvitationEmail.js.map +7 -0
  46. package/dist/modules/customer_accounts/lib/customerEntityOwnership.js +29 -3
  47. package/dist/modules/customer_accounts/lib/customerEntityOwnership.js.map +2 -2
  48. package/dist/modules/customer_accounts/lib/customerUrl.js +19 -10
  49. package/dist/modules/customer_accounts/lib/customerUrl.js.map +2 -2
  50. package/dist/modules/customer_accounts/lib/invitationEmail.js +35 -0
  51. package/dist/modules/customer_accounts/lib/invitationEmail.js.map +7 -0
  52. package/dist/modules/customer_accounts/migrations/Migration20260723120000_customer_accounts.js +13 -0
  53. package/dist/modules/customer_accounts/migrations/Migration20260723120000_customer_accounts.js.map +7 -0
  54. package/dist/modules/customer_accounts/services/customerInvitationService.js +32 -2
  55. package/dist/modules/customer_accounts/services/customerInvitationService.js.map +2 -2
  56. package/dist/modules/customer_accounts/subscribers/autoLinkCrm.js +47 -7
  57. package/dist/modules/customer_accounts/subscribers/autoLinkCrm.js.map +2 -2
  58. package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js +2 -2
  59. package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js.map +2 -2
  60. package/dist/modules/customer_accounts/widgets/injection-table.js +1 -1
  61. package/dist/modules/customer_accounts/widgets/injection-table.js.map +2 -2
  62. package/dist/modules/customers/api/deals/[id]/people/route.js +4 -2
  63. package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
  64. package/dist/modules/customers/api/deals/[id]/route.js +7 -3
  65. package/dist/modules/customers/api/deals/[id]/route.js.map +2 -2
  66. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +11 -1
  67. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
  68. package/dist/modules/customers/backend/customers/deals/[id]/page.js +14 -8
  69. package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
  70. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +21 -6
  71. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  72. package/dist/modules/customers/cli.js +17 -7
  73. package/dist/modules/customers/cli.js.map +2 -2
  74. package/dist/modules/customers/commands/deals.js +48 -10
  75. package/dist/modules/customers/commands/deals.js.map +2 -2
  76. package/dist/modules/customers/commands/people.js +2 -0
  77. package/dist/modules/customers/commands/people.js.map +2 -2
  78. package/dist/modules/customers/components/detail/CompanyDetailTabs.js +26 -6
  79. package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +2 -2
  80. package/dist/modules/customers/components/detail/DealDetailTabs.js +30 -8
  81. package/dist/modules/customers/components/detail/DealDetailTabs.js.map +2 -2
  82. package/dist/modules/customers/components/detail/PersonDetailTabs.js +30 -8
  83. package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
  84. package/dist/modules/customers/data/entities.js +8 -0
  85. package/dist/modules/customers/data/entities.js.map +2 -2
  86. package/dist/modules/customers/data/validators.js +2 -1
  87. package/dist/modules/customers/data/validators.js.map +2 -2
  88. package/dist/modules/customers/migrations/Migration20260723210000_customers.js +15 -0
  89. package/dist/modules/customers/migrations/Migration20260723210000_customers.js.map +7 -0
  90. package/dist/modules/customers/search.js +50 -29
  91. package/dist/modules/customers/search.js.map +2 -2
  92. package/dist/modules/data_sync/api/mappings/[id]/route.js +22 -9
  93. package/dist/modules/data_sync/api/mappings/[id]/route.js.map +2 -2
  94. package/dist/modules/data_sync/api/mappings/route.js +13 -4
  95. package/dist/modules/data_sync/api/mappings/route.js.map +2 -2
  96. package/dist/modules/data_sync/api/options.js +7 -2
  97. package/dist/modules/data_sync/api/options.js.map +2 -2
  98. package/dist/modules/data_sync/api/run.js +7 -2
  99. package/dist/modules/data_sync/api/run.js.map +2 -2
  100. package/dist/modules/data_sync/api/runs/[id]/cancel.js +8 -3
  101. package/dist/modules/data_sync/api/runs/[id]/cancel.js.map +2 -2
  102. package/dist/modules/data_sync/api/runs/[id]/retry.js +7 -2
  103. package/dist/modules/data_sync/api/runs/[id]/retry.js.map +2 -2
  104. package/dist/modules/data_sync/api/runs/[id]/route.js +8 -3
  105. package/dist/modules/data_sync/api/runs/[id]/route.js.map +2 -2
  106. package/dist/modules/data_sync/api/runs.js +7 -2
  107. package/dist/modules/data_sync/api/runs.js.map +2 -2
  108. package/dist/modules/data_sync/api/schedules/[id]/route.js +19 -6
  109. package/dist/modules/data_sync/api/schedules/[id]/route.js.map +2 -2
  110. package/dist/modules/data_sync/api/schedules/route.js +13 -4
  111. package/dist/modules/data_sync/api/schedules/route.js.map +2 -2
  112. package/dist/modules/data_sync/api/validate.js +9 -4
  113. package/dist/modules/data_sync/api/validate.js.map +2 -2
  114. package/dist/modules/design_system/acl.js +9 -0
  115. package/dist/modules/design_system/acl.js.map +7 -0
  116. package/dist/modules/design_system/backend/design-system/page.js +11 -0
  117. package/dist/modules/design_system/backend/design-system/page.js.map +7 -0
  118. package/dist/modules/design_system/backend/design-system/page.meta.js +15 -0
  119. package/dist/modules/design_system/backend/design-system/page.meta.js.map +7 -0
  120. package/dist/modules/design_system/gallery/components/CodeSnippet.js +52 -0
  121. package/dist/modules/design_system/gallery/components/CodeSnippet.js.map +7 -0
  122. package/dist/modules/design_system/gallery/components/EntryCard.js +63 -0
  123. package/dist/modules/design_system/gallery/components/EntryCard.js.map +7 -0
  124. package/dist/modules/design_system/gallery/components/GalleryShell.js +163 -0
  125. package/dist/modules/design_system/gallery/components/GalleryShell.js.map +7 -0
  126. package/dist/modules/design_system/gallery/components/VariantPreview.js +9 -0
  127. package/dist/modules/design_system/gallery/components/VariantPreview.js.map +7 -0
  128. package/dist/modules/design_system/gallery/entries/banners.js +186 -0
  129. package/dist/modules/design_system/gallery/entries/banners.js.map +7 -0
  130. package/dist/modules/design_system/gallery/entries/buttons.js +361 -0
  131. package/dist/modules/design_system/gallery/entries/buttons.js.map +7 -0
  132. package/dist/modules/design_system/gallery/entries/charts.js +457 -0
  133. package/dist/modules/design_system/gallery/entries/charts.js.map +7 -0
  134. package/dist/modules/design_system/gallery/entries/dates.js +306 -0
  135. package/dist/modules/design_system/gallery/entries/dates.js.map +7 -0
  136. package/dist/modules/design_system/gallery/entries/detail.js +358 -0
  137. package/dist/modules/design_system/gallery/entries/detail.js.map +7 -0
  138. package/dist/modules/design_system/gallery/entries/display.js +785 -0
  139. package/dist/modules/design_system/gallery/entries/display.js.map +7 -0
  140. package/dist/modules/design_system/gallery/entries/feedback.js +658 -0
  141. package/dist/modules/design_system/gallery/entries/feedback.js.map +7 -0
  142. package/dist/modules/design_system/gallery/entries/filters.js +505 -0
  143. package/dist/modules/design_system/gallery/entries/filters.js.map +7 -0
  144. package/dist/modules/design_system/gallery/entries/foundations.js +453 -0
  145. package/dist/modules/design_system/gallery/entries/foundations.js.map +7 -0
  146. package/dist/modules/design_system/gallery/entries/icons.js +140 -0
  147. package/dist/modules/design_system/gallery/entries/icons.js.map +7 -0
  148. package/dist/modules/design_system/gallery/entries/inputs.js +1217 -0
  149. package/dist/modules/design_system/gallery/entries/inputs.js.map +7 -0
  150. package/dist/modules/design_system/gallery/entries/messages.js +334 -0
  151. package/dist/modules/design_system/gallery/entries/messages.js.map +7 -0
  152. package/dist/modules/design_system/gallery/entries/navigation.js +475 -0
  153. package/dist/modules/design_system/gallery/entries/navigation.js.map +7 -0
  154. package/dist/modules/design_system/gallery/entries/notifications.js +257 -0
  155. package/dist/modules/design_system/gallery/entries/notifications.js.map +7 -0
  156. package/dist/modules/design_system/gallery/entries/overlays.js +576 -0
  157. package/dist/modules/design_system/gallery/entries/overlays.js.map +7 -0
  158. package/dist/modules/design_system/gallery/entries/scaffolding.js +378 -0
  159. package/dist/modules/design_system/gallery/entries/scaffolding.js.map +7 -0
  160. package/dist/modules/design_system/gallery/entries/schedule.js +297 -0
  161. package/dist/modules/design_system/gallery/entries/schedule.js.map +7 -0
  162. package/dist/modules/design_system/gallery/registry.js +139 -0
  163. package/dist/modules/design_system/gallery/registry.js.map +7 -0
  164. package/dist/modules/design_system/gallery/types.js +1 -0
  165. package/dist/modules/design_system/gallery/types.js.map +7 -0
  166. package/dist/modules/design_system/index.js +9 -0
  167. package/dist/modules/design_system/index.js.map +7 -0
  168. package/dist/modules/design_system/setup.js +14 -0
  169. package/dist/modules/design_system/setup.js.map +7 -0
  170. package/dist/modules/entities/api/entity-settings.js +59 -9
  171. package/dist/modules/entities/api/entity-settings.js.map +2 -2
  172. package/dist/modules/entities/backend/config/settings/page.js +10 -0
  173. package/dist/modules/entities/backend/config/settings/page.js.map +7 -0
  174. package/dist/modules/entities/backend/config/settings/page.meta.js +36 -0
  175. package/dist/modules/entities/backend/config/settings/page.meta.js.map +7 -0
  176. package/dist/modules/entities/backend/entities/user/create/page.js +16 -7
  177. package/dist/modules/entities/backend/entities/user/create/page.js.map +2 -2
  178. package/dist/modules/entities/components/EntitySettingsManager.js +136 -0
  179. package/dist/modules/entities/components/EntitySettingsManager.js.map +7 -0
  180. package/dist/modules/inbox_ops/api/webhook/inbound.js +14 -10
  181. package/dist/modules/inbox_ops/api/webhook/inbound.js.map +2 -2
  182. package/dist/modules/inbox_ops/search.js +15 -4
  183. package/dist/modules/inbox_ops/search.js.map +2 -2
  184. package/dist/modules/integrations/api/[id]/credentials/route.js +11 -5
  185. package/dist/modules/integrations/api/[id]/credentials/route.js.map +2 -2
  186. package/dist/modules/integrations/api/[id]/health/route.js +6 -3
  187. package/dist/modules/integrations/api/[id]/health/route.js.map +2 -2
  188. package/dist/modules/integrations/api/[id]/route.js +6 -3
  189. package/dist/modules/integrations/api/[id]/route.js.map +2 -2
  190. package/dist/modules/integrations/api/[id]/state/route.js +6 -3
  191. package/dist/modules/integrations/api/[id]/state/route.js.map +2 -2
  192. package/dist/modules/integrations/api/[id]/version/route.js +6 -3
  193. package/dist/modules/integrations/api/[id]/version/route.js.map +2 -2
  194. package/dist/modules/integrations/api/logs/route.js +6 -3
  195. package/dist/modules/integrations/api/logs/route.js.map +2 -2
  196. package/dist/modules/integrations/api/route.js +6 -3
  197. package/dist/modules/integrations/api/route.js.map +2 -2
  198. package/dist/modules/integrations/api/umes-read.js +2 -2
  199. package/dist/modules/integrations/api/umes-read.js.map +2 -2
  200. package/dist/modules/integrations/lib/organization-scope.js +2 -9
  201. package/dist/modules/integrations/lib/organization-scope.js.map +2 -2
  202. package/dist/modules/messages/search.js +10 -5
  203. package/dist/modules/messages/search.js.map +2 -2
  204. package/dist/modules/payment_gateways/api/webhook/[provider]/route.js +11 -1
  205. package/dist/modules/payment_gateways/api/webhook/[provider]/route.js.map +2 -2
  206. package/dist/modules/payment_gateways/data/entities.js +4 -0
  207. package/dist/modules/payment_gateways/data/entities.js.map +2 -2
  208. package/dist/modules/payment_gateways/lib/gateway-service.js +12 -2
  209. package/dist/modules/payment_gateways/lib/gateway-service.js.map +2 -2
  210. package/dist/modules/payment_gateways/lib/session-idempotency.js +33 -0
  211. package/dist/modules/payment_gateways/lib/session-idempotency.js.map +2 -2
  212. package/dist/modules/payment_gateways/migrations/Migration20260803103035_payment_gateways.js +18 -0
  213. package/dist/modules/payment_gateways/migrations/Migration20260803103035_payment_gateways.js.map +7 -0
  214. package/dist/modules/payment_gateways/setup.js +47 -0
  215. package/dist/modules/payment_gateways/setup.js.map +2 -2
  216. package/dist/modules/payment_gateways/workers/session-initialization-prune.js +50 -0
  217. package/dist/modules/payment_gateways/workers/session-initialization-prune.js.map +7 -0
  218. package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.js +134 -0
  219. package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.js.map +7 -0
  220. package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.meta.js +11 -0
  221. package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.meta.js.map +7 -0
  222. package/dist/modules/portal/lib/navigation.js +7 -0
  223. package/dist/modules/portal/lib/navigation.js.map +7 -0
  224. package/dist/modules/query_index/data/entities.js +2 -1
  225. package/dist/modules/query_index/data/entities.js.map +2 -2
  226. package/dist/modules/query_index/lib/engine.js +75 -50
  227. package/dist/modules/query_index/lib/engine.js.map +2 -2
  228. package/dist/modules/query_index/lib/search-tokens.js +15 -5
  229. package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
  230. package/dist/modules/query_index/migrations/Migration20260731105052_query_index.js +17 -0
  231. package/dist/modules/query_index/migrations/Migration20260731105052_query_index.js.map +7 -0
  232. package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js +11 -1
  233. package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js.map +2 -2
  234. package/generated/entities/customer_deal_person_link/index.ts +1 -0
  235. package/generated/entities/customer_user_invitation/index.ts +1 -0
  236. package/generated/entities.ids.generated.ts +1 -0
  237. package/generated/entity-fields-registry.ts +2 -0
  238. package/package.json +16 -16
  239. package/src/modules/business_rules/api/openmercato-call-options/route.ts +94 -0
  240. package/src/modules/business_rules/api/rules/route.ts +92 -4
  241. package/src/modules/business_rules/components/ActionBuilder.tsx +54 -5
  242. package/src/modules/business_rules/components/ActionRow.tsx +156 -18
  243. package/src/modules/business_rules/components/utils/actionValidation.ts +6 -0
  244. package/src/modules/business_rules/i18n/de.json +12 -0
  245. package/src/modules/business_rules/i18n/en.json +12 -0
  246. package/src/modules/business_rules/i18n/es.json +12 -0
  247. package/src/modules/business_rules/i18n/pl.json +12 -0
  248. package/src/modules/business_rules/lib/action-executor.ts +198 -0
  249. package/src/modules/business_rules/lib/openmercato-call-options-types.ts +31 -0
  250. package/src/modules/business_rules/lib/openmercato-call-options.ts +297 -0
  251. package/src/modules/business_rules/lib/rule-engine.ts +4 -0
  252. package/src/modules/communication_channels/api/post/webhook/[provider]/route.ts +11 -1
  253. package/src/modules/communication_channels/api/post/webhooks/gmail/route.ts +17 -11
  254. package/src/modules/configs/lib/upgrade-actions.ts +14 -0
  255. package/src/modules/customer_accounts/api/admin/users/[id].ts +16 -1
  256. package/src/modules/customer_accounts/api/admin/users-invite.ts +78 -3
  257. package/src/modules/customer_accounts/api/portal/users-invite.ts +22 -1
  258. package/src/modules/customer_accounts/data/entities.ts +3 -0
  259. package/src/modules/customer_accounts/data/validators.ts +1 -0
  260. package/src/modules/customer_accounts/emails/CustomerInvitationEmail.tsx +45 -0
  261. package/src/modules/customer_accounts/i18n/de.json +6 -0
  262. package/src/modules/customer_accounts/i18n/en.json +6 -0
  263. package/src/modules/customer_accounts/i18n/es.json +6 -0
  264. package/src/modules/customer_accounts/i18n/pl.json +6 -0
  265. package/src/modules/customer_accounts/lib/customerEntityOwnership.ts +68 -2
  266. package/src/modules/customer_accounts/lib/customerUrl.ts +27 -11
  267. package/src/modules/customer_accounts/lib/invitationEmail.ts +42 -0
  268. package/src/modules/customer_accounts/migrations/.snapshot-open-mercato.json +16 -0
  269. package/src/modules/customer_accounts/migrations/Migration20260723120000_customer_accounts.ts +13 -0
  270. package/src/modules/customer_accounts/services/customerInvitationService.ts +56 -3
  271. package/src/modules/customer_accounts/subscribers/autoLinkCrm.ts +75 -8
  272. package/src/modules/customer_accounts/widgets/injection/account-status/widget.client.tsx +2 -2
  273. package/src/modules/customer_accounts/widgets/injection-table.ts +4 -1
  274. package/src/modules/customers/api/deals/[id]/people/route.ts +3 -0
  275. package/src/modules/customers/api/deals/[id]/route.ts +10 -2
  276. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +12 -1
  277. package/src/modules/customers/backend/customers/deals/[id]/hooks/types.ts +1 -0
  278. package/src/modules/customers/backend/customers/deals/[id]/page.tsx +15 -9
  279. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +24 -6
  280. package/src/modules/customers/cli.ts +17 -7
  281. package/src/modules/customers/commands/deals.ts +50 -9
  282. package/src/modules/customers/commands/people.ts +3 -0
  283. package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +30 -7
  284. package/src/modules/customers/components/detail/DealDetailTabs.tsx +34 -9
  285. package/src/modules/customers/components/detail/PersonDetailTabs.tsx +34 -9
  286. package/src/modules/customers/data/entities.ts +9 -1
  287. package/src/modules/customers/data/validators.ts +1 -0
  288. package/src/modules/customers/i18n/de.json +18 -0
  289. package/src/modules/customers/i18n/en.json +18 -0
  290. package/src/modules/customers/i18n/es.json +18 -0
  291. package/src/modules/customers/i18n/pl.json +18 -0
  292. package/src/modules/customers/migrations/.snapshot-open-mercato.json +27 -1
  293. package/src/modules/customers/migrations/Migration20260723210000_customers.ts +15 -0
  294. package/src/modules/customers/search.ts +59 -27
  295. package/src/modules/data_sync/AGENTS.md +1 -0
  296. package/src/modules/data_sync/api/mappings/[id]/route.ts +22 -9
  297. package/src/modules/data_sync/api/mappings/route.ts +13 -4
  298. package/src/modules/data_sync/api/options.ts +7 -2
  299. package/src/modules/data_sync/api/run.ts +7 -2
  300. package/src/modules/data_sync/api/runs/[id]/cancel.ts +8 -3
  301. package/src/modules/data_sync/api/runs/[id]/retry.ts +7 -2
  302. package/src/modules/data_sync/api/runs/[id]/route.ts +8 -3
  303. package/src/modules/data_sync/api/runs.ts +7 -2
  304. package/src/modules/data_sync/api/schedules/[id]/route.ts +19 -6
  305. package/src/modules/data_sync/api/schedules/route.ts +13 -4
  306. package/src/modules/data_sync/api/validate.ts +9 -4
  307. package/src/modules/design_system/AGENTS.md +34 -0
  308. package/src/modules/design_system/acl.ts +5 -0
  309. package/src/modules/design_system/backend/design-system/page.meta.ts +11 -0
  310. package/src/modules/design_system/backend/design-system/page.tsx +14 -0
  311. package/src/modules/design_system/gallery/components/CodeSnippet.tsx +55 -0
  312. package/src/modules/design_system/gallery/components/EntryCard.tsx +95 -0
  313. package/src/modules/design_system/gallery/components/GalleryShell.tsx +206 -0
  314. package/src/modules/design_system/gallery/components/VariantPreview.tsx +15 -0
  315. package/src/modules/design_system/gallery/entries/banners.tsx +226 -0
  316. package/src/modules/design_system/gallery/entries/buttons.tsx +422 -0
  317. package/src/modules/design_system/gallery/entries/charts.tsx +518 -0
  318. package/src/modules/design_system/gallery/entries/dates.tsx +325 -0
  319. package/src/modules/design_system/gallery/entries/detail.tsx +403 -0
  320. package/src/modules/design_system/gallery/entries/display.tsx +893 -0
  321. package/src/modules/design_system/gallery/entries/feedback.tsx +746 -0
  322. package/src/modules/design_system/gallery/entries/filters.tsx +570 -0
  323. package/src/modules/design_system/gallery/entries/foundations.tsx +529 -0
  324. package/src/modules/design_system/gallery/entries/icons.tsx +168 -0
  325. package/src/modules/design_system/gallery/entries/inputs.tsx +1516 -0
  326. package/src/modules/design_system/gallery/entries/messages.tsx +339 -0
  327. package/src/modules/design_system/gallery/entries/navigation.tsx +573 -0
  328. package/src/modules/design_system/gallery/entries/notifications.tsx +285 -0
  329. package/src/modules/design_system/gallery/entries/overlays.tsx +677 -0
  330. package/src/modules/design_system/gallery/entries/scaffolding.tsx +430 -0
  331. package/src/modules/design_system/gallery/entries/schedule.tsx +307 -0
  332. package/src/modules/design_system/gallery/registry.ts +152 -0
  333. package/src/modules/design_system/gallery/types.ts +32 -0
  334. package/src/modules/design_system/i18n/.hardcoded-allowlist.json +71 -0
  335. package/src/modules/design_system/i18n/de.json +46 -0
  336. package/src/modules/design_system/i18n/en.json +46 -0
  337. package/src/modules/design_system/i18n/es.json +46 -0
  338. package/src/modules/design_system/i18n/pl.json +46 -0
  339. package/src/modules/design_system/index.ts +7 -0
  340. package/src/modules/design_system/setup.ts +12 -0
  341. package/src/modules/entities/api/entity-settings.ts +66 -22
  342. package/src/modules/entities/backend/config/settings/page.meta.ts +34 -0
  343. package/src/modules/entities/backend/config/settings/page.tsx +12 -0
  344. package/src/modules/entities/backend/entities/user/create/page.tsx +16 -7
  345. package/src/modules/entities/components/EntitySettingsManager.tsx +160 -0
  346. package/src/modules/entities/i18n/de.json +9 -0
  347. package/src/modules/entities/i18n/en.json +9 -0
  348. package/src/modules/entities/i18n/es.json +9 -0
  349. package/src/modules/entities/i18n/pl.json +9 -0
  350. package/src/modules/inbox_ops/api/webhook/inbound.ts +14 -12
  351. package/src/modules/inbox_ops/i18n/de.json +3 -0
  352. package/src/modules/inbox_ops/i18n/en.json +3 -0
  353. package/src/modules/inbox_ops/i18n/es.json +3 -0
  354. package/src/modules/inbox_ops/i18n/pl.json +3 -0
  355. package/src/modules/inbox_ops/search.ts +20 -4
  356. package/src/modules/integrations/api/[id]/credentials/route.ts +11 -5
  357. package/src/modules/integrations/api/[id]/health/route.ts +6 -3
  358. package/src/modules/integrations/api/[id]/route.ts +6 -3
  359. package/src/modules/integrations/api/[id]/state/route.ts +6 -3
  360. package/src/modules/integrations/api/[id]/version/route.ts +6 -3
  361. package/src/modules/integrations/api/logs/route.ts +6 -3
  362. package/src/modules/integrations/api/route.ts +6 -3
  363. package/src/modules/integrations/api/umes-read.ts +2 -2
  364. package/src/modules/integrations/lib/organization-scope.ts +5 -25
  365. package/src/modules/messages/i18n/de.json +2 -0
  366. package/src/modules/messages/i18n/en.json +2 -0
  367. package/src/modules/messages/i18n/es.json +2 -0
  368. package/src/modules/messages/i18n/pl.json +2 -0
  369. package/src/modules/messages/search.ts +11 -5
  370. package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +13 -1
  371. package/src/modules/payment_gateways/data/entities.ts +5 -0
  372. package/src/modules/payment_gateways/i18n/de.json +5 -1
  373. package/src/modules/payment_gateways/i18n/en.json +5 -1
  374. package/src/modules/payment_gateways/i18n/es.json +5 -1
  375. package/src/modules/payment_gateways/i18n/pl.json +5 -1
  376. package/src/modules/payment_gateways/lib/gateway-service.ts +12 -2
  377. package/src/modules/payment_gateways/lib/session-idempotency.ts +36 -0
  378. package/src/modules/payment_gateways/migrations/.snapshot-open-mercato.json +10 -1
  379. package/src/modules/payment_gateways/migrations/Migration20260803103035_payment_gateways.ts +17 -0
  380. package/src/modules/payment_gateways/setup.ts +62 -0
  381. package/src/modules/payment_gateways/workers/session-initialization-prune.ts +63 -0
  382. package/src/modules/portal/frontend/[orgSlug]/portal/invite/page.meta.ts +9 -0
  383. package/src/modules/portal/frontend/[orgSlug]/portal/invite/page.tsx +164 -0
  384. package/src/modules/portal/i18n/de.json +18 -0
  385. package/src/modules/portal/i18n/en.json +18 -0
  386. package/src/modules/portal/i18n/es.json +18 -0
  387. package/src/modules/portal/i18n/pl.json +18 -0
  388. package/src/modules/portal/lib/navigation.ts +3 -0
  389. package/src/modules/query_index/data/entities.ts +7 -0
  390. package/src/modules/query_index/lib/engine.ts +92 -63
  391. package/src/modules/query_index/lib/search-tokens.ts +16 -4
  392. package/src/modules/query_index/migrations/.snapshot-open-mercato.json +12 -0
  393. package/src/modules/query_index/migrations/Migration20260731105052_query_index.ts +35 -0
  394. package/src/modules/shipping_carriers/api/webhook/[provider]/route.ts +11 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/integrations/api/route.ts"],
4
- "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { CredentialsEncryptionUnavailableError, type CredentialsService } from '../lib/credentials-service'\nimport type { IntegrationStateService } from '../lib/state-service'\nimport type { IntegrationLogService } from '../lib/log-service'\nimport { deriveIntegrationHealthStatus, getEffectiveHealthCheckConfig } from '../lib/health-service'\nimport type { IntegrationHealthDisplayStatus } from '../lib/health-service'\nimport { getAllBundles, getAllIntegrations } from '@open-mercato/shared/modules/integrations/types'\nimport { listIntegrationsQuerySchema } from '../data/validators'\nimport { buildIntegrationsCrudOpenApi, integrationsListResponseSchema } from './openapi'\nimport {\n finalizeIntegrationsReadResponse,\n integrationApiRoutePaths,\n runIntegrationsReadBeforeInterceptors,\n} from './umes-read'\nimport { resolveIntegrationsOrganizationId } from '../lib/organization-scope'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['integrations.view'] },\n}\n\nexport const openApi = buildIntegrationsCrudOpenApi({\n resourceName: 'Integration',\n pluralName: 'Integrations',\n listResponseSchema: integrationsListResponseSchema,\n querySchema: listIntegrationsQuerySchema,\n})\n\nconst HEALTH_SORT_RANK: Record<IntegrationHealthDisplayStatus, number> = {\n healthy: 0,\n degraded: 1,\n unhealthy: 2,\n unconfigured: 3,\n}\n\nfunction matchesSearchQuery(\n integration: { title: string; description?: string; tags?: string[] },\n queryNormalized: string,\n): boolean {\n if (!queryNormalized) return true\n if (integration.title.toLowerCase().includes(queryNormalized)) return true\n if (integration.description?.toLowerCase().includes(queryNormalized)) return true\n const tags = integration.tags ?? []\n return tags.some((tag) => tag.toLowerCase().includes(queryNormalized))\n}\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n const organizationId = resolveIntegrationsOrganizationId(auth)\n if (!auth?.tenantId || !organizationId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const url = new URL(req.url)\n const parsedQuery = listIntegrationsQuerySchema.safeParse(Object.fromEntries(url.searchParams.entries()))\n if (!parsedQuery.success) {\n return NextResponse.json({ error: 'Invalid query', details: parsedQuery.error.flatten() }, { status: 400 })\n }\n const query = parsedQuery.data\n\n const container = await createRequestContainer()\n const beforeInterceptors = await runIntegrationsReadBeforeInterceptors({\n routePath: integrationApiRoutePaths.list,\n request: req,\n auth,\n container,\n })\n if (!beforeInterceptors.ok) {\n return NextResponse.json(beforeInterceptors.body, { status: beforeInterceptors.statusCode })\n }\n const credentialsService = container.resolve('integrationCredentialsService') as CredentialsService\n const stateService = container.resolve('integrationStateService') as IntegrationStateService\n const logService = container.resolve('integrationLogService') as IntegrationLogService\n\n const scope = { organizationId: organizationId, tenantId: auth.tenantId as string }\n const searchNeedle = query.q?.trim().toLowerCase() ?? ''\n\n type ListRow = {\n id: string\n title: string\n description: string | null\n category: string | null\n tags: string[]\n hub: string | null\n providerKey: string | null\n bundleId: string | null\n author: string | null\n company: string | null\n version: string | null\n hasCredentials: boolean\n isEnabled: boolean\n apiVersion: string | null\n healthStatus: IntegrationHealthDisplayStatus\n lastHealthCheckedAt: string | null\n lastHealthLatencyMs: number | null\n enabledAt: string | null\n stateUpdatedAt: string | null\n sortEnabledAtMs: number\n sortTitle: string\n sortCategory: string\n }\n\n const baseRows: ListRow[] = await Promise.all(\n getAllIntegrations().map(async (integration) => {\n const [resolvedCredentials, state] = await Promise.all([\n credentialsService.resolve(integration.id, scope).catch((err) => {\n if (err instanceof CredentialsEncryptionUnavailableError) return null\n throw err\n }),\n stateService.resolveState(integration.id, scope),\n ])\n\n const hasCredentials =\n resolvedCredentials != null && Object.keys(resolvedCredentials).length > 0\n const healthConfig = getEffectiveHealthCheckConfig(integration.id)\n const hasHealthCheck = Boolean(healthConfig?.service)\n const healthStatus = deriveIntegrationHealthStatus({\n hasHealthCheck,\n hasCredentials,\n lastHealthStatus: state.lastHealthStatus,\n lastHealthCheckedAt: state.lastHealthCheckedAt,\n })\n\n const enabledAtMs = state.enabledAt?.getTime() ?? 0\n\n return {\n id: integration.id,\n title: integration.title,\n description: integration.description ?? null,\n category: integration.category ?? null,\n tags: integration.tags ?? [],\n hub: integration.hub ?? null,\n providerKey: integration.providerKey ?? null,\n bundleId: integration.bundleId ?? null,\n author: integration.author ?? null,\n company: integration.company ?? null,\n version: integration.version ?? null,\n hasCredentials,\n isEnabled: state.isEnabled,\n apiVersion: state.apiVersion,\n healthStatus,\n lastHealthCheckedAt: state.lastHealthCheckedAt?.toISOString() ?? null,\n lastHealthLatencyMs: state.lastHealthLatencyMs,\n enabledAt: state.enabledAt?.toISOString() ?? null,\n stateUpdatedAt: state.updatedAt?.toISOString() ?? null,\n sortEnabledAtMs: enabledAtMs,\n sortTitle: integration.title.toLowerCase(),\n sortCategory: (integration.category ?? '').toLowerCase(),\n }\n }),\n )\n\n let filtered = baseRows.filter((row) => matchesSearchQuery(\n { title: row.title, description: row.description ?? undefined, tags: row.tags },\n searchNeedle,\n ))\n\n if (query.category) {\n filtered = filtered.filter((row) => row.category === query.category)\n }\n if (query.bundleId) {\n filtered = filtered.filter((row) => row.bundleId === query.bundleId)\n }\n if (query.isEnabled !== undefined) {\n filtered = filtered.filter((row) => row.isEnabled === query.isEnabled)\n }\n if (query.healthStatus) {\n filtered = filtered.filter((row) => row.healthStatus === query.healthStatus)\n }\n\n const sortKey = query.sort ?? 'title'\n const orderSign = query.order === 'desc' ? -1 : 1\n\n const sorted = [...filtered].sort((rowA, rowB) => {\n let cmp = 0\n if (sortKey === 'title') {\n cmp = rowA.sortTitle.localeCompare(rowB.sortTitle)\n } else if (sortKey === 'category') {\n cmp = rowA.sortCategory.localeCompare(rowB.sortCategory)\n if (cmp === 0) cmp = rowA.sortTitle.localeCompare(rowB.sortTitle)\n } else if (sortKey === 'enabledAt') {\n cmp = rowA.sortEnabledAtMs - rowB.sortEnabledAtMs\n if (cmp === 0) cmp = rowA.sortTitle.localeCompare(rowB.sortTitle)\n } else if (sortKey === 'healthStatus') {\n cmp = HEALTH_SORT_RANK[rowA.healthStatus] - HEALTH_SORT_RANK[rowB.healthStatus]\n if (cmp === 0) cmp = rowA.sortTitle.localeCompare(rowB.sortTitle)\n }\n return cmp * orderSign\n })\n\n const total = sorted.length\n const pageSize = query.pageSize\n const page = query.page\n const totalPages = Math.max(1, Math.ceil(total / pageSize) || 1)\n const safePage = Math.min(page, totalPages)\n const offset = (safePage - 1) * pageSize\n const pageSlice = sorted.slice(offset, offset + pageSize)\n\n const analyticsMap = await logService.aggregateAnalytics(\n pageSlice.map((row) => row.id),\n scope,\n 30,\n )\n\n const items = pageSlice.map((row) => {\n const analytics = analyticsMap.get(row.id)\n return {\n id: row.id,\n title: row.title,\n description: row.description,\n category: row.category,\n tags: row.tags,\n hub: row.hub,\n providerKey: row.providerKey,\n bundleId: row.bundleId,\n author: row.author,\n company: row.company,\n version: row.version,\n hasCredentials: row.hasCredentials,\n isEnabled: row.isEnabled,\n apiVersion: row.apiVersion,\n healthStatus: row.healthStatus,\n lastHealthCheckedAt: row.lastHealthCheckedAt,\n lastHealthLatencyMs: row.lastHealthLatencyMs,\n enabledAt: row.enabledAt,\n stateUpdatedAt: row.stateUpdatedAt,\n analytics: analytics ?? {\n lastActivityAt: null,\n totalCount: 0,\n errorCount: 0,\n errorRate: 0,\n dailyCounts: Array.from({ length: 30 }, () => 0),\n },\n }\n })\n\n const bundles = getAllBundles().map((bundle) => {\n const bundleIntegrations = filtered.filter((row) => row.bundleId === bundle.id)\n const enabledCount = bundleIntegrations.reduce((count, integration) => count + (integration.isEnabled ? 1 : 0), 0)\n\n return {\n id: bundle.id,\n title: bundle.title,\n description: bundle.description,\n icon: bundle.icon ?? null,\n integrationCount: bundleIntegrations.length,\n enabledCount,\n }\n })\n\n return finalizeIntegrationsReadResponse({\n routePath: integrationApiRoutePaths.list,\n request: req,\n auth,\n container,\n interceptorRequest: beforeInterceptors.request,\n beforeMetadata: beforeInterceptors.metadataByInterceptor,\n enrich: {\n targetEntity: 'integrations.integration',\n listKeys: ['items'],\n },\n body: {\n items,\n bundles,\n total,\n page: safePage,\n pageSize,\n totalPages,\n },\n })\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { CredentialsEncryptionUnavailableError, type CredentialsService } from '../lib/credentials-service'\nimport type { IntegrationStateService } from '../lib/state-service'\nimport type { IntegrationLogService } from '../lib/log-service'\nimport { deriveIntegrationHealthStatus, getEffectiveHealthCheckConfig } from '../lib/health-service'\nimport type { IntegrationHealthDisplayStatus } from '../lib/health-service'\nimport { getAllBundles, getAllIntegrations } from '@open-mercato/shared/modules/integrations/types'\nimport { listIntegrationsQuerySchema } from '../data/validators'\nimport { buildIntegrationsCrudOpenApi, integrationsListResponseSchema } from './openapi'\nimport {\n finalizeIntegrationsReadResponse,\n integrationApiRoutePaths,\n runIntegrationsReadBeforeInterceptors,\n} from './umes-read'\nimport { organizationScopeRequiredResponse, resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['integrations.view'] },\n}\n\nexport const openApi = buildIntegrationsCrudOpenApi({\n resourceName: 'Integration',\n pluralName: 'Integrations',\n listResponseSchema: integrationsListResponseSchema,\n querySchema: listIntegrationsQuerySchema,\n})\n\nconst HEALTH_SORT_RANK: Record<IntegrationHealthDisplayStatus, number> = {\n healthy: 0,\n degraded: 1,\n unhealthy: 2,\n unconfigured: 3,\n}\n\nfunction matchesSearchQuery(\n integration: { title: string; description?: string; tags?: string[] },\n queryNormalized: string,\n): boolean {\n if (!queryNormalized) return true\n if (integration.title.toLowerCase().includes(queryNormalized)) return true\n if (integration.description?.toLowerCase().includes(queryNormalized)) return true\n const tags = integration.tags ?? []\n return tags.some((tag) => tag.toLowerCase().includes(queryNormalized))\n}\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n const organizationId = resolveActiveOrganizationId(auth)\n if (!organizationId) {\n return organizationScopeRequiredResponse()\n }\n\n const url = new URL(req.url)\n const parsedQuery = listIntegrationsQuerySchema.safeParse(Object.fromEntries(url.searchParams.entries()))\n if (!parsedQuery.success) {\n return NextResponse.json({ error: 'Invalid query', details: parsedQuery.error.flatten() }, { status: 400 })\n }\n const query = parsedQuery.data\n\n const container = await createRequestContainer()\n const beforeInterceptors = await runIntegrationsReadBeforeInterceptors({\n routePath: integrationApiRoutePaths.list,\n request: req,\n auth,\n container,\n })\n if (!beforeInterceptors.ok) {\n return NextResponse.json(beforeInterceptors.body, { status: beforeInterceptors.statusCode })\n }\n const credentialsService = container.resolve('integrationCredentialsService') as CredentialsService\n const stateService = container.resolve('integrationStateService') as IntegrationStateService\n const logService = container.resolve('integrationLogService') as IntegrationLogService\n\n const scope = { organizationId: organizationId, tenantId: auth.tenantId as string }\n const searchNeedle = query.q?.trim().toLowerCase() ?? ''\n\n type ListRow = {\n id: string\n title: string\n description: string | null\n category: string | null\n tags: string[]\n hub: string | null\n providerKey: string | null\n bundleId: string | null\n author: string | null\n company: string | null\n version: string | null\n hasCredentials: boolean\n isEnabled: boolean\n apiVersion: string | null\n healthStatus: IntegrationHealthDisplayStatus\n lastHealthCheckedAt: string | null\n lastHealthLatencyMs: number | null\n enabledAt: string | null\n stateUpdatedAt: string | null\n sortEnabledAtMs: number\n sortTitle: string\n sortCategory: string\n }\n\n const baseRows: ListRow[] = await Promise.all(\n getAllIntegrations().map(async (integration) => {\n const [resolvedCredentials, state] = await Promise.all([\n credentialsService.resolve(integration.id, scope).catch((err) => {\n if (err instanceof CredentialsEncryptionUnavailableError) return null\n throw err\n }),\n stateService.resolveState(integration.id, scope),\n ])\n\n const hasCredentials =\n resolvedCredentials != null && Object.keys(resolvedCredentials).length > 0\n const healthConfig = getEffectiveHealthCheckConfig(integration.id)\n const hasHealthCheck = Boolean(healthConfig?.service)\n const healthStatus = deriveIntegrationHealthStatus({\n hasHealthCheck,\n hasCredentials,\n lastHealthStatus: state.lastHealthStatus,\n lastHealthCheckedAt: state.lastHealthCheckedAt,\n })\n\n const enabledAtMs = state.enabledAt?.getTime() ?? 0\n\n return {\n id: integration.id,\n title: integration.title,\n description: integration.description ?? null,\n category: integration.category ?? null,\n tags: integration.tags ?? [],\n hub: integration.hub ?? null,\n providerKey: integration.providerKey ?? null,\n bundleId: integration.bundleId ?? null,\n author: integration.author ?? null,\n company: integration.company ?? null,\n version: integration.version ?? null,\n hasCredentials,\n isEnabled: state.isEnabled,\n apiVersion: state.apiVersion,\n healthStatus,\n lastHealthCheckedAt: state.lastHealthCheckedAt?.toISOString() ?? null,\n lastHealthLatencyMs: state.lastHealthLatencyMs,\n enabledAt: state.enabledAt?.toISOString() ?? null,\n stateUpdatedAt: state.updatedAt?.toISOString() ?? null,\n sortEnabledAtMs: enabledAtMs,\n sortTitle: integration.title.toLowerCase(),\n sortCategory: (integration.category ?? '').toLowerCase(),\n }\n }),\n )\n\n let filtered = baseRows.filter((row) => matchesSearchQuery(\n { title: row.title, description: row.description ?? undefined, tags: row.tags },\n searchNeedle,\n ))\n\n if (query.category) {\n filtered = filtered.filter((row) => row.category === query.category)\n }\n if (query.bundleId) {\n filtered = filtered.filter((row) => row.bundleId === query.bundleId)\n }\n if (query.isEnabled !== undefined) {\n filtered = filtered.filter((row) => row.isEnabled === query.isEnabled)\n }\n if (query.healthStatus) {\n filtered = filtered.filter((row) => row.healthStatus === query.healthStatus)\n }\n\n const sortKey = query.sort ?? 'title'\n const orderSign = query.order === 'desc' ? -1 : 1\n\n const sorted = [...filtered].sort((rowA, rowB) => {\n let cmp = 0\n if (sortKey === 'title') {\n cmp = rowA.sortTitle.localeCompare(rowB.sortTitle)\n } else if (sortKey === 'category') {\n cmp = rowA.sortCategory.localeCompare(rowB.sortCategory)\n if (cmp === 0) cmp = rowA.sortTitle.localeCompare(rowB.sortTitle)\n } else if (sortKey === 'enabledAt') {\n cmp = rowA.sortEnabledAtMs - rowB.sortEnabledAtMs\n if (cmp === 0) cmp = rowA.sortTitle.localeCompare(rowB.sortTitle)\n } else if (sortKey === 'healthStatus') {\n cmp = HEALTH_SORT_RANK[rowA.healthStatus] - HEALTH_SORT_RANK[rowB.healthStatus]\n if (cmp === 0) cmp = rowA.sortTitle.localeCompare(rowB.sortTitle)\n }\n return cmp * orderSign\n })\n\n const total = sorted.length\n const pageSize = query.pageSize\n const page = query.page\n const totalPages = Math.max(1, Math.ceil(total / pageSize) || 1)\n const safePage = Math.min(page, totalPages)\n const offset = (safePage - 1) * pageSize\n const pageSlice = sorted.slice(offset, offset + pageSize)\n\n const analyticsMap = await logService.aggregateAnalytics(\n pageSlice.map((row) => row.id),\n scope,\n 30,\n )\n\n const items = pageSlice.map((row) => {\n const analytics = analyticsMap.get(row.id)\n return {\n id: row.id,\n title: row.title,\n description: row.description,\n category: row.category,\n tags: row.tags,\n hub: row.hub,\n providerKey: row.providerKey,\n bundleId: row.bundleId,\n author: row.author,\n company: row.company,\n version: row.version,\n hasCredentials: row.hasCredentials,\n isEnabled: row.isEnabled,\n apiVersion: row.apiVersion,\n healthStatus: row.healthStatus,\n lastHealthCheckedAt: row.lastHealthCheckedAt,\n lastHealthLatencyMs: row.lastHealthLatencyMs,\n enabledAt: row.enabledAt,\n stateUpdatedAt: row.stateUpdatedAt,\n analytics: analytics ?? {\n lastActivityAt: null,\n totalCount: 0,\n errorCount: 0,\n errorRate: 0,\n dailyCounts: Array.from({ length: 30 }, () => 0),\n },\n }\n })\n\n const bundles = getAllBundles().map((bundle) => {\n const bundleIntegrations = filtered.filter((row) => row.bundleId === bundle.id)\n const enabledCount = bundleIntegrations.reduce((count, integration) => count + (integration.isEnabled ? 1 : 0), 0)\n\n return {\n id: bundle.id,\n title: bundle.title,\n description: bundle.description,\n icon: bundle.icon ?? null,\n integrationCount: bundleIntegrations.length,\n enabledCount,\n }\n })\n\n return finalizeIntegrationsReadResponse({\n routePath: integrationApiRoutePaths.list,\n request: req,\n auth,\n container,\n interceptorRequest: beforeInterceptors.request,\n beforeMetadata: beforeInterceptors.metadataByInterceptor,\n enrich: {\n targetEntity: 'integrations.integration',\n listKeys: ['items'],\n },\n body: {\n items,\n bundles,\n total,\n page: safePage,\n pageSize,\n totalPages,\n },\n })\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  import { NextResponse } from "next/server";
2
2
  import { runApiInterceptorsAfter, runApiInterceptorsBefore } from "@open-mercato/shared/lib/crud/interceptor-runner";
3
3
  import { applyResponseEnrichers, applyResponseEnricherToRecord } from "@open-mercato/shared/lib/crud/enricher-runner";
4
- import { resolveIntegrationsOrganizationId } from "../lib/organization-scope.js";
4
+ import { resolveActiveOrganizationId } from "@open-mercato/shared/lib/auth/organizationScope";
5
5
  const integrationApiRoutePaths = {
6
6
  list: "integrations",
7
7
  detail: "integrations/detail",
@@ -35,7 +35,7 @@ function mergeAdditiveBody(baseBody, candidateBody) {
35
35
  }
36
36
  function getEnricherContext(input) {
37
37
  return {
38
- organizationId: resolveIntegrationsOrganizationId(input.auth),
38
+ organizationId: resolveActiveOrganizationId(input.auth),
39
39
  tenantId: input.auth.tenantId,
40
40
  userId: input.auth.sub ?? "",
41
41
  em: input.container.resolve("em"),
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/integrations/api/umes-read.ts"],
4
- "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { NextResponse } from 'next/server'\nimport type { AwilixContainer } from 'awilix'\nimport { runApiInterceptorsAfter, runApiInterceptorsBefore, type RunInterceptorsBeforeResult } from '@open-mercato/shared/lib/crud/interceptor-runner'\nimport { applyResponseEnrichers, applyResponseEnricherToRecord } from '@open-mercato/shared/lib/crud/enricher-runner'\nimport type { ApiInterceptorMethod, InterceptorRequest } from '@open-mercato/shared/lib/crud/api-interceptor'\nimport { resolveIntegrationsOrganizationId } from '../lib/organization-scope'\n\nexport const integrationApiRoutePaths = {\n list: 'integrations',\n detail: 'integrations/detail',\n logs: 'integrations/logs',\n} as const\n\ntype ReadRouteFieldConfig = {\n targetEntity: string\n recordKeys?: string[]\n listKeys?: string[]\n}\n\ntype ReadRouteContext = {\n routePath: string\n request: Request\n auth: {\n tenantId: string | null\n orgId: string | null\n sub?: string | null\n features?: unknown\n }\n container: AwilixContainer\n}\n\nfunction headersToObject(headers: Headers): Record<string, string> {\n return Object.fromEntries(headers.entries())\n}\n\nfunction searchParamsToObject(url: URL): Record<string, string> {\n const entries: Record<string, string> = {}\n url.searchParams.forEach((value, key) => {\n entries[key] = value\n })\n return entries\n}\n\nfunction toUserFeatures(features: unknown): string[] {\n if (!Array.isArray(features)) return []\n return features.filter((value): value is string => typeof value === 'string')\n}\n\nfunction mergeAdditiveRecord<T extends Record<string, unknown>>(base: T, candidate: T): T {\n const additions = Object.fromEntries(\n Object.entries(candidate).filter(([key]) => !(key in base)),\n ) as Partial<T>\n\n return {\n ...base,\n ...additions,\n }\n}\n\nfunction mergeAdditiveBody(\n baseBody: Record<string, unknown>,\n candidateBody: Record<string, unknown>,\n): Record<string, unknown> {\n return mergeAdditiveRecord(baseBody, candidateBody)\n}\n\nfunction getEnricherContext(input: ReadRouteContext) {\n return {\n organizationId: resolveIntegrationsOrganizationId(input.auth) as string,\n tenantId: input.auth.tenantId as string,\n userId: input.auth.sub ?? '',\n em: input.container.resolve('em') as EntityManager,\n container: input.container,\n userFeatures: toUserFeatures(input.auth.features),\n }\n}\n\nexport async function runIntegrationsReadBeforeInterceptors(\n input: ReadRouteContext,\n): Promise<RunInterceptorsBeforeResult> {\n const url = new URL(input.request.url)\n\n return runApiInterceptorsBefore({\n routePath: input.routePath,\n method: 'GET',\n request: {\n method: 'GET',\n url: input.request.url,\n headers: headersToObject(input.request.headers),\n query: searchParamsToObject(url),\n },\n context: getEnricherContext(input),\n })\n}\n\nasync function applySafeRecordEnrichment(\n record: Record<string, unknown>,\n targetEntity: string,\n context: ReturnType<typeof getEnricherContext>,\n): Promise<Record<string, unknown>> {\n const enriched = await applyResponseEnricherToRecord(record, targetEntity, context)\n return mergeAdditiveRecord(record, enriched.record)\n}\n\nasync function applySafeListEnrichment(\n items: Record<string, unknown>[],\n targetEntity: string,\n context: ReturnType<typeof getEnricherContext>,\n): Promise<Record<string, unknown>[]> {\n const enriched = await applyResponseEnrichers(items, targetEntity, context)\n return items.map((item, index) => {\n const enrichedItem = enriched.items[index]\n if (!enrichedItem) return item\n return mergeAdditiveRecord(item, enrichedItem)\n })\n}\n\nexport async function finalizeIntegrationsReadResponse(\n input: ReadRouteContext & {\n interceptorRequest: InterceptorRequest\n body: Record<string, unknown>\n enrich?: ReadRouteFieldConfig\n method?: ApiInterceptorMethod\n beforeMetadata?: Record<string, Record<string, unknown> | undefined>\n },\n): Promise<NextResponse> {\n const method = input.method ?? 'GET'\n const baseBody = input.body\n const context = getEnricherContext(input)\n\n const intercepted = await runApiInterceptorsAfter({\n routePath: input.routePath,\n method,\n request: input.interceptorRequest,\n response: {\n statusCode: 200,\n body: baseBody,\n headers: {},\n },\n context,\n metadataByInterceptor: input.beforeMetadata,\n })\n\n if (!intercepted.ok) {\n return NextResponse.json(intercepted.body, { status: intercepted.statusCode, headers: intercepted.headers })\n }\n\n let responseBody = mergeAdditiveBody(baseBody, intercepted.body)\n\n if (input.enrich) {\n const { targetEntity, recordKeys = [], listKeys = [] } = input.enrich\n\n for (const key of recordKeys) {\n const current = responseBody[key]\n if (!current || typeof current !== 'object' || Array.isArray(current)) continue\n responseBody = {\n ...responseBody,\n [key]: await applySafeRecordEnrichment(current as Record<string, unknown>, targetEntity, context),\n }\n }\n\n for (const key of listKeys) {\n const current = responseBody[key]\n if (!Array.isArray(current)) continue\n const records = current.filter(\n (item): item is Record<string, unknown> => typeof item === 'object' && item !== null && !Array.isArray(item),\n )\n if (records.length !== current.length) continue\n responseBody = {\n ...responseBody,\n [key]: await applySafeListEnrichment(records, targetEntity, context),\n }\n }\n }\n\n return NextResponse.json(responseBody, { headers: intercepted.headers })\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { NextResponse } from 'next/server'\nimport type { AwilixContainer } from 'awilix'\nimport { runApiInterceptorsAfter, runApiInterceptorsBefore, type RunInterceptorsBeforeResult } from '@open-mercato/shared/lib/crud/interceptor-runner'\nimport { applyResponseEnrichers, applyResponseEnricherToRecord } from '@open-mercato/shared/lib/crud/enricher-runner'\nimport type { ApiInterceptorMethod, InterceptorRequest } from '@open-mercato/shared/lib/crud/api-interceptor'\nimport { resolveActiveOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'\n\nexport const integrationApiRoutePaths = {\n list: 'integrations',\n detail: 'integrations/detail',\n logs: 'integrations/logs',\n} as const\n\ntype ReadRouteFieldConfig = {\n targetEntity: string\n recordKeys?: string[]\n listKeys?: string[]\n}\n\ntype ReadRouteContext = {\n routePath: string\n request: Request\n auth: {\n tenantId: string | null\n orgId: string | null\n sub?: string | null\n features?: unknown\n }\n container: AwilixContainer\n}\n\nfunction headersToObject(headers: Headers): Record<string, string> {\n return Object.fromEntries(headers.entries())\n}\n\nfunction searchParamsToObject(url: URL): Record<string, string> {\n const entries: Record<string, string> = {}\n url.searchParams.forEach((value, key) => {\n entries[key] = value\n })\n return entries\n}\n\nfunction toUserFeatures(features: unknown): string[] {\n if (!Array.isArray(features)) return []\n return features.filter((value): value is string => typeof value === 'string')\n}\n\nfunction mergeAdditiveRecord<T extends Record<string, unknown>>(base: T, candidate: T): T {\n const additions = Object.fromEntries(\n Object.entries(candidate).filter(([key]) => !(key in base)),\n ) as Partial<T>\n\n return {\n ...base,\n ...additions,\n }\n}\n\nfunction mergeAdditiveBody(\n baseBody: Record<string, unknown>,\n candidateBody: Record<string, unknown>,\n): Record<string, unknown> {\n return mergeAdditiveRecord(baseBody, candidateBody)\n}\n\nfunction getEnricherContext(input: ReadRouteContext) {\n return {\n organizationId: resolveActiveOrganizationId(input.auth) as string,\n tenantId: input.auth.tenantId as string,\n userId: input.auth.sub ?? '',\n em: input.container.resolve('em') as EntityManager,\n container: input.container,\n userFeatures: toUserFeatures(input.auth.features),\n }\n}\n\nexport async function runIntegrationsReadBeforeInterceptors(\n input: ReadRouteContext,\n): Promise<RunInterceptorsBeforeResult> {\n const url = new URL(input.request.url)\n\n return runApiInterceptorsBefore({\n routePath: input.routePath,\n method: 'GET',\n request: {\n method: 'GET',\n url: input.request.url,\n headers: headersToObject(input.request.headers),\n query: searchParamsToObject(url),\n },\n context: getEnricherContext(input),\n })\n}\n\nasync function applySafeRecordEnrichment(\n record: Record<string, unknown>,\n targetEntity: string,\n context: ReturnType<typeof getEnricherContext>,\n): Promise<Record<string, unknown>> {\n const enriched = await applyResponseEnricherToRecord(record, targetEntity, context)\n return mergeAdditiveRecord(record, enriched.record)\n}\n\nasync function applySafeListEnrichment(\n items: Record<string, unknown>[],\n targetEntity: string,\n context: ReturnType<typeof getEnricherContext>,\n): Promise<Record<string, unknown>[]> {\n const enriched = await applyResponseEnrichers(items, targetEntity, context)\n return items.map((item, index) => {\n const enrichedItem = enriched.items[index]\n if (!enrichedItem) return item\n return mergeAdditiveRecord(item, enrichedItem)\n })\n}\n\nexport async function finalizeIntegrationsReadResponse(\n input: ReadRouteContext & {\n interceptorRequest: InterceptorRequest\n body: Record<string, unknown>\n enrich?: ReadRouteFieldConfig\n method?: ApiInterceptorMethod\n beforeMetadata?: Record<string, Record<string, unknown> | undefined>\n },\n): Promise<NextResponse> {\n const method = input.method ?? 'GET'\n const baseBody = input.body\n const context = getEnricherContext(input)\n\n const intercepted = await runApiInterceptorsAfter({\n routePath: input.routePath,\n method,\n request: input.interceptorRequest,\n response: {\n statusCode: 200,\n body: baseBody,\n headers: {},\n },\n context,\n metadataByInterceptor: input.beforeMetadata,\n })\n\n if (!intercepted.ok) {\n return NextResponse.json(intercepted.body, { status: intercepted.statusCode, headers: intercepted.headers })\n }\n\n let responseBody = mergeAdditiveBody(baseBody, intercepted.body)\n\n if (input.enrich) {\n const { targetEntity, recordKeys = [], listKeys = [] } = input.enrich\n\n for (const key of recordKeys) {\n const current = responseBody[key]\n if (!current || typeof current !== 'object' || Array.isArray(current)) continue\n responseBody = {\n ...responseBody,\n [key]: await applySafeRecordEnrichment(current as Record<string, unknown>, targetEntity, context),\n }\n }\n\n for (const key of listKeys) {\n const current = responseBody[key]\n if (!Array.isArray(current)) continue\n const records = current.filter(\n (item): item is Record<string, unknown> => typeof item === 'object' && item !== null && !Array.isArray(item),\n )\n if (records.length !== current.length) continue\n responseBody = {\n ...responseBody,\n [key]: await applySafeListEnrichment(records, targetEntity, context),\n }\n }\n }\n\n return NextResponse.json(responseBody, { headers: intercepted.headers })\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,12 +1,5 @@
1
- function resolveIntegrationsOrganizationId(auth) {
2
- if (!auth) return null;
3
- const selected = auth.orgId;
4
- if (typeof selected === "string" && selected.trim().length > 0) return selected;
5
- const actorOrgId = auth.actorOrgId;
6
- if (typeof actorOrgId === "string" && actorOrgId.trim().length > 0) return actorOrgId;
7
- return null;
8
- }
1
+ import { resolveActiveOrganizationId } from "@open-mercato/shared/lib/auth/organizationScope";
9
2
  export {
10
- resolveIntegrationsOrganizationId
3
+ resolveActiveOrganizationId as resolveIntegrationsOrganizationId
11
4
  };
12
5
  //# sourceMappingURL=organization-scope.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/integrations/lib/organization-scope.ts"],
4
- "sourcesContent": ["type OrganizationScopedAuth = {\n orgId?: string | null\n actorOrgId?: unknown\n} | null | undefined\n\n/**\n * Resolves the organization an integrations request is scoped to.\n *\n * Integrations are configured per organization \u2014 `integration_credentials` and\n * `integration_states` both require a non-null `organization_id` \u2014 so there is no\n * meaningful \"all organizations\" view of this module. When an operator selects that\n * option the super-admin cookie override clears `auth.orgId` and preserves the actor's\n * own organization in `actorOrgId`; fall back to it so the module keeps showing the\n * operator's own configuration instead of failing.\n *\n * Answering 401 for that case is not merely wrong but self-perpetuating: `apiFetch`\n * reads 401 as an expired session and redirects through `/api/auth/session/refresh`,\n * which succeeds and returns to the same page, reloading forever.\n */\nexport function resolveIntegrationsOrganizationId(auth: OrganizationScopedAuth): string | null {\n if (!auth) return null\n const selected = auth.orgId\n if (typeof selected === 'string' && selected.trim().length > 0) return selected\n const actorOrgId = auth.actorOrgId\n if (typeof actorOrgId === 'string' && actorOrgId.trim().length > 0) return actorOrgId\n return null\n}\n"],
5
- "mappings": "AAmBO,SAAS,kCAAkC,MAA6C;AAC7F,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,WAAW,KAAK;AACtB,MAAI,OAAO,aAAa,YAAY,SAAS,KAAK,EAAE,SAAS,EAAG,QAAO;AACvE,QAAM,aAAa,KAAK;AACxB,MAAI,OAAO,eAAe,YAAY,WAAW,KAAK,EAAE,SAAS,EAAG,QAAO;AAC3E,SAAO;AACT;",
4
+ "sourcesContent": ["/**\n * @deprecated Moved to `@open-mercato/shared/lib/auth/organizationScope` as\n * `resolveActiveOrganizationId`, because `data_sync` needs the same resolution and\n * `integrations` is not the right owner for it. This alias stays for third-party\n * modules that already import from here.\n */\nexport { resolveActiveOrganizationId as resolveIntegrationsOrganizationId } from '@open-mercato/shared/lib/auth/organizationScope'\n"],
5
+ "mappings": "AAMA,SAAwC,mCAAyC;",
6
6
  "names": []
7
7
  }
@@ -1,3 +1,4 @@
1
+ import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
1
2
  function appendLine(lines, label, value) {
2
3
  if (value === null || value === void 0) return;
3
4
  const text = Array.isArray(value) ? value.map((item) => item === null || item === void 0 ? "" : String(item)).filter(Boolean).join(", ") : typeof value === "object" ? JSON.stringify(value) : String(value);
@@ -19,8 +20,8 @@ function snippet(value, max = 140) {
19
20
  if (trimmed.length <= max) return trimmed;
20
21
  return `${trimmed.slice(0, max - 3)}...`;
21
22
  }
22
- function buildMessagePresenter(record) {
23
- const title = pickString(record.subject) ?? "Message";
23
+ function buildMessagePresenter(translate, record) {
24
+ const title = pickString(record.subject) ?? translate("messages.search.fallback.title", "Message");
24
25
  const body = snippet(record.body);
25
26
  const externalName = pickString(record.external_name, record.externalName);
26
27
  const subtitle = [externalName, body].filter(Boolean).join(" \xB7 ") || void 0;
@@ -28,7 +29,7 @@ function buildMessagePresenter(record) {
28
29
  title: String(title),
29
30
  subtitle,
30
31
  icon: "mail",
31
- badge: "Message"
32
+ badge: translate("messages.search.badge.message", "Message")
32
33
  };
33
34
  }
34
35
  const searchConfig = {
@@ -38,6 +39,7 @@ const searchConfig = {
38
39
  enabled: true,
39
40
  priority: 5,
40
41
  buildSource: async (ctx) => {
42
+ const { t } = await resolveTranslations();
41
43
  const record = ctx.record;
42
44
  const lines = [];
43
45
  appendLine(lines, "Subject", record.subject);
@@ -46,7 +48,7 @@ const searchConfig = {
46
48
  if (!lines.length) return null;
47
49
  return {
48
50
  text: lines,
49
- presenter: buildMessagePresenter(record),
51
+ presenter: buildMessagePresenter(t, record),
50
52
  checksumSource: {
51
53
  record: {
52
54
  subject: record.subject,
@@ -57,7 +59,10 @@ const searchConfig = {
57
59
  }
58
60
  };
59
61
  },
60
- formatResult: async (ctx) => buildMessagePresenter(ctx.record),
62
+ formatResult: async (ctx) => {
63
+ const { t } = await resolveTranslations();
64
+ return buildMessagePresenter(t, ctx.record);
65
+ },
61
66
  resolveUrl: async (ctx) => {
62
67
  const id = pickString(ctx.record.id);
63
68
  return id ? `/backend/messages/${encodeURIComponent(id)}` : null;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/modules/messages/search.ts"],
4
- "sourcesContent": ["import type {\n SearchModuleConfig,\n SearchBuildContext,\n SearchIndexSource,\n SearchResultPresenter,\n} from '@open-mercato/shared/modules/search'\n\nfunction appendLine(lines: string[], label: string, value: unknown) {\n if (value === null || value === undefined) return\n const text = Array.isArray(value)\n ? value.map((item) => (item === null || item === undefined ? '' : String(item))).filter(Boolean).join(', ')\n : (typeof value === 'object' ? JSON.stringify(value) : String(value))\n if (!text.trim()) return\n lines.push(`${label}: ${text}`)\n}\n\nfunction pickString(...candidates: Array<unknown>): string | null {\n for (const candidate of candidates) {\n if (typeof candidate !== 'string') continue\n const trimmed = candidate.trim()\n if (trimmed.length > 0) return trimmed\n }\n return null\n}\n\nfunction snippet(value: unknown, max = 140): string | undefined {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n if (!trimmed.length) return undefined\n if (trimmed.length <= max) return trimmed\n return `${trimmed.slice(0, max - 3)}...`\n}\n\nfunction buildMessagePresenter(record: Record<string, unknown>): SearchResultPresenter {\n const title = pickString(record.subject) ?? 'Message'\n const body = snippet(record.body)\n const externalName = pickString(record.external_name, record.externalName)\n const subtitle = [externalName, body].filter(Boolean).join(' \u00B7 ') || undefined\n return {\n title: String(title),\n subtitle,\n icon: 'mail',\n badge: 'Message',\n }\n}\n\nexport const searchConfig: SearchModuleConfig = {\n entities: [\n {\n entityId: 'messages:message',\n enabled: true,\n priority: 5,\n buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Subject', record.subject)\n appendLine(lines, 'Body', record.body)\n appendLine(lines, 'From name', record.external_name ?? record.externalName)\n if (!lines.length) return null\n return {\n text: lines,\n presenter: buildMessagePresenter(record),\n checksumSource: {\n record: {\n subject: record.subject,\n body: record.body,\n external_name: record.external_name ?? record.externalName,\n external_email_hash: record.external_email_hash ?? record.externalEmailHash,\n },\n },\n }\n },\n formatResult: async (ctx) => buildMessagePresenter(ctx.record),\n resolveUrl: async (ctx) => {\n const id = pickString(ctx.record.id)\n return id ? `/backend/messages/${encodeURIComponent(id)}` : null\n },\n fieldPolicy: {\n searchable: ['subject', 'body', 'external_name'],\n hashOnly: ['external_email'],\n excluded: ['action_data', 'action_result'],\n },\n },\n ],\n}\n\nexport default searchConfig\nexport const config = searchConfig\n"],
5
- "mappings": "AAOA,SAAS,WAAW,OAAiB,OAAe,OAAgB;AAClE,MAAI,UAAU,QAAQ,UAAU,OAAW;AAC3C,QAAM,OAAO,MAAM,QAAQ,KAAK,IAC5B,MAAM,IAAI,CAAC,SAAU,SAAS,QAAQ,SAAS,SAAY,KAAK,OAAO,IAAI,CAAE,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,IACvG,OAAO,UAAU,WAAW,KAAK,UAAU,KAAK,IAAI,OAAO,KAAK;AACrE,MAAI,CAAC,KAAK,KAAK,EAAG;AAClB,QAAM,KAAK,GAAG,KAAK,KAAK,IAAI,EAAE;AAChC;AAEA,SAAS,cAAc,YAA2C;AAChE,aAAW,aAAa,YAAY;AAClC,QAAI,OAAO,cAAc,SAAU;AACnC,UAAM,UAAU,UAAU,KAAK;AAC/B,QAAI,QAAQ,SAAS,EAAG,QAAO;AAAA,EACjC;AACA,SAAO;AACT;AAEA,SAAS,QAAQ,OAAgB,MAAM,KAAyB;AAC9D,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,MAAI,QAAQ,UAAU,IAAK,QAAO;AAClC,SAAO,GAAG,QAAQ,MAAM,GAAG,MAAM,CAAC,CAAC;AACrC;AAEA,SAAS,sBAAsB,QAAwD;AACrF,QAAM,QAAQ,WAAW,OAAO,OAAO,KAAK;AAC5C,QAAM,OAAO,QAAQ,OAAO,IAAI;AAChC,QAAM,eAAe,WAAW,OAAO,eAAe,OAAO,YAAY;AACzE,QAAM,WAAW,CAAC,cAAc,IAAI,EAAE,OAAO,OAAO,EAAE,KAAK,QAAK,KAAK;AACrE,SAAO;AAAA,IACL,OAAO,OAAO,KAAK;AAAA,IACnB;AAAA,IACA,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AACF;AAEO,MAAM,eAAmC;AAAA,EAC9C,UAAU;AAAA,IACR;AAAA,MACE,UAAU;AAAA,MACV,SAAS;AAAA,MACT,UAAU;AAAA,MACV,aAAa,OAAO,QAA+D;AACjF,cAAM,SAAS,IAAI;AACnB,cAAM,QAAkB,CAAC;AACzB,mBAAW,OAAO,WAAW,OAAO,OAAO;AAC3C,mBAAW,OAAO,QAAQ,OAAO,IAAI;AACrC,mBAAW,OAAO,aAAa,OAAO,iBAAiB,OAAO,YAAY;AAC1E,YAAI,CAAC,MAAM,OAAQ,QAAO;AAC1B,eAAO;AAAA,UACL,MAAM;AAAA,UACN,WAAW,sBAAsB,MAAM;AAAA,UACvC,gBAAgB;AAAA,YACd,QAAQ;AAAA,cACN,SAAS,OAAO;AAAA,cAChB,MAAM,OAAO;AAAA,cACb,eAAe,OAAO,iBAAiB,OAAO;AAAA,cAC9C,qBAAqB,OAAO,uBAAuB,OAAO;AAAA,YAC5D;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,MACA,cAAc,OAAO,QAAQ,sBAAsB,IAAI,MAAM;AAAA,MAC7D,YAAY,OAAO,QAAQ;AACzB,cAAM,KAAK,WAAW,IAAI,OAAO,EAAE;AACnC,eAAO,KAAK,qBAAqB,mBAAmB,EAAE,CAAC,KAAK;AAAA,MAC9D;AAAA,MACA,aAAa;AAAA,QACX,YAAY,CAAC,WAAW,QAAQ,eAAe;AAAA,QAC/C,UAAU,CAAC,gBAAgB;AAAA,QAC3B,UAAU,CAAC,eAAe,eAAe;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,iBAAQ;AACR,MAAM,SAAS;",
4
+ "sourcesContent": ["import type {\n SearchModuleConfig,\n SearchBuildContext,\n SearchIndexSource,\n SearchResultPresenter,\n} from '@open-mercato/shared/modules/search'\nimport type { TranslateFn } from '@open-mercato/shared/lib/i18n/context'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\n\nfunction appendLine(lines: string[], label: string, value: unknown) {\n if (value === null || value === undefined) return\n const text = Array.isArray(value)\n ? value.map((item) => (item === null || item === undefined ? '' : String(item))).filter(Boolean).join(', ')\n : (typeof value === 'object' ? JSON.stringify(value) : String(value))\n if (!text.trim()) return\n lines.push(`${label}: ${text}`)\n}\n\nfunction pickString(...candidates: Array<unknown>): string | null {\n for (const candidate of candidates) {\n if (typeof candidate !== 'string') continue\n const trimmed = candidate.trim()\n if (trimmed.length > 0) return trimmed\n }\n return null\n}\n\nfunction snippet(value: unknown, max = 140): string | undefined {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n if (!trimmed.length) return undefined\n if (trimmed.length <= max) return trimmed\n return `${trimmed.slice(0, max - 3)}...`\n}\n\nfunction buildMessagePresenter(translate: TranslateFn, record: Record<string, unknown>): SearchResultPresenter {\n const title = pickString(record.subject) ?? translate('messages.search.fallback.title', 'Message')\n const body = snippet(record.body)\n const externalName = pickString(record.external_name, record.externalName)\n const subtitle = [externalName, body].filter(Boolean).join(' \u00B7 ') || undefined\n return {\n title: String(title),\n subtitle,\n icon: 'mail',\n badge: translate('messages.search.badge.message', 'Message'),\n }\n}\n\nexport const searchConfig: SearchModuleConfig = {\n entities: [\n {\n entityId: 'messages:message',\n enabled: true,\n priority: 5,\n buildSource: async (ctx: SearchBuildContext): Promise<SearchIndexSource | null> => {\n const { t } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Subject', record.subject)\n appendLine(lines, 'Body', record.body)\n appendLine(lines, 'From name', record.external_name ?? record.externalName)\n if (!lines.length) return null\n return {\n text: lines,\n presenter: buildMessagePresenter(t, record),\n checksumSource: {\n record: {\n subject: record.subject,\n body: record.body,\n external_name: record.external_name ?? record.externalName,\n external_email_hash: record.external_email_hash ?? record.externalEmailHash,\n },\n },\n }\n },\n formatResult: async (ctx) => {\n const { t } = await resolveTranslations()\n return buildMessagePresenter(t, ctx.record)\n },\n resolveUrl: async (ctx) => {\n const id = pickString(ctx.record.id)\n return id ? `/backend/messages/${encodeURIComponent(id)}` : null\n },\n fieldPolicy: {\n searchable: ['subject', 'body', 'external_name'],\n hashOnly: ['external_email'],\n excluded: ['action_data', 'action_result'],\n },\n },\n ],\n}\n\nexport default searchConfig\nexport const config = searchConfig\n"],
5
+ "mappings": "AAOA,SAAS,2BAA2B;AAEpC,SAAS,WAAW,OAAiB,OAAe,OAAgB;AAClE,MAAI,UAAU,QAAQ,UAAU,OAAW;AAC3C,QAAM,OAAO,MAAM,QAAQ,KAAK,IAC5B,MAAM,IAAI,CAAC,SAAU,SAAS,QAAQ,SAAS,SAAY,KAAK,OAAO,IAAI,CAAE,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,IACvG,OAAO,UAAU,WAAW,KAAK,UAAU,KAAK,IAAI,OAAO,KAAK;AACrE,MAAI,CAAC,KAAK,KAAK,EAAG;AAClB,QAAM,KAAK,GAAG,KAAK,KAAK,IAAI,EAAE;AAChC;AAEA,SAAS,cAAc,YAA2C;AAChE,aAAW,aAAa,YAAY;AAClC,QAAI,OAAO,cAAc,SAAU;AACnC,UAAM,UAAU,UAAU,KAAK;AAC/B,QAAI,QAAQ,SAAS,EAAG,QAAO;AAAA,EACjC;AACA,SAAO;AACT;AAEA,SAAS,QAAQ,OAAgB,MAAM,KAAyB;AAC9D,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,MAAI,QAAQ,UAAU,IAAK,QAAO;AAClC,SAAO,GAAG,QAAQ,MAAM,GAAG,MAAM,CAAC,CAAC;AACrC;AAEA,SAAS,sBAAsB,WAAwB,QAAwD;AAC7G,QAAM,QAAQ,WAAW,OAAO,OAAO,KAAK,UAAU,kCAAkC,SAAS;AACjG,QAAM,OAAO,QAAQ,OAAO,IAAI;AAChC,QAAM,eAAe,WAAW,OAAO,eAAe,OAAO,YAAY;AACzE,QAAM,WAAW,CAAC,cAAc,IAAI,EAAE,OAAO,OAAO,EAAE,KAAK,QAAK,KAAK;AACrE,SAAO;AAAA,IACL,OAAO,OAAO,KAAK;AAAA,IACnB;AAAA,IACA,MAAM;AAAA,IACN,OAAO,UAAU,iCAAiC,SAAS;AAAA,EAC7D;AACF;AAEO,MAAM,eAAmC;AAAA,EAC9C,UAAU;AAAA,IACR;AAAA,MACE,UAAU;AAAA,MACV,SAAS;AAAA,MACT,UAAU;AAAA,MACV,aAAa,OAAO,QAA+D;AACjF,cAAM,EAAE,EAAE,IAAI,MAAM,oBAAoB;AACxC,cAAM,SAAS,IAAI;AACnB,cAAM,QAAkB,CAAC;AACzB,mBAAW,OAAO,WAAW,OAAO,OAAO;AAC3C,mBAAW,OAAO,QAAQ,OAAO,IAAI;AACrC,mBAAW,OAAO,aAAa,OAAO,iBAAiB,OAAO,YAAY;AAC1E,YAAI,CAAC,MAAM,OAAQ,QAAO;AAC1B,eAAO;AAAA,UACL,MAAM;AAAA,UACN,WAAW,sBAAsB,GAAG,MAAM;AAAA,UAC1C,gBAAgB;AAAA,YACd,QAAQ;AAAA,cACN,SAAS,OAAO;AAAA,cAChB,MAAM,OAAO;AAAA,cACb,eAAe,OAAO,iBAAiB,OAAO;AAAA,cAC9C,qBAAqB,OAAO,uBAAuB,OAAO;AAAA,YAC5D;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,MACA,cAAc,OAAO,QAAQ;AAC3B,cAAM,EAAE,EAAE,IAAI,MAAM,oBAAoB;AACxC,eAAO,sBAAsB,GAAG,IAAI,MAAM;AAAA,MAC5C;AAAA,MACA,YAAY,OAAO,QAAQ;AACzB,cAAM,KAAK,WAAW,IAAI,OAAO,EAAE;AACnC,eAAO,KAAK,qBAAqB,mBAAmB,EAAE,CAAC,KAAK;AAAA,MAC9D;AAAA,MACA,aAAa;AAAA,QACX,YAAY,CAAC,WAAW,QAAQ,eAAe;AAAA,QAC/C,UAAU,CAAC,gBAAgB;AAAA,QAC3B,UAAU,CAAC,eAAe,eAAe;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,iBAAQ;AACR,MAAM,SAAS;",
6
6
  "names": []
7
7
  }
@@ -9,6 +9,7 @@ import { getPaymentGatewayQueue } from "../../../lib/queue.js";
9
9
  import { processPaymentGatewayWebhookJob } from "../../../lib/webhook-processor.js";
10
10
  import { paymentGatewaysTag } from "../../openapi.js";
11
11
  import { createLogger } from "@open-mercato/shared/lib/logger";
12
+ import { readBoundedRequestBody, WebhookBodyTooLargeError } from "@open-mercato/shared/lib/webhooks";
12
13
  const logger = createLogger("payment_gateways").child({ component: "webhook" });
13
14
  const metadata = {
14
15
  path: "/payment_gateways/webhook/[provider]",
@@ -30,7 +31,15 @@ async function POST(req, { params }) {
30
31
  }
31
32
  const rateLimitResponse = await checkProviderWebhookRateLimit(container, req, providerKey);
32
33
  if (rateLimitResponse) return rateLimitResponse;
33
- const rawBody = await req.text();
34
+ let rawBody;
35
+ try {
36
+ rawBody = registration.maxBodyBytes === void 0 ? await req.text() : await readBoundedRequestBody(req, { maxBytes: registration.maxBodyBytes });
37
+ } catch (error) {
38
+ if (error instanceof WebhookBodyTooLargeError) {
39
+ return NextResponse.json({ error: "Webhook payload too large" }, { status: 413 });
40
+ }
41
+ throw error;
42
+ }
34
43
  const headers = {};
35
44
  req.headers.forEach((value, key) => {
36
45
  headers[key] = value;
@@ -126,6 +135,7 @@ const openApi = {
126
135
  responses: [
127
136
  { status: 202, description: "Webhook accepted for async processing" },
128
137
  { status: 401, description: "Signature verification failed" },
138
+ { status: 413, description: "Webhook payload too large" },
129
139
  { status: 404, description: "Unknown provider" }
130
140
  ]
131
141
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/payment_gateways/api/webhook/%5Bprovider%5D/route.ts"],
4
- "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { checkRateLimit, getClientIp, RATE_LIMIT_ERROR_FALLBACK } from '@open-mercato/shared/lib/ratelimit/helpers'\nimport type { RateLimiterService } from '@open-mercato/shared/lib/ratelimit/service'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { getWebhookHandler } from '@open-mercato/shared/modules/payment_gateways/types'\nimport type { IntegrationLogService } from '../../../../integrations/lib/log-service'\nimport type { PaymentGatewayService } from '../../../lib/gateway-service'\nimport type { CredentialsService } from '../../../../integrations/lib/credentials-service'\nimport { GatewayTransaction } from '../../../data/entities'\nimport { getPaymentGatewayQueue } from '../../../lib/queue'\nimport { processPaymentGatewayWebhookJob } from '../../../lib/webhook-processor'\nimport { paymentGatewaysTag } from '../../openapi'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('payment_gateways').child({ component: 'webhook' })\n\nexport const metadata = {\n path: '/payment_gateways/webhook/[provider]',\n POST: { requireAuth: false },\n}\n\nconst WEBHOOK_VERIFICATION_FAILED = 'Webhook verification failed'\n\nconst paymentGatewayWebhookRateLimitConfig = {\n points: 60,\n duration: 60,\n keyPrefix: 'payment_gateways:webhook',\n}\n\nexport async function POST(req: Request, { params }: { params: Promise<{ provider: string }> | { provider: string } }) {\n const resolvedParams = await params\n const providerKey = resolvedParams.provider\n const container = await createRequestContainer()\n const registration = getWebhookHandler(providerKey)\n if (!registration) {\n return NextResponse.json({ error: `No webhook handler for provider: ${providerKey}` }, { status: 404 })\n }\n\n const rateLimitResponse = await checkProviderWebhookRateLimit(container, req, providerKey)\n if (rateLimitResponse) return rateLimitResponse\n\n const rawBody = await req.text()\n const headers: Record<string, string> = {}\n req.headers.forEach((value, key) => {\n headers[key] = value\n })\n\n const service = container.resolve('paymentGatewayService') as PaymentGatewayService\n const em = container.resolve('em') as EntityManager\n const integrationCredentialsService = container.resolve('integrationCredentialsService') as CredentialsService\n const queue = getPaymentGatewayQueue(registration.queue ?? 'payment-gateways-webhook')\n const payload = await readJsonSafe<Record<string, unknown>>(rawBody)\n const sessionIdHint = registration.readSessionIdHint?.(payload) ?? null\n\n try {\n // The webhook endpoint is unauthenticated. Tenant/organization scope MUST come from a\n // GatewayTransaction whose per-tenant credentials successfully verify the inbound\n // signature \u2014 NEVER from attacker-controlled payload metadata. If no candidate\n // transaction can be located by the provider-reported session id, or no candidate's\n // credentials can verify the signature, we fail closed with 401. This prevents\n // forged webhooks (e.g. mock gateway PoC) from mutating another tenant's payment\n // state via `event.data.metadata.{organizationId,tenantId}`.\n const candidates = sessionIdHint\n ? await findWithDecryption(\n em,\n GatewayTransaction,\n {\n providerKey,\n providerSessionId: sessionIdHint,\n deletedAt: null,\n },\n { limit: 10, orderBy: { createdAt: 'desc' } },\n )\n : []\n\n let transaction: GatewayTransaction | null = null\n let matchedScope: { organizationId: string; tenantId: string } | null = null\n let event: Awaited<ReturnType<typeof registration.handler>> | null = null\n let lastVerificationError: unknown = null\n\n for (const candidate of candidates) {\n const candidateScope = { organizationId: candidate.organizationId, tenantId: candidate.tenantId }\n const credentials = await integrationCredentialsService.resolve(`gateway_${providerKey}`, candidateScope) ?? {}\n try {\n event = await registration.handler({ rawBody, headers, credentials })\n transaction = candidate\n matchedScope = candidateScope\n break\n } catch (error: unknown) {\n lastVerificationError = error\n }\n }\n\n if (!event || !transaction || !matchedScope) {\n throw lastVerificationError ?? new Error('Webhook verification failed: no matching transaction')\n }\n\n const scope = matchedScope\n\n const jobPayload = {\n providerKey,\n event,\n transactionId: transaction.id,\n scope,\n }\n\n if (process.env.QUEUE_STRATEGY === 'async') {\n await queue.enqueue({\n name: 'payment-gateway-webhook',\n payload: jobPayload,\n })\n } else {\n await processPaymentGatewayWebhookJob(\n {\n em: container.resolve('em') as EntityManager,\n paymentGatewayService: service,\n integrationLogService: container.resolve('integrationLogService') as IntegrationLogService,\n },\n jobPayload,\n )\n }\n\n return NextResponse.json({ received: true, queued: true }, { status: 202 })\n } catch (err: unknown) {\n logger.warn('Webhook verification failed', { providerKey, err })\n return NextResponse.json({ error: WEBHOOK_VERIFICATION_FAILED }, { status: 401 })\n }\n}\n\nasync function checkProviderWebhookRateLimit(\n container: { resolve: (name: string) => unknown },\n req: Request,\n providerKey: string,\n): Promise<NextResponse | null> {\n const rateLimiterService = tryResolve<RateLimiterService>(container, 'rateLimiterService')\n if (!rateLimiterService) return null\n\n return checkRateLimit(\n rateLimiterService,\n paymentGatewayWebhookRateLimitConfig,\n `${providerKey}:${getClientIp(req, rateLimiterService.trustProxyDepth) ?? 'unknown'}`,\n RATE_LIMIT_ERROR_FALLBACK,\n )\n}\n\nfunction tryResolve<T>(container: { resolve: (name: string) => unknown }, name: string): T | null {\n try {\n return container.resolve(name) as T\n } catch {\n return null\n }\n}\n\nexport const openApi = {\n tags: [paymentGatewaysTag],\n summary: 'Receive payment gateway webhook',\n methods: {\n POST: {\n summary: 'Process inbound webhook from payment provider',\n tags: [paymentGatewaysTag],\n responses: [\n { status: 202, description: 'Webhook accepted for async processing' },\n { status: 401, description: 'Signature verification failed' },\n { status: 404, description: 'Unknown provider' },\n ],\n },\n },\n}\n\nexport default POST\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { checkRateLimit, getClientIp, RATE_LIMIT_ERROR_FALLBACK } from '@open-mercato/shared/lib/ratelimit/helpers'\nimport type { RateLimiterService } from '@open-mercato/shared/lib/ratelimit/service'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { getWebhookHandler } from '@open-mercato/shared/modules/payment_gateways/types'\nimport type { IntegrationLogService } from '../../../../integrations/lib/log-service'\nimport type { PaymentGatewayService } from '../../../lib/gateway-service'\nimport type { CredentialsService } from '../../../../integrations/lib/credentials-service'\nimport { GatewayTransaction } from '../../../data/entities'\nimport { getPaymentGatewayQueue } from '../../../lib/queue'\nimport { processPaymentGatewayWebhookJob } from '../../../lib/webhook-processor'\nimport { paymentGatewaysTag } from '../../openapi'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { readBoundedRequestBody, WebhookBodyTooLargeError } from '@open-mercato/shared/lib/webhooks'\n\nconst logger = createLogger('payment_gateways').child({ component: 'webhook' })\n\nexport const metadata = {\n path: '/payment_gateways/webhook/[provider]',\n POST: { requireAuth: false },\n}\n\nconst WEBHOOK_VERIFICATION_FAILED = 'Webhook verification failed'\n\nconst paymentGatewayWebhookRateLimitConfig = {\n points: 60,\n duration: 60,\n keyPrefix: 'payment_gateways:webhook',\n}\n\nexport async function POST(req: Request, { params }: { params: Promise<{ provider: string }> | { provider: string } }) {\n const resolvedParams = await params\n const providerKey = resolvedParams.provider\n const container = await createRequestContainer()\n const registration = getWebhookHandler(providerKey)\n if (!registration) {\n return NextResponse.json({ error: `No webhook handler for provider: ${providerKey}` }, { status: 404 })\n }\n\n const rateLimitResponse = await checkProviderWebhookRateLimit(container, req, providerKey)\n if (rateLimitResponse) return rateLimitResponse\n\n let rawBody: string\n try {\n rawBody = registration.maxBodyBytes === undefined\n ? await req.text()\n : await readBoundedRequestBody(req, { maxBytes: registration.maxBodyBytes })\n } catch (error) {\n if (error instanceof WebhookBodyTooLargeError) {\n return NextResponse.json({ error: 'Webhook payload too large' }, { status: 413 })\n }\n throw error\n }\n const headers: Record<string, string> = {}\n req.headers.forEach((value, key) => {\n headers[key] = value\n })\n\n const service = container.resolve('paymentGatewayService') as PaymentGatewayService\n const em = container.resolve('em') as EntityManager\n const integrationCredentialsService = container.resolve('integrationCredentialsService') as CredentialsService\n const queue = getPaymentGatewayQueue(registration.queue ?? 'payment-gateways-webhook')\n const payload = await readJsonSafe<Record<string, unknown>>(rawBody)\n const sessionIdHint = registration.readSessionIdHint?.(payload) ?? null\n\n try {\n // The webhook endpoint is unauthenticated. Tenant/organization scope MUST come from a\n // GatewayTransaction whose per-tenant credentials successfully verify the inbound\n // signature \u2014 NEVER from attacker-controlled payload metadata. If no candidate\n // transaction can be located by the provider-reported session id, or no candidate's\n // credentials can verify the signature, we fail closed with 401. This prevents\n // forged webhooks (e.g. mock gateway PoC) from mutating another tenant's payment\n // state via `event.data.metadata.{organizationId,tenantId}`.\n const candidates = sessionIdHint\n ? await findWithDecryption(\n em,\n GatewayTransaction,\n {\n providerKey,\n providerSessionId: sessionIdHint,\n deletedAt: null,\n },\n { limit: 10, orderBy: { createdAt: 'desc' } },\n )\n : []\n\n let transaction: GatewayTransaction | null = null\n let matchedScope: { organizationId: string; tenantId: string } | null = null\n let event: Awaited<ReturnType<typeof registration.handler>> | null = null\n let lastVerificationError: unknown = null\n\n for (const candidate of candidates) {\n const candidateScope = { organizationId: candidate.organizationId, tenantId: candidate.tenantId }\n const credentials = await integrationCredentialsService.resolve(`gateway_${providerKey}`, candidateScope) ?? {}\n try {\n event = await registration.handler({ rawBody, headers, credentials })\n transaction = candidate\n matchedScope = candidateScope\n break\n } catch (error: unknown) {\n lastVerificationError = error\n }\n }\n\n if (!event || !transaction || !matchedScope) {\n throw lastVerificationError ?? new Error('Webhook verification failed: no matching transaction')\n }\n\n const scope = matchedScope\n\n const jobPayload = {\n providerKey,\n event,\n transactionId: transaction.id,\n scope,\n }\n\n if (process.env.QUEUE_STRATEGY === 'async') {\n await queue.enqueue({\n name: 'payment-gateway-webhook',\n payload: jobPayload,\n })\n } else {\n await processPaymentGatewayWebhookJob(\n {\n em: container.resolve('em') as EntityManager,\n paymentGatewayService: service,\n integrationLogService: container.resolve('integrationLogService') as IntegrationLogService,\n },\n jobPayload,\n )\n }\n\n return NextResponse.json({ received: true, queued: true }, { status: 202 })\n } catch (err: unknown) {\n logger.warn('Webhook verification failed', { providerKey, err })\n return NextResponse.json({ error: WEBHOOK_VERIFICATION_FAILED }, { status: 401 })\n }\n}\n\nasync function checkProviderWebhookRateLimit(\n container: { resolve: (name: string) => unknown },\n req: Request,\n providerKey: string,\n): Promise<NextResponse | null> {\n const rateLimiterService = tryResolve<RateLimiterService>(container, 'rateLimiterService')\n if (!rateLimiterService) return null\n\n return checkRateLimit(\n rateLimiterService,\n paymentGatewayWebhookRateLimitConfig,\n `${providerKey}:${getClientIp(req, rateLimiterService.trustProxyDepth) ?? 'unknown'}`,\n RATE_LIMIT_ERROR_FALLBACK,\n )\n}\n\nfunction tryResolve<T>(container: { resolve: (name: string) => unknown }, name: string): T | null {\n try {\n return container.resolve(name) as T\n } catch {\n return null\n }\n}\n\nexport const openApi = {\n tags: [paymentGatewaysTag],\n summary: 'Receive payment gateway webhook',\n methods: {\n POST: {\n summary: 'Process inbound webhook from payment provider',\n tags: [paymentGatewaysTag],\n responses: [\n { status: 202, description: 'Webhook accepted for async processing' },\n { status: 401, description: 'Signature verification failed' },\n { status: 413, description: 'Webhook payload too large' },\n { status: 404, description: 'Unknown provider' },\n ],\n },\n },\n}\n\nexport default POST\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -205,6 +205,10 @@ GatewaySessionInitialization = __decorateClass([
205
205
  Unique({
206
206
  name: "gateway_session_initializations_scope_operation_unique",
207
207
  properties: ["operationKey", "providerKey", "organizationId", "tenantId"]
208
+ }),
209
+ Index({
210
+ name: "gateway_session_initializations_prune_idx",
211
+ expression: 'create index "gateway_session_initializations_prune_idx" on "gateway_session_initializations" ("tenant_id", "organization_id", "updated_at") where "gateway_transaction_id" is not null'
208
212
  })
209
213
  ], GatewaySessionInitialization);
210
214
  OptionalProps;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/payment_gateways/data/entities.ts"],
4
- "sourcesContent": ["import { OptionalProps } from '@mikro-orm/core'\nimport { Entity, Index, PrimaryKey, Property, Unique } from '@mikro-orm/decorators/legacy'\n\n@Entity({ tableName: 'gateway_transactions' })\n@Index({ properties: ['paymentId', 'organizationId', 'tenantId'] })\n@Index({ properties: ['providerKey', 'providerSessionId', 'organizationId'] })\n@Index({ properties: ['organizationId', 'tenantId', 'unifiedStatus'] })\nexport class GatewayTransaction {\n [OptionalProps]?: 'unifiedStatus' | 'gatewayStatus' | 'providerSessionId' | 'gatewayPaymentId' | 'gatewayRefundId' | 'redirectUrl' | 'clientSecret' | 'capturedAmount' | 'gatewayMetadata' | 'webhookLog' | 'lastWebhookAt' | 'lastPolledAt' | 'expiresAt' | 'createdAt' | 'updatedAt' | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'payment_id', type: 'uuid' })\n paymentId!: string\n\n @Property({ name: 'provider_key', type: 'text' })\n providerKey!: string\n\n @Property({ name: 'provider_session_id', type: 'text', nullable: true })\n providerSessionId?: string | null\n\n @Property({ name: 'gateway_payment_id', type: 'text', nullable: true })\n gatewayPaymentId?: string | null\n\n @Property({ name: 'gateway_refund_id', type: 'text', nullable: true })\n gatewayRefundId?: string | null\n\n @Property({ name: 'unified_status', type: 'text' })\n unifiedStatus: string = 'pending'\n\n @Property({ name: 'gateway_status', type: 'text', nullable: true })\n gatewayStatus?: string | null\n\n @Property({ name: 'redirect_url', type: 'text', nullable: true })\n redirectUrl?: string | null\n\n @Property({ name: 'client_secret', type: 'text', nullable: true })\n clientSecret?: string | null\n\n @Property({ name: 'amount', type: 'numeric', precision: 18, scale: 4 })\n amount!: string\n\n @Property({ name: 'captured_amount', type: 'numeric', precision: 18, scale: 4, default: '0' })\n capturedAmount: string = '0'\n\n @Property({ name: 'currency_code', type: 'text' })\n currencyCode!: string\n\n @Property({ name: 'gateway_metadata', type: 'jsonb', nullable: true })\n gatewayMetadata?: Record<string, unknown> | null\n\n @Property({ name: 'webhook_log', type: 'jsonb', nullable: true })\n webhookLog?: Array<{ eventType: string; receivedAt: string; idempotencyKey: string; unifiedStatus: string; processed: boolean }> | null\n\n @Property({ name: 'last_webhook_at', type: Date, nullable: true })\n lastWebhookAt?: Date | null\n\n @Property({ name: 'last_polled_at', type: Date, nullable: true })\n lastPolledAt?: Date | null\n\n @Property({ name: 'expires_at', type: Date, nullable: true })\n expiresAt?: Date | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'gateway_payment_operations' })\n@Unique({\n name: 'gateway_payment_operations_scope_operation_unique',\n properties: ['operationId', 'organizationId', 'tenantId'],\n})\n@Index({ properties: ['transactionId', 'operationType', 'organizationId', 'tenantId'] })\n@Index({ properties: ['status', 'leaseExpiresAt'] })\nexport class GatewayPaymentOperation {\n [OptionalProps]?: 'status' | 'attemptCount' | 'result' | 'reservedAmount' | 'leaseExpiresAt' | 'createdAt' | 'updatedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'operation_id', type: 'text' })\n operationId!: string\n\n @Property({ name: 'transaction_id', type: 'uuid' })\n transactionId!: string\n\n @Property({ name: 'operation_type', type: 'text' })\n operationType!: string\n\n @Property({ name: 'provider_key', type: 'text' })\n providerKey!: string\n\n @Property({ name: 'request_hash', type: 'text' })\n requestHash!: string\n\n @Property({ name: 'provider_idempotency_key', type: 'text' })\n providerIdempotencyKey!: string\n\n @Property({ name: 'status', type: 'text' })\n status: string = 'in_progress'\n\n @Property({ name: 'attempt_token', type: 'text' })\n attemptToken!: string\n\n @Property({ name: 'attempt_count', type: 'integer' })\n attemptCount: number = 1\n\n @Property({ name: 'result', type: 'jsonb', nullable: true })\n result?: Record<string, unknown> | null\n\n @Property({ name: 'reserved_amount', type: 'numeric', precision: 18, scale: 4, nullable: true })\n reservedAmount?: string | null\n\n @Property({ name: 'lease_expires_at', type: Date, nullable: true })\n leaseExpiresAt?: Date | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onCreate: () => new Date(), onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n@Entity({ tableName: 'gateway_session_initializations' })\n@Unique({\n name: 'gateway_session_initializations_scope_operation_unique',\n properties: ['operationKey', 'providerKey', 'organizationId', 'tenantId'],\n})\nexport class GatewaySessionInitialization {\n [OptionalProps]?: 'claimToken' | 'claimedAt' | 'gatewayTransactionId' | 'createdAt' | 'updatedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'operation_key', type: 'text' })\n operationKey!: string\n\n @Property({ name: 'provider_key', type: 'text' })\n providerKey!: string\n\n @Property({ name: 'claim_token', type: 'uuid', nullable: true })\n claimToken?: string | null\n\n @Property({ name: 'claimed_at', type: Date, nullable: true })\n claimedAt?: Date | null\n\n @Property({ name: 'gateway_transaction_id', type: 'uuid', nullable: true })\n gatewayTransactionId?: string | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onCreate: () => new Date(), onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n@Entity({ tableName: 'gateway_webhook_events' })\n@Unique({\n name: 'gateway_webhook_events_idempotency_unique',\n properties: ['idempotencyKey', 'providerKey', 'organizationId', 'tenantId'],\n})\nexport class WebhookProcessedEvent {\n [OptionalProps]?: 'processedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'provider_key', type: 'text' })\n providerKey!: string\n\n @Property({ name: 'idempotency_key', type: 'text' })\n idempotencyKey!: string\n\n @Property({ name: 'event_type', type: 'text' })\n eventType!: string\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'processed_at', type: Date, onCreate: () => new Date() })\n processedAt: Date = new Date()\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { OptionalProps } from '@mikro-orm/core'\nimport { Entity, Index, PrimaryKey, Property, Unique } from '@mikro-orm/decorators/legacy'\n\n@Entity({ tableName: 'gateway_transactions' })\n@Index({ properties: ['paymentId', 'organizationId', 'tenantId'] })\n@Index({ properties: ['providerKey', 'providerSessionId', 'organizationId'] })\n@Index({ properties: ['organizationId', 'tenantId', 'unifiedStatus'] })\nexport class GatewayTransaction {\n [OptionalProps]?: 'unifiedStatus' | 'gatewayStatus' | 'providerSessionId' | 'gatewayPaymentId' | 'gatewayRefundId' | 'redirectUrl' | 'clientSecret' | 'capturedAmount' | 'gatewayMetadata' | 'webhookLog' | 'lastWebhookAt' | 'lastPolledAt' | 'expiresAt' | 'createdAt' | 'updatedAt' | 'deletedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'payment_id', type: 'uuid' })\n paymentId!: string\n\n @Property({ name: 'provider_key', type: 'text' })\n providerKey!: string\n\n @Property({ name: 'provider_session_id', type: 'text', nullable: true })\n providerSessionId?: string | null\n\n @Property({ name: 'gateway_payment_id', type: 'text', nullable: true })\n gatewayPaymentId?: string | null\n\n @Property({ name: 'gateway_refund_id', type: 'text', nullable: true })\n gatewayRefundId?: string | null\n\n @Property({ name: 'unified_status', type: 'text' })\n unifiedStatus: string = 'pending'\n\n @Property({ name: 'gateway_status', type: 'text', nullable: true })\n gatewayStatus?: string | null\n\n @Property({ name: 'redirect_url', type: 'text', nullable: true })\n redirectUrl?: string | null\n\n @Property({ name: 'client_secret', type: 'text', nullable: true })\n clientSecret?: string | null\n\n @Property({ name: 'amount', type: 'numeric', precision: 18, scale: 4 })\n amount!: string\n\n @Property({ name: 'captured_amount', type: 'numeric', precision: 18, scale: 4, default: '0' })\n capturedAmount: string = '0'\n\n @Property({ name: 'currency_code', type: 'text' })\n currencyCode!: string\n\n @Property({ name: 'gateway_metadata', type: 'jsonb', nullable: true })\n gatewayMetadata?: Record<string, unknown> | null\n\n @Property({ name: 'webhook_log', type: 'jsonb', nullable: true })\n webhookLog?: Array<{ eventType: string; receivedAt: string; idempotencyKey: string; unifiedStatus: string; processed: boolean }> | null\n\n @Property({ name: 'last_webhook_at', type: Date, nullable: true })\n lastWebhookAt?: Date | null\n\n @Property({ name: 'last_polled_at', type: Date, nullable: true })\n lastPolledAt?: Date | null\n\n @Property({ name: 'expires_at', type: Date, nullable: true })\n expiresAt?: Date | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n\n@Entity({ tableName: 'gateway_payment_operations' })\n@Unique({\n name: 'gateway_payment_operations_scope_operation_unique',\n properties: ['operationId', 'organizationId', 'tenantId'],\n})\n@Index({ properties: ['transactionId', 'operationType', 'organizationId', 'tenantId'] })\n@Index({ properties: ['status', 'leaseExpiresAt'] })\nexport class GatewayPaymentOperation {\n [OptionalProps]?: 'status' | 'attemptCount' | 'result' | 'reservedAmount' | 'leaseExpiresAt' | 'createdAt' | 'updatedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'operation_id', type: 'text' })\n operationId!: string\n\n @Property({ name: 'transaction_id', type: 'uuid' })\n transactionId!: string\n\n @Property({ name: 'operation_type', type: 'text' })\n operationType!: string\n\n @Property({ name: 'provider_key', type: 'text' })\n providerKey!: string\n\n @Property({ name: 'request_hash', type: 'text' })\n requestHash!: string\n\n @Property({ name: 'provider_idempotency_key', type: 'text' })\n providerIdempotencyKey!: string\n\n @Property({ name: 'status', type: 'text' })\n status: string = 'in_progress'\n\n @Property({ name: 'attempt_token', type: 'text' })\n attemptToken!: string\n\n @Property({ name: 'attempt_count', type: 'integer' })\n attemptCount: number = 1\n\n @Property({ name: 'result', type: 'jsonb', nullable: true })\n result?: Record<string, unknown> | null\n\n @Property({ name: 'reserved_amount', type: 'numeric', precision: 18, scale: 4, nullable: true })\n reservedAmount?: string | null\n\n @Property({ name: 'lease_expires_at', type: Date, nullable: true })\n leaseExpiresAt?: Date | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onCreate: () => new Date(), onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n@Entity({ tableName: 'gateway_session_initializations' })\n@Unique({\n name: 'gateway_session_initializations_scope_operation_unique',\n properties: ['operationKey', 'providerKey', 'organizationId', 'tenantId'],\n})\n@Index({\n name: 'gateway_session_initializations_prune_idx',\n expression:\n 'create index \"gateway_session_initializations_prune_idx\" on \"gateway_session_initializations\" (\"tenant_id\", \"organization_id\", \"updated_at\") where \"gateway_transaction_id\" is not null',\n})\nexport class GatewaySessionInitialization {\n [OptionalProps]?: 'claimToken' | 'claimedAt' | 'gatewayTransactionId' | 'createdAt' | 'updatedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'operation_key', type: 'text' })\n operationKey!: string\n\n @Property({ name: 'provider_key', type: 'text' })\n providerKey!: string\n\n @Property({ name: 'claim_token', type: 'uuid', nullable: true })\n claimToken?: string | null\n\n @Property({ name: 'claimed_at', type: Date, nullable: true })\n claimedAt?: Date | null\n\n @Property({ name: 'gateway_transaction_id', type: 'uuid', nullable: true })\n gatewayTransactionId?: string | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onCreate: () => new Date(), onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n\n@Entity({ tableName: 'gateway_webhook_events' })\n@Unique({\n name: 'gateway_webhook_events_idempotency_unique',\n properties: ['idempotencyKey', 'providerKey', 'organizationId', 'tenantId'],\n})\nexport class WebhookProcessedEvent {\n [OptionalProps]?: 'processedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'provider_key', type: 'text' })\n providerKey!: string\n\n @Property({ name: 'idempotency_key', type: 'text' })\n idempotencyKey!: string\n\n @Property({ name: 'event_type', type: 'text' })\n eventType!: string\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'processed_at', type: Date, onCreate: () => new Date() })\n processedAt: Date = new Date()\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,5 +1,6 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { findOneWithDecryption, findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
3
+ import { createLogger } from "@open-mercato/shared/lib/logger";
3
4
  import {
4
5
  getGatewayAdapter
5
6
  } from "@open-mercato/shared/modules/payment_gateways/types";
@@ -33,6 +34,7 @@ import {
33
34
  } from "./session-idempotency.js";
34
35
  const PAYMENT_SESSION_CLAIM_STALE_MS = 3e4;
35
36
  const PAYMENT_SESSION_WAIT_INTERVAL_MS = 25;
37
+ const logger = createLogger("payment_gateways").child({ component: "gateway-service" });
36
38
  function assertManualActionAllowed(action, transaction) {
37
39
  const current = transaction.unifiedStatus;
38
40
  if (!canApplyManualAction(action, current)) {
@@ -330,7 +332,7 @@ function createPaymentGatewayService(deps) {
330
332
  scope
331
333
  );
332
334
  if (!transaction2) {
333
- throw new Error("Completed payment session is missing its gateway transaction");
335
+ throw new Error("[internal] Completed payment session is missing its gateway transaction");
334
336
  }
335
337
  return { transaction: transaction2, session: restoreSession(transaction2) };
336
338
  }
@@ -346,7 +348,15 @@ function createPaymentGatewayService(deps) {
346
348
  try {
347
349
  session = await adapter.createSession({ ...sessionInput, idempotencyKey: operationKey });
348
350
  } catch (error) {
349
- await releasePaymentSessionInitialization(em, ownership, scope).catch(() => void 0);
351
+ try {
352
+ await releasePaymentSessionInitialization(em, ownership, scope);
353
+ } catch (releaseError) {
354
+ logger.warn("Failed to release payment session initialization claim", {
355
+ claimId: ownership.id,
356
+ providerKey: input.providerKey,
357
+ err: releaseError
358
+ });
359
+ }
350
360
  throw error;
351
361
  } finally {
352
362
  await stopHeartbeat();