@open-mercato/core 0.6.6-develop.6465.1.019f0fb26f → 0.6.6-develop.6472.1.1673e7e66b

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 (1213) hide show
  1. package/dist/bootstrap.js +13 -11
  2. package/dist/bootstrap.js.map +2 -2
  3. package/dist/helpers/integration/queue-runner.js +4 -2
  4. package/dist/helpers/integration/queue-runner.js.map +2 -2
  5. package/dist/modules/api_keys/services/apiKeyService.js +5 -3
  6. package/dist/modules/api_keys/services/apiKeyService.js.map +2 -2
  7. package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js +4 -2
  8. package/dist/modules/attachments/api/image/[id]/[[...slug]]/route.js.map +2 -2
  9. package/dist/modules/attachments/api/library/[id]/route.js +3 -1
  10. package/dist/modules/attachments/api/library/[id]/route.js.map +2 -2
  11. package/dist/modules/attachments/api/route.js +8 -6
  12. package/dist/modules/attachments/api/route.js.map +2 -2
  13. package/dist/modules/attachments/components/AttachmentPartitionSettings.js +5 -3
  14. package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
  15. package/dist/modules/attachments/lib/assignmentDetails.js +3 -1
  16. package/dist/modules/attachments/lib/assignmentDetails.js.map +2 -2
  17. package/dist/modules/attachments/lib/drivers/driverFactory.js +3 -1
  18. package/dist/modules/attachments/lib/drivers/driverFactory.js.map +2 -2
  19. package/dist/modules/attachments/lib/ocrQueue.js +10 -11
  20. package/dist/modules/attachments/lib/ocrQueue.js.map +2 -2
  21. package/dist/modules/attachments/lib/ocrService.js +6 -4
  22. package/dist/modules/attachments/lib/ocrService.js.map +2 -2
  23. package/dist/modules/audit_logs/api/audit-logs/actions/redo/route.js +3 -1
  24. package/dist/modules/audit_logs/api/audit-logs/actions/redo/route.js.map +2 -2
  25. package/dist/modules/audit_logs/api/audit-logs/actions/undo/route.js +3 -1
  26. package/dist/modules/audit_logs/api/audit-logs/actions/undo/route.js.map +2 -2
  27. package/dist/modules/audit_logs/backend/audit-logs/page.js +3 -1
  28. package/dist/modules/audit_logs/backend/audit-logs/page.js.map +2 -2
  29. package/dist/modules/audit_logs/components/AuditLogsActions.js +4 -2
  30. package/dist/modules/audit_logs/components/AuditLogsActions.js.map +2 -2
  31. package/dist/modules/audit_logs/services/accessLogService.js +4 -2
  32. package/dist/modules/audit_logs/services/accessLogService.js.map +2 -2
  33. package/dist/modules/audit_logs/services/actionLogService.js +7 -5
  34. package/dist/modules/audit_logs/services/actionLogService.js.map +3 -3
  35. package/dist/modules/auth/api/profile/route.js +4 -2
  36. package/dist/modules/auth/api/profile/route.js.map +2 -2
  37. package/dist/modules/auth/api/reset/confirm.js +3 -1
  38. package/dist/modules/auth/api/reset/confirm.js.map +2 -2
  39. package/dist/modules/auth/api/reset.js +4 -2
  40. package/dist/modules/auth/api/reset.js.map +2 -2
  41. package/dist/modules/auth/api/roles/route.js +3 -1
  42. package/dist/modules/auth/api/roles/route.js.map +2 -2
  43. package/dist/modules/auth/api/sidebar/variants/route.js +3 -1
  44. package/dist/modules/auth/api/sidebar/variants/route.js.map +2 -2
  45. package/dist/modules/auth/api/users/resend-invite/route.js +4 -2
  46. package/dist/modules/auth/api/users/resend-invite/route.js.map +2 -2
  47. package/dist/modules/auth/api/users/route.js +3 -1
  48. package/dist/modules/auth/api/users/route.js.map +2 -2
  49. package/dist/modules/auth/backend/auth/profile/page.js +3 -1
  50. package/dist/modules/auth/backend/auth/profile/page.js.map +2 -2
  51. package/dist/modules/auth/backend/profile/change-password/page.js +3 -1
  52. package/dist/modules/auth/backend/profile/change-password/page.js.map +2 -2
  53. package/dist/modules/auth/backend/users/[id]/edit/page.js +5 -3
  54. package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
  55. package/dist/modules/auth/backend/users/create/page.js +4 -2
  56. package/dist/modules/auth/backend/users/create/page.js.map +2 -2
  57. package/dist/modules/auth/cli.js +10 -0
  58. package/dist/modules/auth/cli.js.map +2 -2
  59. package/dist/modules/auth/commands/users.js +4 -2
  60. package/dist/modules/auth/commands/users.js.map +2 -2
  61. package/dist/modules/auth/lib/consentIntegrity.js +3 -3
  62. package/dist/modules/auth/lib/consentIntegrity.js.map +2 -2
  63. package/dist/modules/auth/lib/setup-app.js +9 -10
  64. package/dist/modules/auth/lib/setup-app.js.map +2 -2
  65. package/dist/modules/auth/lib/tenantAccess.js +3 -1
  66. package/dist/modules/auth/lib/tenantAccess.js.map +2 -2
  67. package/dist/modules/auth/lib/tokenHash.js +3 -3
  68. package/dist/modules/auth/lib/tokenHash.js.map +2 -2
  69. package/dist/modules/business_rules/api/rules/route.js +4 -2
  70. package/dist/modules/business_rules/api/rules/route.js.map +2 -2
  71. package/dist/modules/business_rules/lib/expression-evaluator.js +7 -5
  72. package/dist/modules/business_rules/lib/expression-evaluator.js.map +2 -2
  73. package/dist/modules/business_rules/lib/rule-engine.js +5 -3
  74. package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
  75. package/dist/modules/business_rules/lib/rule-evaluator.js +11 -12
  76. package/dist/modules/business_rules/lib/rule-evaluator.js.map +2 -2
  77. package/dist/modules/business_rules/subscribers/crud-rule-trigger.js +3 -1
  78. package/dist/modules/business_rules/subscribers/crud-rule-trigger.js.map +2 -2
  79. package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js +3 -1
  80. package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js.map +2 -2
  81. package/dist/modules/catalog/ai-agents-context.js +4 -5
  82. package/dist/modules/catalog/ai-agents-context.js.map +2 -2
  83. package/dist/modules/catalog/ai-tools/_shared.js +3 -1
  84. package/dist/modules/catalog/ai-tools/_shared.js.map +2 -2
  85. package/dist/modules/catalog/ai-tools/authoring-pack.js +3 -1
  86. package/dist/modules/catalog/ai-tools/authoring-pack.js.map +2 -2
  87. package/dist/modules/catalog/ai-tools/merchandising-pack.js +3 -1
  88. package/dist/modules/catalog/ai-tools/merchandising-pack.js.map +2 -2
  89. package/dist/modules/catalog/api/dictionaries/[key]/route.js +3 -1
  90. package/dist/modules/catalog/api/dictionaries/[key]/route.js.map +2 -2
  91. package/dist/modules/catalog/api/prices/route.js +3 -1
  92. package/dist/modules/catalog/api/prices/route.js.map +2 -2
  93. package/dist/modules/catalog/api/products/route.js +5 -3
  94. package/dist/modules/catalog/api/products/route.js.map +2 -2
  95. package/dist/modules/catalog/api/settings/route.js +4 -2
  96. package/dist/modules/catalog/api/settings/route.js.map +2 -2
  97. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +14 -12
  98. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  99. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js +8 -6
  100. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.js.map +2 -2
  101. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/create/page.js +5 -3
  102. package/dist/modules/catalog/backend/catalog/products/[productId]/variants/create/page.js.map +2 -2
  103. package/dist/modules/catalog/backend/catalog/products/create/page.js +5 -6
  104. package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
  105. package/dist/modules/catalog/backend/catalog/products/optionSchemaClient.js +3 -1
  106. package/dist/modules/catalog/backend/catalog/products/optionSchemaClient.js.map +2 -2
  107. package/dist/modules/catalog/components/PriceKindSettings.js +5 -3
  108. package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
  109. package/dist/modules/catalog/components/UnitPriceDisplaySettings.js +4 -2
  110. package/dist/modules/catalog/components/UnitPriceDisplaySettings.js.map +2 -2
  111. package/dist/modules/catalog/inbox-actions.js +4 -2
  112. package/dist/modules/catalog/inbox-actions.js.map +2 -2
  113. package/dist/modules/catalog/seed/examples.js +4 -5
  114. package/dist/modules/catalog/seed/examples.js.map +2 -2
  115. package/dist/modules/catalog/subscribers/low-stock-notification.js +3 -1
  116. package/dist/modules/catalog/subscribers/low-stock-notification.js.map +2 -2
  117. package/dist/modules/catalog/widgets/injection/product-seo/state.js +3 -1
  118. package/dist/modules/catalog/widgets/injection/product-seo/state.js.map +2 -2
  119. package/dist/modules/communication_channels/api/get/oauth/[provider]/callback/route.js +12 -11
  120. package/dist/modules/communication_channels/api/get/oauth/[provider]/callback/route.js.map +2 -2
  121. package/dist/modules/communication_channels/api/post/channels/[id]/import-history/route.js +3 -1
  122. package/dist/modules/communication_channels/api/post/channels/[id]/import-history/route.js.map +2 -2
  123. package/dist/modules/communication_channels/api/post/channels/[id]/push/register/route.js +3 -1
  124. package/dist/modules/communication_channels/api/post/channels/[id]/push/register/route.js.map +2 -2
  125. package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js +5 -3
  126. package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js.map +2 -2
  127. package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js +6 -6
  128. package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js.map +2 -2
  129. package/dist/modules/communication_channels/commands/connect-credential-channel.js +4 -6
  130. package/dist/modules/communication_channels/commands/connect-credential-channel.js.map +2 -2
  131. package/dist/modules/communication_channels/commands/delete-channel.js +3 -3
  132. package/dist/modules/communication_channels/commands/delete-channel.js.map +2 -2
  133. package/dist/modules/communication_channels/commands/deliver-outbound-message.js +4 -5
  134. package/dist/modules/communication_channels/commands/deliver-outbound-message.js.map +2 -2
  135. package/dist/modules/communication_channels/commands/disconnect-channel.js +3 -3
  136. package/dist/modules/communication_channels/commands/disconnect-channel.js.map +2 -2
  137. package/dist/modules/communication_channels/commands/ingest-inbound-message.js +5 -12
  138. package/dist/modules/communication_channels/commands/ingest-inbound-message.js.map +2 -2
  139. package/dist/modules/communication_channels/commands/push-unregister.js +3 -3
  140. package/dist/modules/communication_channels/commands/push-unregister.js.map +2 -2
  141. package/dist/modules/communication_channels/commands/reassign-conversation.js +5 -3
  142. package/dist/modules/communication_channels/commands/reassign-conversation.js.map +2 -2
  143. package/dist/modules/communication_channels/lib/dead-letter.js +3 -3
  144. package/dist/modules/communication_channels/lib/dead-letter.js.map +2 -2
  145. package/dist/modules/communication_channels/lib/email-mime.js +4 -6
  146. package/dist/modules/communication_channels/lib/email-mime.js.map +2 -2
  147. package/dist/modules/communication_channels/lib/oauth-client-config.js +5 -3
  148. package/dist/modules/communication_channels/lib/oauth-client-config.js.map +2 -2
  149. package/dist/modules/communication_channels/lib/send-as-user.js +3 -1
  150. package/dist/modules/communication_channels/lib/send-as-user.js.map +2 -2
  151. package/dist/modules/communication_channels/lib/thread-token.js +4 -2
  152. package/dist/modules/communication_channels/lib/thread-token.js.map +2 -2
  153. package/dist/modules/communication_channels/setup.js +3 -4
  154. package/dist/modules/communication_channels/setup.js.map +2 -2
  155. package/dist/modules/communication_channels/workers/channel-import-history.js +4 -6
  156. package/dist/modules/communication_channels/workers/channel-import-history.js.map +2 -2
  157. package/dist/modules/communication_channels/workers/gmail-history-sync.js +8 -16
  158. package/dist/modules/communication_channels/workers/gmail-history-sync.js.map +2 -2
  159. package/dist/modules/communication_channels/workers/gmail-renew-watch.js +5 -7
  160. package/dist/modules/communication_channels/workers/gmail-renew-watch.js.map +2 -2
  161. package/dist/modules/communication_channels/workers/outbound-delivery.js +6 -12
  162. package/dist/modules/communication_channels/workers/outbound-delivery.js.map +2 -2
  163. package/dist/modules/communication_channels/workers/poll-channel.js +7 -15
  164. package/dist/modules/communication_channels/workers/poll-channel.js.map +2 -2
  165. package/dist/modules/communication_channels/workers/poll-tick.js +5 -6
  166. package/dist/modules/communication_channels/workers/poll-tick.js.map +2 -2
  167. package/dist/modules/communication_channels/workers/reaction-processor.js +5 -9
  168. package/dist/modules/communication_channels/workers/reaction-processor.js.map +2 -2
  169. package/dist/modules/configs/api/cache/route.js +4 -2
  170. package/dist/modules/configs/api/cache/route.js.map +2 -2
  171. package/dist/modules/configs/api/system-status/route.js +4 -2
  172. package/dist/modules/configs/api/system-status/route.js.map +2 -2
  173. package/dist/modules/configs/api/upgrade-actions/route.js +4 -2
  174. package/dist/modules/configs/api/upgrade-actions/route.js.map +2 -2
  175. package/dist/modules/configs/components/ModuleTelemetryPanel.js +3 -1
  176. package/dist/modules/configs/components/ModuleTelemetryPanel.js.map +2 -2
  177. package/dist/modules/configs/lib/touchGeneratedBarrels.js +2 -1
  178. package/dist/modules/configs/lib/touchGeneratedBarrels.js.map +2 -2
  179. package/dist/modules/configs/services/upgradeActionsService.js +6 -3
  180. package/dist/modules/configs/services/upgradeActionsService.js.map +2 -2
  181. package/dist/modules/currencies/components/CurrencyFetchingConfig.js +3 -1
  182. package/dist/modules/currencies/components/CurrencyFetchingConfig.js.map +2 -2
  183. package/dist/modules/currencies/lib/exchangeRateFormConfig.js +3 -1
  184. package/dist/modules/currencies/lib/exchangeRateFormConfig.js.map +2 -2
  185. package/dist/modules/currencies/services/providers/nbp.js +6 -4
  186. package/dist/modules/currencies/services/providers/nbp.js.map +2 -2
  187. package/dist/modules/currencies/services/providers/raiffeisen.js +7 -7
  188. package/dist/modules/currencies/services/providers/raiffeisen.js.map +2 -2
  189. package/dist/modules/customer_accounts/api/domain-resolve/all.js +6 -5
  190. package/dist/modules/customer_accounts/api/domain-resolve/all.js.map +2 -2
  191. package/dist/modules/customer_accounts/api/signup.js +4 -2
  192. package/dist/modules/customer_accounts/api/signup.js.map +2 -2
  193. package/dist/modules/customer_accounts/lib/customerAuthServer.js +3 -1
  194. package/dist/modules/customer_accounts/lib/customerAuthServer.js.map +2 -2
  195. package/dist/modules/customer_accounts/subscribers/autoLinkCrm.js +3 -1
  196. package/dist/modules/customer_accounts/subscribers/autoLinkCrm.js.map +2 -2
  197. package/dist/modules/customer_accounts/subscribers/autoLinkCrmReverse.js +3 -1
  198. package/dist/modules/customer_accounts/subscribers/autoLinkCrmReverse.js.map +2 -2
  199. package/dist/modules/customer_accounts/subscribers/unlinkOnCompanyDelete.js +3 -1
  200. package/dist/modules/customer_accounts/subscribers/unlinkOnCompanyDelete.js.map +2 -2
  201. package/dist/modules/customer_accounts/subscribers/unlinkOnPersonDelete.js +3 -1
  202. package/dist/modules/customer_accounts/subscribers/unlinkOnPersonDelete.js.map +2 -2
  203. package/dist/modules/customers/ai-agents-context.js +4 -5
  204. package/dist/modules/customers/ai-agents-context.js.map +2 -2
  205. package/dist/modules/customers/api/activities/route.js +6 -4
  206. package/dist/modules/customers/api/activities/route.js.map +2 -2
  207. package/dist/modules/customers/api/comments/route.js +3 -1
  208. package/dist/modules/customers/api/comments/route.js.map +2 -2
  209. package/dist/modules/customers/api/companies/[id]/people/route.js +3 -1
  210. package/dist/modules/customers/api/companies/[id]/people/route.js.map +2 -2
  211. package/dist/modules/customers/api/companies/[id]/route.js +5 -3
  212. package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
  213. package/dist/modules/customers/api/companies/route.js +5 -3
  214. package/dist/modules/customers/api/companies/route.js.map +2 -2
  215. package/dist/modules/customers/api/dashboard/widgets/customer-todos/route.js +3 -1
  216. package/dist/modules/customers/api/dashboard/widgets/customer-todos/route.js.map +2 -2
  217. package/dist/modules/customers/api/dashboard/widgets/new-customers/route.js +3 -1
  218. package/dist/modules/customers/api/dashboard/widgets/new-customers/route.js.map +2 -2
  219. package/dist/modules/customers/api/dashboard/widgets/new-deals/route.js +3 -1
  220. package/dist/modules/customers/api/dashboard/widgets/new-deals/route.js.map +2 -2
  221. package/dist/modules/customers/api/dashboard/widgets/next-interactions/route.js +3 -1
  222. package/dist/modules/customers/api/dashboard/widgets/next-interactions/route.js.map +2 -2
  223. package/dist/modules/customers/api/deals/[id]/companies/route.js +3 -1
  224. package/dist/modules/customers/api/deals/[id]/companies/route.js.map +2 -2
  225. package/dist/modules/customers/api/deals/[id]/people/route.js +3 -1
  226. package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
  227. package/dist/modules/customers/api/deals/aggregate/route.js +3 -1
  228. package/dist/modules/customers/api/deals/aggregate/route.js.map +2 -2
  229. package/dist/modules/customers/api/deals/bulk-update-owner/route.js +7 -5
  230. package/dist/modules/customers/api/deals/bulk-update-owner/route.js.map +2 -2
  231. package/dist/modules/customers/api/deals/bulk-update-stage/route.js +7 -5
  232. package/dist/modules/customers/api/deals/bulk-update-stage/route.js.map +2 -2
  233. package/dist/modules/customers/api/deals/route.js +3 -1
  234. package/dist/modules/customers/api/deals/route.js.map +2 -2
  235. package/dist/modules/customers/api/deals/summary/route.js +3 -1
  236. package/dist/modules/customers/api/deals/summary/route.js.map +2 -2
  237. package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js +4 -2
  238. package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js.map +2 -2
  239. package/dist/modules/customers/api/dictionaries/[kind]/route.js +5 -3
  240. package/dist/modules/customers/api/dictionaries/[kind]/route.js.map +2 -2
  241. package/dist/modules/customers/api/dictionaries/cache.js +3 -1
  242. package/dist/modules/customers/api/dictionaries/cache.js.map +2 -2
  243. package/dist/modules/customers/api/dictionaries/context.js +3 -1
  244. package/dist/modules/customers/api/dictionaries/context.js.map +2 -2
  245. package/dist/modules/customers/api/dictionaries/currency/route.js +3 -1
  246. package/dist/modules/customers/api/dictionaries/currency/route.js.map +2 -2
  247. package/dist/modules/customers/api/dictionaries/kind-settings/route.js +4 -2
  248. package/dist/modules/customers/api/dictionaries/kind-settings/route.js.map +2 -2
  249. package/dist/modules/customers/api/entity-roles-factory.js +7 -5
  250. package/dist/modules/customers/api/entity-roles-factory.js.map +2 -2
  251. package/dist/modules/customers/api/interactions/cancel/route.js +3 -1
  252. package/dist/modules/customers/api/interactions/cancel/route.js.map +2 -2
  253. package/dist/modules/customers/api/interactions/complete/route.js +3 -1
  254. package/dist/modules/customers/api/interactions/complete/route.js.map +2 -2
  255. package/dist/modules/customers/api/interactions/conflicts/route.js +3 -1
  256. package/dist/modules/customers/api/interactions/conflicts/route.js.map +2 -2
  257. package/dist/modules/customers/api/interactions/counts/route.js +3 -1
  258. package/dist/modules/customers/api/interactions/counts/route.js.map +2 -2
  259. package/dist/modules/customers/api/interactions/route.js +7 -4
  260. package/dist/modules/customers/api/interactions/route.js.map +2 -2
  261. package/dist/modules/customers/api/interactions/tasks/route.js +3 -1
  262. package/dist/modules/customers/api/interactions/tasks/route.js.map +2 -2
  263. package/dist/modules/customers/api/labels/assign/route.js +3 -1
  264. package/dist/modules/customers/api/labels/assign/route.js.map +2 -2
  265. package/dist/modules/customers/api/labels/route.js +6 -3
  266. package/dist/modules/customers/api/labels/route.js.map +2 -2
  267. package/dist/modules/customers/api/labels/unassign/route.js +3 -1
  268. package/dist/modules/customers/api/labels/unassign/route.js.map +2 -2
  269. package/dist/modules/customers/api/people/[id]/companies/enriched/route.js +3 -1
  270. package/dist/modules/customers/api/people/[id]/companies/enriched/route.js.map +2 -2
  271. package/dist/modules/customers/api/people/[id]/route.js +5 -3
  272. package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
  273. package/dist/modules/customers/api/people/route.js +5 -3
  274. package/dist/modules/customers/api/people/route.js.map +2 -2
  275. package/dist/modules/customers/api/pipeline-stages/reorder/route.js +3 -1
  276. package/dist/modules/customers/api/pipeline-stages/reorder/route.js.map +2 -2
  277. package/dist/modules/customers/api/pipeline-stages/route.js +6 -4
  278. package/dist/modules/customers/api/pipeline-stages/route.js.map +2 -2
  279. package/dist/modules/customers/api/pipelines/route.js +6 -4
  280. package/dist/modules/customers/api/pipelines/route.js.map +2 -2
  281. package/dist/modules/customers/api/settings/address-format/route.js +4 -2
  282. package/dist/modules/customers/api/settings/address-format/route.js.map +2 -2
  283. package/dist/modules/customers/api/settings/dictionary-sort-modes/route.js +4 -2
  284. package/dist/modules/customers/api/settings/dictionary-sort-modes/route.js.map +2 -2
  285. package/dist/modules/customers/api/settings/stuck-threshold/route.js +4 -2
  286. package/dist/modules/customers/api/settings/stuck-threshold/route.js.map +2 -2
  287. package/dist/modules/customers/api/tags/assign/route.js +3 -1
  288. package/dist/modules/customers/api/tags/assign/route.js.map +2 -2
  289. package/dist/modules/customers/api/tags/unassign/route.js +3 -1
  290. package/dist/modules/customers/api/tags/unassign/route.js.map +2 -2
  291. package/dist/modules/customers/api/todos/route.js +6 -4
  292. package/dist/modules/customers/api/todos/route.js.map +2 -2
  293. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +5 -3
  294. package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
  295. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.js +3 -1
  296. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.js.map +2 -2
  297. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealClosure.js +3 -1
  298. package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealClosure.js.map +2 -2
  299. package/dist/modules/customers/backend/customers/deals/map/components/DealsMapCanvasImpl.js +4 -2
  300. package/dist/modules/customers/backend/customers/deals/map/components/DealsMapCanvasImpl.js.map +2 -2
  301. package/dist/modules/customers/backend/customers/deals/page.js +4 -2
  302. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  303. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +5 -3
  304. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  305. package/dist/modules/customers/commands/deals.js +3 -1
  306. package/dist/modules/customers/commands/deals.js.map +2 -2
  307. package/dist/modules/customers/commands/dictionaries.js +3 -1
  308. package/dist/modules/customers/commands/dictionaries.js.map +2 -2
  309. package/dist/modules/customers/commands/interactions.js +4 -2
  310. package/dist/modules/customers/commands/interactions.js.map +2 -2
  311. package/dist/modules/customers/commands/shared.js +4 -2
  312. package/dist/modules/customers/commands/shared.js.map +2 -2
  313. package/dist/modules/customers/commands/todos.js +3 -1
  314. package/dist/modules/customers/commands/todos.js.map +2 -2
  315. package/dist/modules/customers/components/DictionarySettings.js +5 -3
  316. package/dist/modules/customers/components/DictionarySettings.js.map +2 -2
  317. package/dist/modules/customers/components/DictionarySortSettings.js +3 -1
  318. package/dist/modules/customers/components/DictionarySortSettings.js.map +2 -2
  319. package/dist/modules/customers/components/detail/ActivitiesCard.js +3 -1
  320. package/dist/modules/customers/components/detail/ActivitiesCard.js.map +2 -2
  321. package/dist/modules/customers/components/detail/ActivitiesDayStrip.js +3 -1
  322. package/dist/modules/customers/components/detail/ActivitiesDayStrip.js.map +2 -2
  323. package/dist/modules/customers/components/detail/ActivitiesSection.js +6 -4
  324. package/dist/modules/customers/components/detail/ActivitiesSection.js.map +2 -2
  325. package/dist/modules/customers/components/detail/ActivityCard.js +3 -1
  326. package/dist/modules/customers/components/detail/ActivityCard.js.map +2 -2
  327. package/dist/modules/customers/components/detail/ChangelogTab.js +3 -1
  328. package/dist/modules/customers/components/detail/ChangelogTab.js.map +2 -2
  329. package/dist/modules/customers/components/detail/CompanyCard.js +3 -1
  330. package/dist/modules/customers/components/detail/CompanyCard.js.map +2 -2
  331. package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js +3 -1
  332. package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js.map +2 -2
  333. package/dist/modules/customers/components/detail/EntityTagsDialog.js +3 -1
  334. package/dist/modules/customers/components/detail/EntityTagsDialog.js.map +2 -2
  335. package/dist/modules/customers/components/detail/InlineActivityComposer.js +3 -1
  336. package/dist/modules/customers/components/detail/InlineActivityComposer.js.map +2 -2
  337. package/dist/modules/customers/components/detail/ManageTagsDialog.js +3 -1
  338. package/dist/modules/customers/components/detail/ManageTagsDialog.js.map +2 -2
  339. package/dist/modules/customers/components/detail/RoleAssignmentRow.js +5 -3
  340. package/dist/modules/customers/components/detail/RoleAssignmentRow.js.map +2 -2
  341. package/dist/modules/customers/components/detail/RolesSection.js +4 -2
  342. package/dist/modules/customers/components/detail/RolesSection.js.map +2 -2
  343. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js +5 -3
  344. package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js.map +2 -2
  345. package/dist/modules/customers/components/linking/LinkEntityDialog.js +4 -2
  346. package/dist/modules/customers/components/linking/LinkEntityDialog.js.map +2 -2
  347. package/dist/modules/customers/inbox-actions.js +3 -1
  348. package/dist/modules/customers/inbox-actions.js.map +2 -2
  349. package/dist/modules/customers/lib/bulkDeals.js +3 -1
  350. package/dist/modules/customers/lib/bulkDeals.js.map +2 -2
  351. package/dist/modules/customers/lib/dealClosureNotification.js +4 -2
  352. package/dist/modules/customers/lib/dealClosureNotification.js.map +2 -2
  353. package/dist/modules/customers/lib/dealStageTransitionTable.js +3 -1
  354. package/dist/modules/customers/lib/dealStageTransitionTable.js.map +2 -2
  355. package/dist/modules/customers/lib/interactionFeatureFlags.js +3 -1
  356. package/dist/modules/customers/lib/interactionFeatureFlags.js.map +2 -2
  357. package/dist/modules/customers/lib/todoCompatibility.js +3 -1
  358. package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
  359. package/dist/modules/customers/search.js +14 -7
  360. package/dist/modules/customers/search.js.map +2 -2
  361. package/dist/modules/customers/widgets/dashboard/customer-todos/widget.client.js +3 -1
  362. package/dist/modules/customers/widgets/dashboard/customer-todos/widget.client.js.map +2 -2
  363. package/dist/modules/customers/widgets/dashboard/new-customers/widget.client.js +3 -1
  364. package/dist/modules/customers/widgets/dashboard/new-customers/widget.client.js.map +2 -2
  365. package/dist/modules/customers/widgets/dashboard/new-deals/widget.client.js +3 -1
  366. package/dist/modules/customers/widgets/dashboard/new-deals/widget.client.js.map +2 -2
  367. package/dist/modules/customers/widgets/dashboard/next-interactions/widget.client.js +3 -1
  368. package/dist/modules/customers/widgets/dashboard/next-interactions/widget.client.js.map +2 -2
  369. package/dist/modules/dashboards/api/widgets/data/batch/route.js +3 -1
  370. package/dist/modules/dashboards/api/widgets/data/batch/route.js.map +2 -2
  371. package/dist/modules/dashboards/api/widgets/data/route.js +3 -1
  372. package/dist/modules/dashboards/api/widgets/data/route.js.map +2 -2
  373. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +5 -3
  374. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +2 -2
  375. package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.js +3 -1
  376. package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.js.map +2 -2
  377. package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.client.js +3 -1
  378. package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.client.js.map +2 -2
  379. package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.js +3 -1
  380. package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.js.map +2 -2
  381. package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.client.js +3 -1
  382. package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.client.js.map +2 -2
  383. package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.js +3 -1
  384. package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.js.map +2 -2
  385. package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.js +3 -1
  386. package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.js.map +2 -2
  387. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js +3 -1
  388. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js.map +2 -2
  389. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js +3 -1
  390. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js.map +2 -2
  391. package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js +3 -1
  392. package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js.map +2 -2
  393. package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js +3 -1
  394. package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js.map +2 -2
  395. package/dist/modules/data_sync/api/run.js +3 -1
  396. package/dist/modules/data_sync/api/run.js.map +2 -2
  397. package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js +1 -1
  398. package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js.map +2 -2
  399. package/dist/modules/data_sync/lib/adapter-registry.js +11 -4
  400. package/dist/modules/data_sync/lib/adapter-registry.js.map +2 -2
  401. package/dist/modules/data_sync/lib/sync-engine.js +23 -2
  402. package/dist/modules/data_sync/lib/sync-engine.js.map +2 -2
  403. package/dist/modules/data_sync/workers/sync-export.js +3 -1
  404. package/dist/modules/data_sync/workers/sync-export.js.map +2 -2
  405. package/dist/modules/data_sync/workers/sync-import.js +3 -1
  406. package/dist/modules/data_sync/workers/sync-import.js.map +2 -2
  407. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js +4 -2
  408. package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js.map +2 -2
  409. package/dist/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.js +3 -1
  410. package/dist/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.js.map +2 -2
  411. package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js +4 -2
  412. package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js.map +2 -2
  413. package/dist/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.js +3 -1
  414. package/dist/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.js.map +2 -2
  415. package/dist/modules/dictionaries/api/[dictionaryId]/route.js +5 -3
  416. package/dist/modules/dictionaries/api/[dictionaryId]/route.js.map +2 -2
  417. package/dist/modules/dictionaries/api/context.js +3 -1
  418. package/dist/modules/dictionaries/api/context.js.map +2 -2
  419. package/dist/modules/dictionaries/api/route.js +4 -2
  420. package/dist/modules/dictionaries/api/route.js.map +2 -2
  421. package/dist/modules/dictionaries/components/DictionariesManager.js +5 -3
  422. package/dist/modules/dictionaries/components/DictionariesManager.js.map +2 -2
  423. package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js +4 -2
  424. package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js.map +2 -2
  425. package/dist/modules/dictionaries/components/DictionaryEntrySelect.js +4 -2
  426. package/dist/modules/dictionaries/components/DictionaryEntrySelect.js.map +2 -2
  427. package/dist/modules/dictionaries/components/DictionarySelectControl.js +3 -1
  428. package/dist/modules/dictionaries/components/DictionarySelectControl.js.map +2 -2
  429. package/dist/modules/dictionaries/fields/dictionary.js +3 -1
  430. package/dist/modules/dictionaries/fields/dictionary.js.map +2 -2
  431. package/dist/modules/directory/api/organization-branding/route.js +3 -1
  432. package/dist/modules/directory/api/organization-branding/route.js.map +2 -2
  433. package/dist/modules/directory/api/organization-switcher/route.js +3 -1
  434. package/dist/modules/directory/api/organization-switcher/route.js.map +2 -2
  435. package/dist/modules/directory/commands/tenants.js +5 -3
  436. package/dist/modules/directory/commands/tenants.js.map +2 -2
  437. package/dist/modules/directory/utils/organizationScope.js +6 -4
  438. package/dist/modules/directory/utils/organizationScope.js.map +2 -2
  439. package/dist/modules/entities/api/definitions.cache.js +3 -1
  440. package/dist/modules/entities/api/definitions.cache.js.map +2 -2
  441. package/dist/modules/entities/api/definitions.js +7 -5
  442. package/dist/modules/entities/api/definitions.js.map +2 -2
  443. package/dist/modules/entities/api/records.js +4 -8
  444. package/dist/modules/entities/api/records.js.map +2 -2
  445. package/dist/modules/entities/components/EncryptionManager.js +3 -1
  446. package/dist/modules/entities/components/EncryptionManager.js.map +2 -2
  447. package/dist/modules/entities/lib/makeActivityRoute.js +3 -1
  448. package/dist/modules/entities/lib/makeActivityRoute.js.map +2 -2
  449. package/dist/modules/feature_toggles/api/overrides/route.js +3 -1
  450. package/dist/modules/feature_toggles/api/overrides/route.js.map +2 -2
  451. package/dist/modules/feature_toggles/lib/feature-flag-check.js +5 -9
  452. package/dist/modules/feature_toggles/lib/feature-flag-check.js.map +2 -2
  453. package/dist/modules/inbox_ops/api/emails/[id]/reprocess/route.js +4 -2
  454. package/dist/modules/inbox_ops/api/emails/[id]/reprocess/route.js.map +2 -2
  455. package/dist/modules/inbox_ops/api/emails/[id]/route.js +4 -2
  456. package/dist/modules/inbox_ops/api/emails/[id]/route.js.map +2 -2
  457. package/dist/modules/inbox_ops/api/emails/route.js +3 -1
  458. package/dist/modules/inbox_ops/api/emails/route.js.map +2 -2
  459. package/dist/modules/inbox_ops/api/extract/route.js +3 -1
  460. package/dist/modules/inbox_ops/api/extract/route.js.map +2 -2
  461. package/dist/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.js +3 -1
  462. package/dist/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.js.map +2 -2
  463. package/dist/modules/inbox_ops/api/proposals/[id]/replies/[replyId]/send/route.js +4 -2
  464. package/dist/modules/inbox_ops/api/proposals/[id]/replies/[replyId]/send/route.js.map +2 -2
  465. package/dist/modules/inbox_ops/api/proposals/counts/route.js +4 -2
  466. package/dist/modules/inbox_ops/api/proposals/counts/route.js.map +2 -2
  467. package/dist/modules/inbox_ops/api/proposals/route.js +3 -1
  468. package/dist/modules/inbox_ops/api/proposals/route.js.map +2 -2
  469. package/dist/modules/inbox_ops/api/routeHelpers.js +3 -1
  470. package/dist/modules/inbox_ops/api/routeHelpers.js.map +2 -2
  471. package/dist/modules/inbox_ops/api/settings/route.js +3 -1
  472. package/dist/modules/inbox_ops/api/settings/route.js.map +2 -2
  473. package/dist/modules/inbox_ops/api/webhook/inbound.js +7 -5
  474. package/dist/modules/inbox_ops/api/webhook/inbound.js.map +2 -2
  475. package/dist/modules/inbox_ops/lib/cache.js +4 -2
  476. package/dist/modules/inbox_ops/lib/cache.js.map +2 -2
  477. package/dist/modules/inbox_ops/lib/catalogLookup.js +3 -1
  478. package/dist/modules/inbox_ops/lib/catalogLookup.js.map +2 -2
  479. package/dist/modules/inbox_ops/lib/eventBus.js +3 -4
  480. package/dist/modules/inbox_ops/lib/eventBus.js.map +2 -2
  481. package/dist/modules/inbox_ops/lib/messagesIntegration.js +4 -8
  482. package/dist/modules/inbox_ops/lib/messagesIntegration.js.map +2 -2
  483. package/dist/modules/inbox_ops/subscribers/executionAuditor.js +3 -1
  484. package/dist/modules/inbox_ops/subscribers/executionAuditor.js.map +2 -2
  485. package/dist/modules/inbox_ops/subscribers/extractionWorker.js +10 -8
  486. package/dist/modules/inbox_ops/subscribers/extractionWorker.js.map +2 -2
  487. package/dist/modules/inbox_ops/subscribers/proposalNotifier.js +3 -1
  488. package/dist/modules/inbox_ops/subscribers/proposalNotifier.js.map +2 -2
  489. package/dist/modules/messages/api/[id]/route.js +3 -4
  490. package/dist/modules/messages/api/[id]/route.js.map +2 -2
  491. package/dist/modules/messages/commands/actions.js +3 -1
  492. package/dist/modules/messages/commands/actions.js.map +2 -2
  493. package/dist/modules/messages/components/MessagesInboxPageClient.js +3 -1
  494. package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
  495. package/dist/modules/messages/lib/email-sender.js +3 -7
  496. package/dist/modules/messages/lib/email-sender.js.map +2 -2
  497. package/dist/modules/messages/lib/message-objects-registry.js +3 -1
  498. package/dist/modules/messages/lib/message-objects-registry.js.map +2 -2
  499. package/dist/modules/messages/lib/message-types-registry.js +3 -1
  500. package/dist/modules/messages/lib/message-types-registry.js.map +2 -2
  501. package/dist/modules/messages/workers/send-email.worker.js +6 -4
  502. package/dist/modules/messages/workers/send-email.worker.js.map +2 -2
  503. package/dist/modules/notifications/lib/notificationMapper.js +3 -4
  504. package/dist/modules/notifications/lib/notificationMapper.js.map +2 -2
  505. package/dist/modules/notifications/lib/notificationService.js +4 -5
  506. package/dist/modules/notifications/lib/notificationService.js.map +2 -2
  507. package/dist/modules/notifications/subscribers/deliver-notification.js +8 -13
  508. package/dist/modules/notifications/subscribers/deliver-notification.js.map +2 -2
  509. package/dist/modules/payment_gateways/api/webhook/[provider]/route.js +3 -1
  510. package/dist/modules/payment_gateways/api/webhook/[provider]/route.js.map +2 -2
  511. package/dist/modules/perspectives/services/perspectiveService.js +3 -3
  512. package/dist/modules/perspectives/services/perspectiveService.js.map +2 -2
  513. package/dist/modules/planner/api/access.js +3 -3
  514. package/dist/modules/planner/api/access.js.map +2 -2
  515. package/dist/modules/planner/api/availability-date-specific.js +3 -1
  516. package/dist/modules/planner/api/availability-date-specific.js.map +2 -2
  517. package/dist/modules/planner/api/availability-weekly.js +3 -1
  518. package/dist/modules/planner/api/availability-weekly.js.map +2 -2
  519. package/dist/modules/planner/backend/planner/availability-rulesets/page.js +4 -2
  520. package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
  521. package/dist/modules/planner/components/AvailabilityRulesEditor.js +3 -1
  522. package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
  523. package/dist/modules/progress/api/jobs/route.js +3 -1
  524. package/dist/modules/progress/api/jobs/route.js.map +2 -2
  525. package/dist/modules/query_index/components/QueryIndexesTable.js +5 -3
  526. package/dist/modules/query_index/components/QueryIndexesTable.js.map +2 -2
  527. package/dist/modules/query_index/lib/batch.js +4 -2
  528. package/dist/modules/query_index/lib/batch.js.map +2 -2
  529. package/dist/modules/query_index/lib/coverage.js +3 -1
  530. package/dist/modules/query_index/lib/coverage.js.map +2 -2
  531. package/dist/modules/query_index/lib/engine.js +13 -18
  532. package/dist/modules/query_index/lib/engine.js.map +2 -2
  533. package/dist/modules/query_index/lib/reindexer.js +8 -6
  534. package/dist/modules/query_index/lib/reindexer.js.map +2 -2
  535. package/dist/modules/query_index/lib/search-tokens.js +3 -1
  536. package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
  537. package/dist/modules/query_index/subscribers/coverage_refresh.js +3 -1
  538. package/dist/modules/query_index/subscribers/coverage_refresh.js.map +2 -2
  539. package/dist/modules/resources/api/comments.js +3 -1
  540. package/dist/modules/resources/api/comments.js.map +2 -2
  541. package/dist/modules/resources/api/resources/tags/assign/route.js +3 -1
  542. package/dist/modules/resources/api/resources/tags/assign/route.js.map +2 -2
  543. package/dist/modules/resources/api/resources/tags/unassign/route.js +3 -1
  544. package/dist/modules/resources/api/resources/tags/unassign/route.js.map +2 -2
  545. package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js +3 -1
  546. package/dist/modules/resources/backend/resources/resource-types/[id]/edit/page.js.map +2 -2
  547. package/dist/modules/resources/backend/resources/resource-types/page.js +4 -2
  548. package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
  549. package/dist/modules/resources/commands/activities.js +6 -5
  550. package/dist/modules/resources/commands/activities.js.map +2 -2
  551. package/dist/modules/resources/commands/comments.js +6 -4
  552. package/dist/modules/resources/commands/comments.js.map +2 -2
  553. package/dist/modules/resources/commands/shared.js +24 -1
  554. package/dist/modules/resources/commands/shared.js.map +2 -2
  555. package/dist/modules/sales/api/channels/route.js +3 -1
  556. package/dist/modules/sales/api/channels/route.js.map +2 -2
  557. package/dist/modules/sales/api/document-history/route.js +3 -1
  558. package/dist/modules/sales/api/document-history/route.js.map +2 -2
  559. package/dist/modules/sales/api/document-numbers/route.js +3 -1
  560. package/dist/modules/sales/api/document-numbers/route.js.map +2 -2
  561. package/dist/modules/sales/api/quotes/accept/route.js +4 -2
  562. package/dist/modules/sales/api/quotes/accept/route.js.map +2 -2
  563. package/dist/modules/sales/api/quotes/convert/route.js +3 -1
  564. package/dist/modules/sales/api/quotes/convert/route.js.map +2 -2
  565. package/dist/modules/sales/api/quotes/public/[token]/route.js +3 -1
  566. package/dist/modules/sales/api/quotes/public/[token]/route.js.map +2 -2
  567. package/dist/modules/sales/api/quotes/send/route.js +3 -1
  568. package/dist/modules/sales/api/quotes/send/route.js.map +2 -2
  569. package/dist/modules/sales/api/returns/[id]/route.js +3 -1
  570. package/dist/modules/sales/api/returns/[id]/route.js.map +2 -2
  571. package/dist/modules/sales/api/settings/document-numbers/route.js +4 -2
  572. package/dist/modules/sales/api/settings/document-numbers/route.js.map +2 -2
  573. package/dist/modules/sales/api/settings/order-editing/route.js +4 -2
  574. package/dist/modules/sales/api/settings/order-editing/route.js.map +2 -2
  575. package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js +3 -1
  576. package/dist/modules/sales/backend/sales/channels/[channelId]/edit/page.js.map +2 -2
  577. package/dist/modules/sales/backend/sales/channels/offers/page.js +6 -4
  578. package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
  579. package/dist/modules/sales/backend/sales/channels/page.js +4 -2
  580. package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
  581. package/dist/modules/sales/backend/sales/documents/[id]/page.js +20 -18
  582. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  583. package/dist/modules/sales/commands/documents.js +4 -8
  584. package/dist/modules/sales/commands/documents.js.map +2 -2
  585. package/dist/modules/sales/commands/payments.js +3 -1
  586. package/dist/modules/sales/commands/payments.js.map +2 -2
  587. package/dist/modules/sales/commands/shipments.js +3 -1
  588. package/dist/modules/sales/commands/shipments.js.map +2 -2
  589. package/dist/modules/sales/components/AdjustmentKindSettings.js +5 -3
  590. package/dist/modules/sales/components/AdjustmentKindSettings.js.map +2 -2
  591. package/dist/modules/sales/components/DocumentNumberSettings.js +4 -2
  592. package/dist/modules/sales/components/DocumentNumberSettings.js.map +2 -2
  593. package/dist/modules/sales/components/OrderEditingSettings.js +4 -2
  594. package/dist/modules/sales/components/OrderEditingSettings.js.map +2 -2
  595. package/dist/modules/sales/components/PaymentMethodsSettings.js +5 -3
  596. package/dist/modules/sales/components/PaymentMethodsSettings.js.map +2 -2
  597. package/dist/modules/sales/components/ShippingMethodsSettings.js +5 -3
  598. package/dist/modules/sales/components/ShippingMethodsSettings.js.map +2 -2
  599. package/dist/modules/sales/components/StatusSettings.js +5 -3
  600. package/dist/modules/sales/components/StatusSettings.js.map +2 -2
  601. package/dist/modules/sales/components/TaxRatesSettings.js +5 -3
  602. package/dist/modules/sales/components/TaxRatesSettings.js.map +2 -2
  603. package/dist/modules/sales/components/channels/ChannelOfferForm.js +16 -14
  604. package/dist/modules/sales/components/channels/ChannelOfferForm.js.map +2 -2
  605. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +4 -2
  606. package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
  607. package/dist/modules/sales/components/documents/AddressesSection.js +5 -3
  608. package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
  609. package/dist/modules/sales/components/documents/AdjustmentDialog.js +3 -1
  610. package/dist/modules/sales/components/documents/AdjustmentDialog.js.map +2 -2
  611. package/dist/modules/sales/components/documents/AdjustmentsSection.js +5 -3
  612. package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
  613. package/dist/modules/sales/components/documents/ItemsSection.js +6 -4
  614. package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
  615. package/dist/modules/sales/components/documents/LineItemDialog.js +8 -6
  616. package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
  617. package/dist/modules/sales/components/documents/PaymentDialog.js +5 -3
  618. package/dist/modules/sales/components/documents/PaymentDialog.js.map +2 -2
  619. package/dist/modules/sales/components/documents/PaymentsSection.js +4 -2
  620. package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
  621. package/dist/modules/sales/components/documents/SalesDocumentForm.js +14 -12
  622. package/dist/modules/sales/components/documents/SalesDocumentForm.js.map +2 -2
  623. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +5 -3
  624. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  625. package/dist/modules/sales/components/documents/ShipmentDialog.js +9 -7
  626. package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
  627. package/dist/modules/sales/components/documents/ShipmentsSection.js +4 -2
  628. package/dist/modules/sales/components/documents/ShipmentsSection.js.map +2 -2
  629. package/dist/modules/sales/frontend/quote/[token]/page.js +4 -2
  630. package/dist/modules/sales/frontend/quote/[token]/page.js.map +2 -2
  631. package/dist/modules/sales/seed/examples.js +7 -9
  632. package/dist/modules/sales/seed/examples.js.map +2 -2
  633. package/dist/modules/sales/subscribers/quote-expiring-notification.js +3 -1
  634. package/dist/modules/sales/subscribers/quote-expiring-notification.js.map +2 -2
  635. package/dist/modules/sales/subscribers/reconcileOnAddressDelete.js +3 -1
  636. package/dist/modules/sales/subscribers/reconcileOnAddressDelete.js.map +2 -2
  637. package/dist/modules/sales/subscribers/reconcileOnCompanyDelete.js +3 -1
  638. package/dist/modules/sales/subscribers/reconcileOnCompanyDelete.js.map +2 -2
  639. package/dist/modules/sales/subscribers/reconcileOnCustomerDelete.js +3 -1
  640. package/dist/modules/sales/subscribers/reconcileOnCustomerDelete.js.map +2 -2
  641. package/dist/modules/sales/widgets/dashboard/makeDashboardWidgetRoute.js +5 -3
  642. package/dist/modules/sales/widgets/dashboard/makeDashboardWidgetRoute.js.map +2 -2
  643. package/dist/modules/sales/widgets/dashboard/new-orders/widget.client.js +3 -1
  644. package/dist/modules/sales/widgets/dashboard/new-orders/widget.client.js.map +2 -2
  645. package/dist/modules/sales/widgets/dashboard/new-quotes/widget.client.js +3 -1
  646. package/dist/modules/sales/widgets/dashboard/new-quotes/widget.client.js.map +2 -2
  647. package/dist/modules/shipping_carriers/api/tracking/route.js +5 -0
  648. package/dist/modules/shipping_carriers/api/tracking/route.js.map +2 -2
  649. package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js +3 -1
  650. package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js.map +2 -2
  651. package/dist/modules/shipping_carriers/lib/shipping-service.js +41 -19
  652. package/dist/modules/shipping_carriers/lib/shipping-service.js.map +2 -2
  653. package/dist/modules/shipping_carriers/lib/upstream-error-response.js +3 -1
  654. package/dist/modules/shipping_carriers/lib/upstream-error-response.js.map +2 -2
  655. package/dist/modules/shipping_carriers/workers/webhook-processor.js +3 -5
  656. package/dist/modules/shipping_carriers/workers/webhook-processor.js.map +2 -2
  657. package/dist/modules/staff/api/comments.js +3 -1
  658. package/dist/modules/staff/api/comments.js.map +2 -2
  659. package/dist/modules/staff/api/leave-requests/accept/route.js +3 -1
  660. package/dist/modules/staff/api/leave-requests/accept/route.js.map +2 -2
  661. package/dist/modules/staff/api/leave-requests/reject/route.js +3 -1
  662. package/dist/modules/staff/api/leave-requests/reject/route.js.map +2 -2
  663. package/dist/modules/staff/api/team-members/assignable/route.js +3 -1
  664. package/dist/modules/staff/api/team-members/assignable/route.js.map +2 -2
  665. package/dist/modules/staff/api/team-members/self/route.js +4 -2
  666. package/dist/modules/staff/api/team-members/self/route.js.map +2 -2
  667. package/dist/modules/staff/api/team-members/tags/assign/route.js +3 -1
  668. package/dist/modules/staff/api/team-members/tags/assign/route.js.map +2 -2
  669. package/dist/modules/staff/api/team-members/tags/unassign/route.js +3 -1
  670. package/dist/modules/staff/api/team-members/tags/unassign/route.js.map +2 -2
  671. package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js +3 -1
  672. package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js.map +2 -2
  673. package/dist/modules/staff/api/timesheets/my-projects/route.js +3 -1
  674. package/dist/modules/staff/api/timesheets/my-projects/route.js.map +2 -2
  675. package/dist/modules/staff/api/timesheets/projects/kpis/route.js +3 -1
  676. package/dist/modules/staff/api/timesheets/projects/kpis/route.js.map +2 -2
  677. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js +3 -1
  678. package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js.map +2 -2
  679. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js +4 -2
  680. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js.map +2 -2
  681. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js +4 -2
  682. package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js.map +2 -2
  683. package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js +3 -1
  684. package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js.map +2 -2
  685. package/dist/modules/staff/api/timesheets/time-entries/start-timer/route.js +3 -1
  686. package/dist/modules/staff/api/timesheets/time-entries/start-timer/route.js.map +2 -2
  687. package/dist/modules/staff/backend/staff/team-members/page.js +4 -2
  688. package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
  689. package/dist/modules/staff/backend/staff/team-roles/page.js +4 -2
  690. package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
  691. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +4 -2
  692. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  693. package/dist/modules/staff/backend/staff/teams/page.js +4 -2
  694. package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
  695. package/dist/modules/staff/backend/staff/timesheets/page.js +7 -5
  696. package/dist/modules/staff/backend/staff/timesheets/page.js.map +2 -2
  697. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js +3 -1
  698. package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js.map +2 -2
  699. package/dist/modules/staff/backend/staff/timesheets/projects/page.js +4 -2
  700. package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +2 -2
  701. package/dist/modules/staff/commands/timesheets-entries.js +3 -1
  702. package/dist/modules/staff/commands/timesheets-entries.js.map +2 -2
  703. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.js +3 -1
  704. package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.js.map +2 -2
  705. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js +5 -3
  706. package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js.map +2 -2
  707. package/dist/modules/sync_excel/api/import/route.js +3 -1
  708. package/dist/modules/sync_excel/api/import/route.js.map +2 -2
  709. package/dist/modules/translations/api/[entityType]/[entityId]/route.js +5 -3
  710. package/dist/modules/translations/api/[entityType]/[entityId]/route.js.map +2 -2
  711. package/dist/modules/translations/api/get/locales.js +3 -1
  712. package/dist/modules/translations/api/get/locales.js.map +2 -2
  713. package/dist/modules/translations/api/put/locales.js +3 -1
  714. package/dist/modules/translations/api/put/locales.js.map +2 -2
  715. package/dist/modules/translations/components/TranslationManager.js +3 -1
  716. package/dist/modules/translations/components/TranslationManager.js.map +2 -2
  717. package/dist/modules/translations/subscribers/cleanup.js +3 -1
  718. package/dist/modules/translations/subscribers/cleanup.js.map +2 -2
  719. package/dist/modules/workflows/api/definitions/[id]/customize/route.js +4 -2
  720. package/dist/modules/workflows/api/definitions/[id]/customize/route.js.map +2 -2
  721. package/dist/modules/workflows/api/definitions/[id]/reset-to-code/route.js +4 -2
  722. package/dist/modules/workflows/api/definitions/[id]/reset-to-code/route.js.map +2 -2
  723. package/dist/modules/workflows/api/definitions/[id]/route.js +6 -4
  724. package/dist/modules/workflows/api/definitions/[id]/route.js.map +2 -2
  725. package/dist/modules/workflows/api/definitions/route.js +4 -2
  726. package/dist/modules/workflows/api/definitions/route.js.map +2 -2
  727. package/dist/modules/workflows/api/events/[id]/route.js +3 -1
  728. package/dist/modules/workflows/api/events/[id]/route.js.map +2 -2
  729. package/dist/modules/workflows/api/events/route.js +3 -1
  730. package/dist/modules/workflows/api/events/route.js.map +2 -2
  731. package/dist/modules/workflows/api/instances/[id]/advance/route.js +3 -1
  732. package/dist/modules/workflows/api/instances/[id]/advance/route.js.map +2 -2
  733. package/dist/modules/workflows/api/instances/[id]/cancel/route.js +3 -1
  734. package/dist/modules/workflows/api/instances/[id]/cancel/route.js.map +2 -2
  735. package/dist/modules/workflows/api/instances/[id]/events/route.js +3 -1
  736. package/dist/modules/workflows/api/instances/[id]/events/route.js.map +2 -2
  737. package/dist/modules/workflows/api/instances/[id]/retry/route.js +3 -1
  738. package/dist/modules/workflows/api/instances/[id]/retry/route.js.map +2 -2
  739. package/dist/modules/workflows/api/instances/[id]/route.js +3 -1
  740. package/dist/modules/workflows/api/instances/[id]/route.js.map +2 -2
  741. package/dist/modules/workflows/api/instances/[id]/signal/route.js +5 -7
  742. package/dist/modules/workflows/api/instances/[id]/signal/route.js.map +2 -2
  743. package/dist/modules/workflows/api/instances/route.js +5 -3
  744. package/dist/modules/workflows/api/instances/route.js.map +2 -2
  745. package/dist/modules/workflows/api/instances/validate-start/route.js +3 -1
  746. package/dist/modules/workflows/api/instances/validate-start/route.js.map +2 -2
  747. package/dist/modules/workflows/api/signals/route.js +3 -1
  748. package/dist/modules/workflows/api/signals/route.js.map +2 -2
  749. package/dist/modules/workflows/api/tasks/[id]/claim/route.js +3 -1
  750. package/dist/modules/workflows/api/tasks/[id]/claim/route.js.map +2 -2
  751. package/dist/modules/workflows/api/tasks/[id]/complete/route.js +3 -1
  752. package/dist/modules/workflows/api/tasks/[id]/complete/route.js.map +2 -2
  753. package/dist/modules/workflows/api/tasks/[id]/route.js +3 -1
  754. package/dist/modules/workflows/api/tasks/[id]/route.js.map +2 -2
  755. package/dist/modules/workflows/api/tasks/route.js +3 -1
  756. package/dist/modules/workflows/api/tasks/route.js.map +2 -2
  757. package/dist/modules/workflows/backend/definitions/visual-editor/page.js +4 -2
  758. package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
  759. package/dist/modules/workflows/backend/instances/[id]/page.js +5 -3
  760. package/dist/modules/workflows/backend/instances/[id]/page.js.map +2 -2
  761. package/dist/modules/workflows/backend/tasks/[id]/page.js +3 -1
  762. package/dist/modules/workflows/backend/tasks/[id]/page.js.map +2 -2
  763. package/dist/modules/workflows/components/BusinessRulesSelector.js +5 -3
  764. package/dist/modules/workflows/components/BusinessRulesSelector.js.map +2 -2
  765. package/dist/modules/workflows/components/WorkflowSelector.js +5 -3
  766. package/dist/modules/workflows/components/WorkflowSelector.js.map +2 -2
  767. package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js +3 -1
  768. package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js.map +2 -2
  769. package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js +3 -1
  770. package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js.map +2 -2
  771. package/dist/modules/workflows/components/fields/WorkflowSelectorField.js +3 -1
  772. package/dist/modules/workflows/components/fields/WorkflowSelectorField.js.map +2 -2
  773. package/dist/modules/workflows/frontend/checkout-demo/page.js +8 -7
  774. package/dist/modules/workflows/frontend/checkout-demo/page.js.map +2 -2
  775. package/dist/modules/workflows/lib/activity-executor.js +25 -21
  776. package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
  777. package/dist/modules/workflows/lib/activity-worker-handler.js +8 -15
  778. package/dist/modules/workflows/lib/activity-worker-handler.js.map +2 -2
  779. package/dist/modules/workflows/lib/code-registry.js +7 -7
  780. package/dist/modules/workflows/lib/code-registry.js.map +2 -2
  781. package/dist/modules/workflows/lib/compensation-handler.js +4 -2
  782. package/dist/modules/workflows/lib/compensation-handler.js.map +2 -2
  783. package/dist/modules/workflows/lib/edgeFormTransforms.js +3 -1
  784. package/dist/modules/workflows/lib/edgeFormTransforms.js.map +2 -2
  785. package/dist/modules/workflows/lib/event-trigger-service.js +5 -3
  786. package/dist/modules/workflows/lib/event-trigger-service.js.map +2 -2
  787. package/dist/modules/workflows/lib/nodeFormTransforms.js +3 -1
  788. package/dist/modules/workflows/lib/nodeFormTransforms.js.map +2 -2
  789. package/dist/modules/workflows/lib/seeds.js +16 -2
  790. package/dist/modules/workflows/lib/seeds.js.map +2 -2
  791. package/dist/modules/workflows/lib/signal-handler.js +3 -1
  792. package/dist/modules/workflows/lib/signal-handler.js.map +2 -2
  793. package/dist/modules/workflows/lib/start-validator.js +9 -3
  794. package/dist/modules/workflows/lib/start-validator.js.map +2 -2
  795. package/dist/modules/workflows/lib/step-handler.js +3 -1
  796. package/dist/modules/workflows/lib/step-handler.js.map +2 -2
  797. package/dist/modules/workflows/lib/task-handler.js +3 -1
  798. package/dist/modules/workflows/lib/task-handler.js.map +2 -2
  799. package/dist/modules/workflows/lib/transition-handler.js +5 -3
  800. package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
  801. package/dist/modules/workflows/lib/workflow-executor.js +27 -15
  802. package/dist/modules/workflows/lib/workflow-executor.js.map +2 -2
  803. package/dist/modules/workflows/subscribers/event-trigger.js +21 -18
  804. package/dist/modules/workflows/subscribers/event-trigger.js.map +2 -2
  805. package/dist/modules/workflows/subscribers/task-assigned-notification.js +3 -1
  806. package/dist/modules/workflows/subscribers/task-assigned-notification.js.map +2 -2
  807. package/dist/modules/workflows/workers/workflow-activities.worker.js +30 -20
  808. package/dist/modules/workflows/workers/workflow-activities.worker.js.map +2 -2
  809. package/package.json +7 -7
  810. package/src/bootstrap.ts +14 -11
  811. package/src/helpers/integration/queue-runner.ts +2 -2
  812. package/src/modules/api_keys/services/apiKeyService.ts +6 -3
  813. package/src/modules/attachments/api/image/[id]/[[...slug]]/route.ts +5 -2
  814. package/src/modules/attachments/api/library/[id]/route.ts +4 -1
  815. package/src/modules/attachments/api/route.ts +9 -6
  816. package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +6 -3
  817. package/src/modules/attachments/lib/assignmentDetails.ts +4 -1
  818. package/src/modules/attachments/lib/drivers/driverFactory.ts +4 -1
  819. package/src/modules/attachments/lib/ocrQueue.ts +11 -11
  820. package/src/modules/attachments/lib/ocrService.ts +7 -4
  821. package/src/modules/audit_logs/api/audit-logs/actions/redo/route.ts +4 -1
  822. package/src/modules/audit_logs/api/audit-logs/actions/undo/route.ts +4 -1
  823. package/src/modules/audit_logs/backend/audit-logs/page.tsx +4 -1
  824. package/src/modules/audit_logs/components/AuditLogsActions.tsx +5 -2
  825. package/src/modules/audit_logs/services/accessLogService.ts +5 -4
  826. package/src/modules/audit_logs/services/actionLogService.ts +5 -2
  827. package/src/modules/auth/api/profile/route.ts +5 -2
  828. package/src/modules/auth/api/reset/confirm.ts +4 -1
  829. package/src/modules/auth/api/reset.ts +5 -2
  830. package/src/modules/auth/api/roles/route.ts +4 -1
  831. package/src/modules/auth/api/sidebar/variants/route.ts +4 -2
  832. package/src/modules/auth/api/users/resend-invite/route.ts +5 -2
  833. package/src/modules/auth/api/users/route.ts +4 -1
  834. package/src/modules/auth/backend/auth/profile/page.tsx +4 -1
  835. package/src/modules/auth/backend/profile/change-password/page.tsx +4 -1
  836. package/src/modules/auth/backend/users/[id]/edit/page.tsx +6 -3
  837. package/src/modules/auth/backend/users/create/page.tsx +5 -2
  838. package/src/modules/auth/cli.ts +10 -0
  839. package/src/modules/auth/commands/users.ts +5 -2
  840. package/src/modules/auth/lib/consentIntegrity.ts +4 -4
  841. package/src/modules/auth/lib/setup-app.ts +10 -10
  842. package/src/modules/auth/lib/tenantAccess.ts +4 -1
  843. package/src/modules/auth/lib/tokenHash.ts +4 -4
  844. package/src/modules/business_rules/api/rules/route.ts +5 -2
  845. package/src/modules/business_rules/lib/expression-evaluator.ts +8 -6
  846. package/src/modules/business_rules/lib/rule-engine.ts +6 -3
  847. package/src/modules/business_rules/lib/rule-evaluator.ts +11 -11
  848. package/src/modules/business_rules/subscribers/crud-rule-trigger.ts +4 -1
  849. package/src/modules/business_rules/subscribers/rule-execution-failed-notification.ts +4 -1
  850. package/src/modules/catalog/ai-agents-context.ts +5 -5
  851. package/src/modules/catalog/ai-tools/_shared.ts +4 -1
  852. package/src/modules/catalog/ai-tools/authoring-pack.ts +4 -1
  853. package/src/modules/catalog/ai-tools/merchandising-pack.ts +4 -1
  854. package/src/modules/catalog/api/dictionaries/[key]/route.ts +4 -1
  855. package/src/modules/catalog/api/prices/route.ts +4 -1
  856. package/src/modules/catalog/api/products/route.ts +6 -3
  857. package/src/modules/catalog/api/settings/route.ts +5 -2
  858. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +15 -12
  859. package/src/modules/catalog/backend/catalog/products/[productId]/variants/[variantId]/page.tsx +9 -6
  860. package/src/modules/catalog/backend/catalog/products/[productId]/variants/create/page.tsx +6 -3
  861. package/src/modules/catalog/backend/catalog/products/create/page.tsx +6 -6
  862. package/src/modules/catalog/backend/catalog/products/optionSchemaClient.ts +4 -1
  863. package/src/modules/catalog/components/PriceKindSettings.tsx +6 -3
  864. package/src/modules/catalog/components/UnitPriceDisplaySettings.tsx +5 -2
  865. package/src/modules/catalog/inbox-actions.ts +5 -2
  866. package/src/modules/catalog/seed/examples.ts +5 -5
  867. package/src/modules/catalog/subscribers/low-stock-notification.ts +4 -1
  868. package/src/modules/catalog/widgets/injection/product-seo/state.ts +4 -1
  869. package/src/modules/communication_channels/api/get/oauth/[provider]/callback/route.ts +13 -13
  870. package/src/modules/communication_channels/api/post/channels/[id]/import-history/route.ts +4 -1
  871. package/src/modules/communication_channels/api/post/channels/[id]/push/register/route.ts +4 -1
  872. package/src/modules/communication_channels/api/post/webhook/[provider]/route.ts +6 -3
  873. package/src/modules/communication_channels/api/post/webhooks/gmail/route.ts +7 -6
  874. package/src/modules/communication_channels/commands/connect-credential-channel.ts +5 -10
  875. package/src/modules/communication_channels/commands/delete-channel.ts +4 -5
  876. package/src/modules/communication_channels/commands/deliver-outbound-message.ts +5 -5
  877. package/src/modules/communication_channels/commands/disconnect-channel.ts +4 -5
  878. package/src/modules/communication_channels/commands/ingest-inbound-message.ts +6 -12
  879. package/src/modules/communication_channels/commands/push-unregister.ts +4 -3
  880. package/src/modules/communication_channels/commands/reassign-conversation.ts +6 -3
  881. package/src/modules/communication_channels/lib/dead-letter.ts +4 -5
  882. package/src/modules/communication_channels/lib/email-mime.ts +5 -6
  883. package/src/modules/communication_channels/lib/oauth-client-config.ts +7 -3
  884. package/src/modules/communication_channels/lib/send-as-user.ts +4 -1
  885. package/src/modules/communication_channels/lib/thread-token.ts +5 -2
  886. package/src/modules/communication_channels/setup.ts +4 -4
  887. package/src/modules/communication_channels/workers/channel-import-history.ts +5 -8
  888. package/src/modules/communication_channels/workers/gmail-history-sync.ts +9 -18
  889. package/src/modules/communication_channels/workers/gmail-renew-watch.ts +6 -9
  890. package/src/modules/communication_channels/workers/outbound-delivery.ts +7 -12
  891. package/src/modules/communication_channels/workers/poll-channel.ts +8 -15
  892. package/src/modules/communication_channels/workers/poll-tick.ts +6 -6
  893. package/src/modules/communication_channels/workers/reaction-processor.ts +6 -9
  894. package/src/modules/configs/api/cache/route.ts +5 -2
  895. package/src/modules/configs/api/system-status/route.ts +5 -2
  896. package/src/modules/configs/api/upgrade-actions/route.ts +5 -2
  897. package/src/modules/configs/components/ModuleTelemetryPanel.tsx +4 -1
  898. package/src/modules/configs/lib/touchGeneratedBarrels.ts +1 -1
  899. package/src/modules/configs/services/upgradeActionsService.ts +7 -3
  900. package/src/modules/currencies/components/CurrencyFetchingConfig.tsx +4 -1
  901. package/src/modules/currencies/lib/exchangeRateFormConfig.ts +4 -1
  902. package/src/modules/currencies/services/providers/nbp.ts +7 -4
  903. package/src/modules/currencies/services/providers/raiffeisen.ts +8 -7
  904. package/src/modules/customer_accounts/api/domain-resolve/all.ts +7 -5
  905. package/src/modules/customer_accounts/api/signup.ts +5 -2
  906. package/src/modules/customer_accounts/lib/customerAuthServer.ts +4 -1
  907. package/src/modules/customer_accounts/subscribers/autoLinkCrm.ts +4 -1
  908. package/src/modules/customer_accounts/subscribers/autoLinkCrmReverse.ts +4 -1
  909. package/src/modules/customer_accounts/subscribers/unlinkOnCompanyDelete.ts +4 -1
  910. package/src/modules/customer_accounts/subscribers/unlinkOnPersonDelete.ts +4 -1
  911. package/src/modules/customers/ai-agents-context.ts +5 -5
  912. package/src/modules/customers/api/activities/route.ts +7 -4
  913. package/src/modules/customers/api/comments/route.ts +4 -1
  914. package/src/modules/customers/api/companies/[id]/people/route.ts +4 -1
  915. package/src/modules/customers/api/companies/[id]/route.ts +6 -3
  916. package/src/modules/customers/api/companies/route.ts +6 -3
  917. package/src/modules/customers/api/dashboard/widgets/customer-todos/route.ts +4 -1
  918. package/src/modules/customers/api/dashboard/widgets/new-customers/route.ts +4 -1
  919. package/src/modules/customers/api/dashboard/widgets/new-deals/route.ts +4 -1
  920. package/src/modules/customers/api/dashboard/widgets/next-interactions/route.ts +4 -1
  921. package/src/modules/customers/api/deals/[id]/companies/route.ts +4 -1
  922. package/src/modules/customers/api/deals/[id]/people/route.ts +4 -1
  923. package/src/modules/customers/api/deals/aggregate/route.ts +4 -1
  924. package/src/modules/customers/api/deals/bulk-update-owner/route.ts +8 -5
  925. package/src/modules/customers/api/deals/bulk-update-stage/route.ts +8 -5
  926. package/src/modules/customers/api/deals/route.ts +4 -1
  927. package/src/modules/customers/api/deals/summary/route.ts +4 -1
  928. package/src/modules/customers/api/dictionaries/[kind]/[id]/route.ts +5 -2
  929. package/src/modules/customers/api/dictionaries/[kind]/route.ts +6 -3
  930. package/src/modules/customers/api/dictionaries/cache.ts +4 -1
  931. package/src/modules/customers/api/dictionaries/context.ts +4 -1
  932. package/src/modules/customers/api/dictionaries/currency/route.ts +4 -1
  933. package/src/modules/customers/api/dictionaries/kind-settings/route.ts +5 -2
  934. package/src/modules/customers/api/entity-roles-factory.ts +8 -5
  935. package/src/modules/customers/api/interactions/cancel/route.ts +4 -1
  936. package/src/modules/customers/api/interactions/complete/route.ts +4 -1
  937. package/src/modules/customers/api/interactions/conflicts/route.ts +4 -1
  938. package/src/modules/customers/api/interactions/counts/route.ts +4 -1
  939. package/src/modules/customers/api/interactions/route.ts +8 -4
  940. package/src/modules/customers/api/interactions/tasks/route.ts +4 -1
  941. package/src/modules/customers/api/labels/assign/route.ts +4 -1
  942. package/src/modules/customers/api/labels/route.ts +7 -3
  943. package/src/modules/customers/api/labels/unassign/route.ts +4 -1
  944. package/src/modules/customers/api/people/[id]/companies/enriched/route.ts +4 -1
  945. package/src/modules/customers/api/people/[id]/route.ts +6 -3
  946. package/src/modules/customers/api/people/route.ts +6 -3
  947. package/src/modules/customers/api/pipeline-stages/reorder/route.ts +4 -1
  948. package/src/modules/customers/api/pipeline-stages/route.ts +7 -4
  949. package/src/modules/customers/api/pipelines/route.ts +7 -4
  950. package/src/modules/customers/api/settings/address-format/route.ts +5 -2
  951. package/src/modules/customers/api/settings/dictionary-sort-modes/route.ts +5 -2
  952. package/src/modules/customers/api/settings/stuck-threshold/route.ts +5 -2
  953. package/src/modules/customers/api/tags/assign/route.ts +4 -1
  954. package/src/modules/customers/api/tags/unassign/route.ts +4 -1
  955. package/src/modules/customers/api/todos/route.ts +7 -4
  956. package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +6 -3
  957. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.ts +4 -1
  958. package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealClosure.ts +4 -1
  959. package/src/modules/customers/backend/customers/deals/map/components/DealsMapCanvasImpl.tsx +5 -3
  960. package/src/modules/customers/backend/customers/deals/page.tsx +5 -2
  961. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +6 -3
  962. package/src/modules/customers/commands/deals.ts +4 -1
  963. package/src/modules/customers/commands/dictionaries.ts +4 -1
  964. package/src/modules/customers/commands/interactions.ts +5 -2
  965. package/src/modules/customers/commands/shared.ts +5 -2
  966. package/src/modules/customers/commands/todos.ts +4 -1
  967. package/src/modules/customers/components/DictionarySettings.tsx +6 -3
  968. package/src/modules/customers/components/DictionarySortSettings.tsx +4 -1
  969. package/src/modules/customers/components/detail/ActivitiesCard.tsx +4 -1
  970. package/src/modules/customers/components/detail/ActivitiesDayStrip.tsx +4 -1
  971. package/src/modules/customers/components/detail/ActivitiesSection.tsx +7 -4
  972. package/src/modules/customers/components/detail/ActivityCard.tsx +4 -1
  973. package/src/modules/customers/components/detail/ChangelogTab.tsx +4 -1
  974. package/src/modules/customers/components/detail/CompanyCard.tsx +4 -1
  975. package/src/modules/customers/components/detail/ConfirmDealLostDialog.tsx +4 -1
  976. package/src/modules/customers/components/detail/EntityTagsDialog.tsx +4 -1
  977. package/src/modules/customers/components/detail/InlineActivityComposer.tsx +4 -1
  978. package/src/modules/customers/components/detail/ManageTagsDialog.tsx +4 -1
  979. package/src/modules/customers/components/detail/RoleAssignmentRow.tsx +6 -3
  980. package/src/modules/customers/components/detail/RolesSection.tsx +5 -2
  981. package/src/modules/customers/components/detail/hooks/useInteractionMutations.ts +6 -3
  982. package/src/modules/customers/components/linking/LinkEntityDialog.tsx +5 -2
  983. package/src/modules/customers/inbox-actions.ts +4 -1
  984. package/src/modules/customers/lib/bulkDeals.ts +4 -1
  985. package/src/modules/customers/lib/dealClosureNotification.ts +5 -2
  986. package/src/modules/customers/lib/dealStageTransitionTable.ts +4 -1
  987. package/src/modules/customers/lib/interactionFeatureFlags.ts +5 -1
  988. package/src/modules/customers/lib/todoCompatibility.ts +4 -1
  989. package/src/modules/customers/search.ts +15 -7
  990. package/src/modules/customers/widgets/dashboard/customer-todos/widget.client.tsx +4 -1
  991. package/src/modules/customers/widgets/dashboard/new-customers/widget.client.tsx +4 -1
  992. package/src/modules/customers/widgets/dashboard/new-deals/widget.client.tsx +4 -1
  993. package/src/modules/customers/widgets/dashboard/next-interactions/widget.client.tsx +4 -1
  994. package/src/modules/dashboards/api/widgets/data/batch/route.ts +4 -1
  995. package/src/modules/dashboards/api/widgets/data/route.ts +4 -1
  996. package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +6 -3
  997. package/src/modules/dashboards/widgets/dashboard/aov-kpi/widget.client.tsx +4 -1
  998. package/src/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.client.tsx +4 -1
  999. package/src/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.tsx +4 -1
  1000. package/src/modules/dashboards/widgets/dashboard/orders-kpi/widget.client.tsx +4 -1
  1001. package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.client.tsx +4 -1
  1002. package/src/modules/dashboards/widgets/dashboard/revenue-kpi/widget.client.tsx +4 -1
  1003. package/src/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.tsx +4 -1
  1004. package/src/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.tsx +4 -1
  1005. package/src/modules/dashboards/widgets/dashboard/top-customers/widget.client.tsx +4 -1
  1006. package/src/modules/dashboards/widgets/dashboard/top-products/widget.client.tsx +4 -1
  1007. package/src/modules/data_sync/api/run.ts +4 -1
  1008. package/src/modules/data_sync/backend/data-sync/runs/[id]/page.tsx +3 -1
  1009. package/src/modules/data_sync/lib/adapter-registry.ts +16 -4
  1010. package/src/modules/data_sync/lib/sync-engine.ts +31 -2
  1011. package/src/modules/data_sync/workers/sync-export.ts +4 -1
  1012. package/src/modules/data_sync/workers/sync-import.ts +4 -1
  1013. package/src/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.ts +5 -2
  1014. package/src/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.ts +4 -1
  1015. package/src/modules/dictionaries/api/[dictionaryId]/entries/route.ts +5 -2
  1016. package/src/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.ts +4 -1
  1017. package/src/modules/dictionaries/api/[dictionaryId]/route.ts +6 -3
  1018. package/src/modules/dictionaries/api/context.ts +4 -1
  1019. package/src/modules/dictionaries/api/route.ts +5 -2
  1020. package/src/modules/dictionaries/components/DictionariesManager.tsx +6 -3
  1021. package/src/modules/dictionaries/components/DictionaryEntriesEditor.tsx +5 -2
  1022. package/src/modules/dictionaries/components/DictionaryEntrySelect.tsx +5 -2
  1023. package/src/modules/dictionaries/components/DictionarySelectControl.tsx +4 -1
  1024. package/src/modules/dictionaries/fields/dictionary.tsx +4 -1
  1025. package/src/modules/directory/api/organization-branding/route.ts +4 -1
  1026. package/src/modules/directory/api/organization-switcher/route.ts +4 -1
  1027. package/src/modules/directory/commands/tenants.ts +6 -3
  1028. package/src/modules/directory/utils/organizationScope.ts +7 -4
  1029. package/src/modules/entities/api/definitions.cache.ts +4 -1
  1030. package/src/modules/entities/api/definitions.ts +8 -5
  1031. package/src/modules/entities/api/records.ts +5 -2
  1032. package/src/modules/entities/components/EncryptionManager.tsx +4 -1
  1033. package/src/modules/entities/lib/makeActivityRoute.ts +4 -1
  1034. package/src/modules/feature_toggles/api/overrides/route.ts +4 -1
  1035. package/src/modules/feature_toggles/lib/feature-flag-check.ts +6 -9
  1036. package/src/modules/inbox_ops/api/emails/[id]/reprocess/route.ts +5 -2
  1037. package/src/modules/inbox_ops/api/emails/[id]/route.ts +5 -2
  1038. package/src/modules/inbox_ops/api/emails/route.ts +4 -1
  1039. package/src/modules/inbox_ops/api/extract/route.ts +4 -1
  1040. package/src/modules/inbox_ops/api/proposals/[id]/actions/[actionId]/route.ts +4 -1
  1041. package/src/modules/inbox_ops/api/proposals/[id]/replies/[replyId]/send/route.ts +5 -2
  1042. package/src/modules/inbox_ops/api/proposals/counts/route.ts +5 -2
  1043. package/src/modules/inbox_ops/api/proposals/route.ts +4 -1
  1044. package/src/modules/inbox_ops/api/routeHelpers.ts +4 -1
  1045. package/src/modules/inbox_ops/api/settings/route.ts +4 -1
  1046. package/src/modules/inbox_ops/api/webhook/inbound.ts +8 -5
  1047. package/src/modules/inbox_ops/lib/cache.ts +5 -2
  1048. package/src/modules/inbox_ops/lib/catalogLookup.ts +4 -1
  1049. package/src/modules/inbox_ops/lib/eventBus.ts +4 -4
  1050. package/src/modules/inbox_ops/lib/messagesIntegration.ts +5 -8
  1051. package/src/modules/inbox_ops/subscribers/executionAuditor.ts +5 -1
  1052. package/src/modules/inbox_ops/subscribers/extractionWorker.ts +11 -8
  1053. package/src/modules/inbox_ops/subscribers/proposalNotifier.ts +4 -1
  1054. package/src/modules/messages/api/[id]/route.ts +4 -4
  1055. package/src/modules/messages/commands/actions.ts +4 -1
  1056. package/src/modules/messages/components/MessagesInboxPageClient.tsx +4 -1
  1057. package/src/modules/messages/lib/email-sender.ts +4 -7
  1058. package/src/modules/messages/lib/message-objects-registry.ts +4 -1
  1059. package/src/modules/messages/lib/message-types-registry.ts +4 -1
  1060. package/src/modules/messages/workers/send-email.worker.ts +7 -4
  1061. package/src/modules/notifications/lib/notificationMapper.ts +4 -4
  1062. package/src/modules/notifications/lib/notificationService.ts +4 -5
  1063. package/src/modules/notifications/subscribers/deliver-notification.ts +9 -14
  1064. package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +4 -1
  1065. package/src/modules/perspectives/services/perspectiveService.ts +4 -3
  1066. package/src/modules/planner/api/access.ts +4 -3
  1067. package/src/modules/planner/api/availability-date-specific.ts +4 -1
  1068. package/src/modules/planner/api/availability-weekly.ts +4 -1
  1069. package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +5 -2
  1070. package/src/modules/planner/components/AvailabilityRulesEditor.tsx +4 -1
  1071. package/src/modules/progress/api/jobs/route.ts +4 -1
  1072. package/src/modules/query_index/components/QueryIndexesTable.tsx +6 -3
  1073. package/src/modules/query_index/lib/batch.ts +5 -2
  1074. package/src/modules/query_index/lib/coverage.ts +4 -1
  1075. package/src/modules/query_index/lib/engine.ts +14 -17
  1076. package/src/modules/query_index/lib/reindexer.ts +9 -6
  1077. package/src/modules/query_index/lib/search-tokens.ts +4 -2
  1078. package/src/modules/query_index/subscribers/coverage_refresh.ts +4 -1
  1079. package/src/modules/resources/api/comments.ts +4 -1
  1080. package/src/modules/resources/api/resources/tags/assign/route.ts +4 -1
  1081. package/src/modules/resources/api/resources/tags/unassign/route.ts +4 -1
  1082. package/src/modules/resources/backend/resources/resource-types/[id]/edit/page.tsx +4 -1
  1083. package/src/modules/resources/backend/resources/resource-types/page.tsx +5 -2
  1084. package/src/modules/resources/commands/activities.ts +5 -4
  1085. package/src/modules/resources/commands/comments.ts +6 -4
  1086. package/src/modules/resources/commands/shared.ts +36 -0
  1087. package/src/modules/sales/api/channels/route.ts +4 -1
  1088. package/src/modules/sales/api/document-history/route.ts +4 -1
  1089. package/src/modules/sales/api/document-numbers/route.ts +4 -1
  1090. package/src/modules/sales/api/quotes/accept/route.ts +5 -2
  1091. package/src/modules/sales/api/quotes/convert/route.ts +4 -1
  1092. package/src/modules/sales/api/quotes/public/[token]/route.ts +4 -1
  1093. package/src/modules/sales/api/quotes/send/route.ts +4 -1
  1094. package/src/modules/sales/api/returns/[id]/route.ts +4 -1
  1095. package/src/modules/sales/api/settings/document-numbers/route.ts +5 -2
  1096. package/src/modules/sales/api/settings/order-editing/route.ts +5 -2
  1097. package/src/modules/sales/backend/sales/channels/[channelId]/edit/page.tsx +4 -1
  1098. package/src/modules/sales/backend/sales/channels/offers/page.tsx +7 -4
  1099. package/src/modules/sales/backend/sales/channels/page.tsx +5 -2
  1100. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +21 -18
  1101. package/src/modules/sales/commands/documents.ts +5 -8
  1102. package/src/modules/sales/commands/payments.ts +4 -1
  1103. package/src/modules/sales/commands/shipments.ts +4 -2
  1104. package/src/modules/sales/components/AdjustmentKindSettings.tsx +6 -3
  1105. package/src/modules/sales/components/DocumentNumberSettings.tsx +5 -2
  1106. package/src/modules/sales/components/OrderEditingSettings.tsx +5 -2
  1107. package/src/modules/sales/components/PaymentMethodsSettings.tsx +6 -3
  1108. package/src/modules/sales/components/ShippingMethodsSettings.tsx +6 -3
  1109. package/src/modules/sales/components/StatusSettings.tsx +6 -3
  1110. package/src/modules/sales/components/TaxRatesSettings.tsx +6 -3
  1111. package/src/modules/sales/components/channels/ChannelOfferForm.tsx +17 -14
  1112. package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +5 -2
  1113. package/src/modules/sales/components/documents/AddressesSection.tsx +6 -3
  1114. package/src/modules/sales/components/documents/AdjustmentDialog.tsx +4 -1
  1115. package/src/modules/sales/components/documents/AdjustmentsSection.tsx +6 -3
  1116. package/src/modules/sales/components/documents/ItemsSection.tsx +7 -4
  1117. package/src/modules/sales/components/documents/LineItemDialog.tsx +9 -6
  1118. package/src/modules/sales/components/documents/PaymentDialog.tsx +6 -3
  1119. package/src/modules/sales/components/documents/PaymentsSection.tsx +5 -2
  1120. package/src/modules/sales/components/documents/SalesDocumentForm.tsx +15 -12
  1121. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +6 -3
  1122. package/src/modules/sales/components/documents/ShipmentDialog.tsx +10 -7
  1123. package/src/modules/sales/components/documents/ShipmentsSection.tsx +5 -2
  1124. package/src/modules/sales/frontend/quote/[token]/page.tsx +5 -2
  1125. package/src/modules/sales/seed/examples.ts +8 -9
  1126. package/src/modules/sales/subscribers/quote-expiring-notification.ts +4 -1
  1127. package/src/modules/sales/subscribers/reconcileOnAddressDelete.ts +4 -1
  1128. package/src/modules/sales/subscribers/reconcileOnCompanyDelete.ts +4 -1
  1129. package/src/modules/sales/subscribers/reconcileOnCustomerDelete.ts +4 -1
  1130. package/src/modules/sales/widgets/dashboard/makeDashboardWidgetRoute.ts +6 -3
  1131. package/src/modules/sales/widgets/dashboard/new-orders/widget.client.tsx +274 -271
  1132. package/src/modules/sales/widgets/dashboard/new-quotes/widget.client.tsx +280 -277
  1133. package/src/modules/shipping_carriers/api/tracking/route.ts +5 -1
  1134. package/src/modules/shipping_carriers/api/webhook/[provider]/route.ts +4 -1
  1135. package/src/modules/shipping_carriers/lib/shipping-service.ts +47 -22
  1136. package/src/modules/shipping_carriers/lib/upstream-error-response.ts +4 -1
  1137. package/src/modules/shipping_carriers/workers/webhook-processor.ts +4 -5
  1138. package/src/modules/staff/api/comments.ts +4 -1
  1139. package/src/modules/staff/api/leave-requests/accept/route.ts +4 -1
  1140. package/src/modules/staff/api/leave-requests/reject/route.ts +4 -1
  1141. package/src/modules/staff/api/team-members/assignable/route.ts +4 -1
  1142. package/src/modules/staff/api/team-members/self/route.ts +5 -2
  1143. package/src/modules/staff/api/team-members/tags/assign/route.ts +4 -1
  1144. package/src/modules/staff/api/team-members/tags/unassign/route.ts +4 -1
  1145. package/src/modules/staff/api/timesheets/my-projects/[projectId]/route.ts +4 -1
  1146. package/src/modules/staff/api/timesheets/my-projects/route.ts +4 -1
  1147. package/src/modules/staff/api/timesheets/projects/kpis/route.ts +4 -1
  1148. package/src/modules/staff/api/timesheets/time-entries/[id]/segments/route.ts +4 -1
  1149. package/src/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.ts +5 -2
  1150. package/src/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.ts +5 -2
  1151. package/src/modules/staff/api/timesheets/time-entries/bulk/route.ts +4 -1
  1152. package/src/modules/staff/api/timesheets/time-entries/start-timer/route.ts +4 -1
  1153. package/src/modules/staff/backend/staff/team-members/page.tsx +5 -2
  1154. package/src/modules/staff/backend/staff/team-roles/page.tsx +5 -2
  1155. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +5 -2
  1156. package/src/modules/staff/backend/staff/teams/page.tsx +5 -2
  1157. package/src/modules/staff/backend/staff/timesheets/page.tsx +8 -5
  1158. package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.tsx +4 -1
  1159. package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +5 -2
  1160. package/src/modules/staff/commands/timesheets-entries.ts +4 -1
  1161. package/src/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.tsx +4 -1
  1162. package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.tsx +6 -3
  1163. package/src/modules/sync_excel/api/import/route.ts +4 -1
  1164. package/src/modules/translations/api/[entityType]/[entityId]/route.ts +6 -3
  1165. package/src/modules/translations/api/get/locales.ts +4 -1
  1166. package/src/modules/translations/api/put/locales.ts +4 -1
  1167. package/src/modules/translations/components/TranslationManager.tsx +4 -1
  1168. package/src/modules/translations/subscribers/cleanup.ts +4 -1
  1169. package/src/modules/workflows/api/definitions/[id]/customize/route.ts +5 -2
  1170. package/src/modules/workflows/api/definitions/[id]/reset-to-code/route.ts +5 -2
  1171. package/src/modules/workflows/api/definitions/[id]/route.ts +7 -4
  1172. package/src/modules/workflows/api/definitions/route.ts +5 -2
  1173. package/src/modules/workflows/api/events/[id]/route.ts +4 -1
  1174. package/src/modules/workflows/api/events/route.ts +4 -1
  1175. package/src/modules/workflows/api/instances/[id]/advance/route.ts +4 -1
  1176. package/src/modules/workflows/api/instances/[id]/cancel/route.ts +4 -1
  1177. package/src/modules/workflows/api/instances/[id]/events/route.ts +4 -1
  1178. package/src/modules/workflows/api/instances/[id]/retry/route.ts +4 -1
  1179. package/src/modules/workflows/api/instances/[id]/route.ts +4 -1
  1180. package/src/modules/workflows/api/instances/[id]/signal/route.ts +6 -7
  1181. package/src/modules/workflows/api/instances/route.ts +6 -3
  1182. package/src/modules/workflows/api/instances/validate-start/route.ts +4 -1
  1183. package/src/modules/workflows/api/signals/route.ts +4 -1
  1184. package/src/modules/workflows/api/tasks/[id]/claim/route.ts +4 -1
  1185. package/src/modules/workflows/api/tasks/[id]/complete/route.ts +4 -1
  1186. package/src/modules/workflows/api/tasks/[id]/route.ts +4 -1
  1187. package/src/modules/workflows/api/tasks/route.ts +4 -1
  1188. package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +5 -2
  1189. package/src/modules/workflows/backend/instances/[id]/page.tsx +6 -3
  1190. package/src/modules/workflows/backend/tasks/[id]/page.tsx +4 -1
  1191. package/src/modules/workflows/components/BusinessRulesSelector.tsx +6 -3
  1192. package/src/modules/workflows/components/WorkflowSelector.tsx +6 -3
  1193. package/src/modules/workflows/components/fields/BusinessRuleConditionsEditor.tsx +4 -1
  1194. package/src/modules/workflows/components/fields/StartPreConditionsEditor.tsx +4 -1
  1195. package/src/modules/workflows/components/fields/WorkflowSelectorField.tsx +4 -1
  1196. package/src/modules/workflows/frontend/checkout-demo/page.tsx +9 -7
  1197. package/src/modules/workflows/lib/activity-executor.ts +26 -21
  1198. package/src/modules/workflows/lib/activity-worker-handler.ts +9 -15
  1199. package/src/modules/workflows/lib/code-registry.ts +8 -7
  1200. package/src/modules/workflows/lib/compensation-handler.ts +5 -2
  1201. package/src/modules/workflows/lib/edgeFormTransforms.ts +4 -1
  1202. package/src/modules/workflows/lib/event-trigger-service.ts +6 -3
  1203. package/src/modules/workflows/lib/nodeFormTransforms.ts +4 -1
  1204. package/src/modules/workflows/lib/seeds.ts +17 -2
  1205. package/src/modules/workflows/lib/signal-handler.ts +4 -1
  1206. package/src/modules/workflows/lib/start-validator.ts +10 -3
  1207. package/src/modules/workflows/lib/step-handler.ts +4 -1
  1208. package/src/modules/workflows/lib/task-handler.ts +4 -1
  1209. package/src/modules/workflows/lib/transition-handler.ts +6 -3
  1210. package/src/modules/workflows/lib/workflow-executor.ts +28 -15
  1211. package/src/modules/workflows/subscribers/event-trigger.ts +22 -24
  1212. package/src/modules/workflows/subscribers/task-assigned-notification.ts +4 -1
  1213. package/src/modules/workflows/workers/workflow-activities.worker.ts +31 -20
package/dist/bootstrap.js CHANGED
@@ -14,6 +14,8 @@ import {
14
14
  } from "@open-mercato/search";
15
15
  import { RateLimiterService } from "@open-mercato/shared/lib/ratelimit/service";
16
16
  import { readRateLimitConfig } from "@open-mercato/shared/lib/ratelimit/config";
17
+ import { createLogger } from "@open-mercato/shared/lib/logger";
18
+ const logger = createLogger("core");
17
19
  const RL_GLOBAL_KEY = "__openMercatoRateLimiterService__";
18
20
  const RL_SHUTDOWN_KEY = "__openMercatoRateLimiterShutdown__";
19
21
  const CACHE_GLOBAL_KEY = "__openMercatoCacheService__";
@@ -33,7 +35,7 @@ function getCachedCacheService() {
33
35
  try {
34
36
  service = createCacheService();
35
37
  } catch (err) {
36
- console.warn("Cache service initialization failed; falling back to memory strategy:", err?.message || err);
38
+ logger.warn("Cache service initialization failed; falling back to memory strategy", { err });
37
39
  service = createCacheService({ strategy: "memory" });
38
40
  }
39
41
  ;
@@ -48,7 +50,7 @@ function getCachedCacheService() {
48
50
  globalThis[CACHE_SHUTDOWN_KEY] = true;
49
51
  }
50
52
  } catch (err) {
51
- console.warn("[cache] Failed to create cache service:", err?.message || err);
53
+ logger.warn("Failed to create cache service", { component: "cache", err });
52
54
  }
53
55
  }
54
56
  return service;
@@ -60,7 +62,7 @@ function getCachedRateLimiterService() {
60
62
  const rateLimitConfig = readRateLimitConfig();
61
63
  service = new RateLimiterService(rateLimitConfig);
62
64
  service.initialize().catch((err) => {
63
- console.warn("[ratelimit] Async initialization failed:", err?.message || err);
65
+ logger.warn("Async initialization failed", { component: "ratelimit", err });
64
66
  });
65
67
  globalThis[RL_GLOBAL_KEY] = service;
66
68
  if (!globalThis[RL_SHUTDOWN_KEY]) {
@@ -73,7 +75,7 @@ function getCachedRateLimiterService() {
73
75
  globalThis[RL_SHUTDOWN_KEY] = true;
74
76
  }
75
77
  } catch (err) {
76
- console.warn("[ratelimit] Failed to create rate limiter service:", err?.message || err);
78
+ logger.warn("Failed to create rate limiter service", { component: "ratelimit", err });
77
79
  }
78
80
  }
79
81
  return service;
@@ -84,7 +86,7 @@ async function bootstrap(container) {
84
86
  try {
85
87
  cache = createCacheService();
86
88
  } catch (err) {
87
- console.warn("Cache service initialization failed; falling back to memory strategy:", err?.message || err);
89
+ logger.warn("Cache service initialization failed; falling back to memory strategy", { err });
88
90
  cache = createCacheService({ strategy: "memory" });
89
91
  }
90
92
  }
@@ -95,7 +97,7 @@ async function bootstrap(container) {
95
97
  const queueStrategy = strategyEnv === "async" || strategyEnv === "redis" ? "async" : "local";
96
98
  eventBus = createEventBus({ resolve: container.resolve.bind(container), queueStrategy });
97
99
  } catch (err) {
98
- console.warn("Event bus initialization failed; falling back to local strategy:", err?.message || err);
100
+ logger.warn("Event bus initialization failed; falling back to local strategy", { err });
99
101
  try {
100
102
  eventBus = createEventBus({ resolve: container.resolve.bind(container), queueStrategy: "local" });
101
103
  } catch {
@@ -140,7 +142,7 @@ async function bootstrap(container) {
140
142
  }
141
143
  }
142
144
  } catch (err) {
143
- console.error("Failed to register module subscribers:", err);
145
+ logger.error("Failed to register module subscribers:", { err });
144
146
  }
145
147
  const kmsService = createKmsService();
146
148
  container.register({ kmsService: asValue(kmsService) });
@@ -159,13 +161,13 @@ async function bootstrap(container) {
159
161
  try {
160
162
  registerTenantEncryptionSubscriber(em, tenantEncryptionService);
161
163
  } catch (err) {
162
- console.warn("[encryption] Failed to register MikroORM encryption subscriber:", err?.message || err);
164
+ logger.warn("Failed to register MikroORM encryption subscriber", { component: "encryption", err });
163
165
  }
164
166
  } else if (isTenantDataEncryptionEnabled() && !kmsService.isHealthy()) {
165
- console.warn("[encryption] Vault/KMS unhealthy - tenant data encryption is disabled until recovery");
167
+ logger.warn("Vault/KMS unhealthy - tenant data encryption is disabled until recovery", { component: "encryption" });
166
168
  }
167
169
  } catch (err) {
168
- console.warn("[encryption] Failed to initialize tenant encryption service:", err?.message || err);
170
+ logger.warn("Failed to initialize tenant encryption service", { component: "encryption", err });
169
171
  }
170
172
  const rateLimiterService = getCachedRateLimiterService();
171
173
  if (rateLimiterService) {
@@ -191,7 +193,7 @@ async function bootstrap(container) {
191
193
  } catch {
192
194
  }
193
195
  } catch (err) {
194
- console.warn("[search] Failed to register search module:", err?.message || err);
196
+ logger.warn("Failed to register search module", { component: "search", err });
195
197
  }
196
198
  }
197
199
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/bootstrap.ts"],
4
- "sourcesContent": ["import type { AwilixContainer } from 'awilix'\nimport { asValue } from 'awilix'\nimport type { ModuleSubscriber } from '@open-mercato/shared/modules/registry'\nimport { createEventBus } from '@open-mercato/events/index'\nimport { setGlobalEventBus } from '@open-mercato/shared/modules/events'\nimport { createCacheService } from '@open-mercato/cache'\nimport type { CacheStrategy } from '@open-mercato/cache'\nimport { createKmsService } from '@open-mercato/shared/lib/encryption/kms'\nimport { TenantDataEncryptionService } from '@open-mercato/shared/lib/encryption/tenantDataEncryptionService'\nimport { registerTenantEncryptionSubscriber } from '@open-mercato/shared/lib/encryption/subscriber'\nimport { isTenantDataEncryptionEnabled } from '@open-mercato/shared/lib/encryption/toggles'\nimport { getSearchModuleConfigs } from '@open-mercato/shared/modules/search'\nimport {\n registerSearchModule,\n createSearchDeleteSubscriber,\n searchDeleteMetadata,\n} from '@open-mercato/search'\nimport { RateLimiterService } from '@open-mercato/shared/lib/ratelimit/service'\nimport { readRateLimitConfig } from '@open-mercato/shared/lib/ratelimit/config'\nimport type { EntityManager } from '@mikro-orm/postgresql'\n\n// Use globalThis to survive tsx/webpack module duplication (same pattern as container.ts DI registrars)\nconst RL_GLOBAL_KEY = '__openMercatoRateLimiterService__'\nconst RL_SHUTDOWN_KEY = '__openMercatoRateLimiterShutdown__'\n\nconst CACHE_GLOBAL_KEY = '__openMercatoCacheService__'\nconst CACHE_SHUTDOWN_KEY = '__openMercatoCacheShutdown__'\n\n// Escape hatch: set OM_CACHE_SINGLETON=off to fall back to the legacy\n// per-request cache instance (e.g. to isolate a regression). Default ON.\nfunction isCacheSingletonEnabled(): boolean {\n const raw = process.env.OM_CACHE_SINGLETON\n if (raw === undefined) return true\n const normalized = raw.trim().toLowerCase()\n if (!normalized.length) return true\n return !(normalized === '0' || normalized === 'off' || normalized === 'false' || normalized === 'no')\n}\n\n/**\n * Process-wide cache service singleton, mirroring getCachedRateLimiterService.\n *\n * bootstrap() previously built a fresh cache per request container, so under\n * the default memory strategy every cross-request cache was a no-op (each\n * instance is process-local) and under sqlite each request leaked a native\n * handle. Reusing one instance is safe by construction: tenant scope resolves\n * per-call via AsyncLocalStorage (packages/cache/src/tenantContext.ts), so the\n * service holds no request-bound state.\n *\n * Returns null when disabled via the escape hatch or when creation fails, so\n * the caller falls back to a per-request instance.\n */\nexport function getCachedCacheService(): CacheStrategy | null {\n if (!isCacheSingletonEnabled()) return null\n let service = (globalThis as any)[CACHE_GLOBAL_KEY] as CacheStrategy | null ?? null\n if (!service) {\n try {\n try {\n service = createCacheService()\n } catch (err) {\n console.warn('Cache service initialization failed; falling back to memory strategy:', (err as Error)?.message || err)\n service = createCacheService({ strategy: 'memory' })\n }\n ;(globalThis as any)[CACHE_GLOBAL_KEY] = service\n\n // Register shutdown hook once to close persistent handles (sqlite/redis) on process exit\n if (!(globalThis as any)[CACHE_SHUTDOWN_KEY]) {\n const shutdown = () => { service?.close?.().catch(() => {}) }\n process.once('SIGTERM', shutdown)\n process.once('SIGINT', shutdown)\n ;(globalThis as any)[CACHE_SHUTDOWN_KEY] = true\n }\n } catch (err) {\n console.warn('[cache] Failed to create cache service:', (err as Error)?.message || err)\n }\n }\n return service\n}\n\nexport function getCachedRateLimiterService(): RateLimiterService | null {\n let service = (globalThis as any)[RL_GLOBAL_KEY] as RateLimiterService | null ?? null\n if (!service) {\n try {\n const rateLimitConfig = readRateLimitConfig()\n service = new RateLimiterService(rateLimitConfig)\n // Fire-and-forget async init (only needed for Redis strategy;\n // memory strategy works synchronously, and Redis has an in-memory\n // insurance limiter so the first few requests are still protected)\n service.initialize().catch((err) => {\n console.warn('[ratelimit] Async initialization failed:', (err as Error)?.message || err)\n })\n ;(globalThis as any)[RL_GLOBAL_KEY] = service\n\n // Register shutdown hook once to disconnect Redis on process exit\n if (!(globalThis as any)[RL_SHUTDOWN_KEY]) {\n const shutdown = () => { service?.destroy().catch(() => {}) }\n process.once('SIGTERM', shutdown)\n process.once('SIGINT', shutdown)\n ;(globalThis as any)[RL_SHUTDOWN_KEY] = true\n }\n } catch (err) {\n console.warn('[ratelimit] Failed to create rate limiter service:', (err as Error)?.message || err)\n }\n }\n return service\n}\n\nexport async function bootstrap(container: AwilixContainer) {\n // Register the cache service. Prefer the process-wide singleton so caches\n // survive across request containers; fall back to a per-request instance\n // when the singleton is disabled or fails to build.\n let cache: any = getCachedCacheService()\n if (!cache) {\n try {\n cache = createCacheService()\n } catch (err: any) {\n console.warn('Cache service initialization failed; falling back to memory strategy:', err?.message || err)\n cache = createCacheService({ strategy: 'memory' })\n }\n }\n container.register({ cache: asValue(cache) })\n\n // Create and register the DI-aware event bus\n let eventBus: any\n try {\n // Support both QUEUE_STRATEGY and legacy EVENTS_STRATEGY env vars\n const strategyEnv = process.env.QUEUE_STRATEGY || process.env.EVENTS_STRATEGY\n const queueStrategy = strategyEnv === 'async' || strategyEnv === 'redis' ? 'async' : 'local'\n eventBus = createEventBus({ resolve: container.resolve.bind(container) as any, queueStrategy })\n } catch (err: any) {\n // Fall back to local strategy to avoid breaking the app on misconfiguration\n console.warn('Event bus initialization failed; falling back to local strategy:', err?.message || err)\n try {\n eventBus = createEventBus({ resolve: container.resolve.bind(container) as any, queueStrategy: 'local' })\n } catch {\n // In extreme cases, provide a no-op bus to avoid crashes\n eventBus = {\n emit: async () => {},\n on: () => {},\n registerModuleSubscribers: () => {},\n clearQueue: async () => ({ removed: 0 }),\n }\n }\n }\n container.register({ eventBus: asValue(eventBus) })\n // Wire the global event bus so createModuleEvents().emit works outside DI context\n setGlobalEventBus(eventBus)\n // Auto-register discovered module subscribers\n try {\n let loadedModules: any[] = []\n try {\n const { getModules } = await import('@open-mercato/shared/lib/i18n/server')\n loadedModules = getModules()\n } catch {}\n const subs = loadedModules.flatMap((m) =>\n (m.subscribers || []).map((subscriber: ModuleSubscriber) => ({\n ...subscriber,\n moduleId: subscriber.moduleId ?? m.id,\n })),\n )\n if (subs.length) (container.resolve as any)('eventBus').registerModuleSubscribers(subs)\n\n // Extract sync subscribers and register in the sync-subscriber-store\n const syncSubs = subs.filter((s: any) => s.sync === true)\n if (syncSubs.length) {\n try {\n const { registerSyncSubscribers } = await import('@open-mercato/shared/lib/crud/sync-subscriber-store')\n registerSyncSubscribers(\n syncSubs.map((s: any) => ({\n metadata: { event: s.event, sync: true as const, priority: s.priority, id: s.id },\n handler: s.handler,\n })),\n )\n } catch {\n // sync-subscriber-store may not be available\n }\n }\n } catch (err) {\n console.error(\"Failed to register module subscribers:\", err);\n }\n\n // KMS + tenant encryption\n const kmsService = createKmsService()\n container.register({ kmsService: asValue(kmsService) })\n try {\n const em = container.resolve('em') as EntityManager\n const cacheService = (() => {\n try { return container.resolve('cache') as any } catch { return null }\n })()\n const tenantEncryptionService = new TenantDataEncryptionService(em, { cache: cacheService, kms: kmsService })\n container.register({ tenantEncryptionService: asValue(tenantEncryptionService) })\n if (isTenantDataEncryptionEnabled() && kmsService.isHealthy()) {\n try {\n registerTenantEncryptionSubscriber(em, tenantEncryptionService)\n } catch (err) {\n console.warn('[encryption] Failed to register MikroORM encryption subscriber:', (err as Error)?.message || err)\n }\n } else if (isTenantDataEncryptionEnabled() && !kmsService.isHealthy()) {\n console.warn('[encryption] Vault/KMS unhealthy - tenant data encryption is disabled until recovery')\n }\n } catch (err) {\n console.warn('[encryption] Failed to initialize tenant encryption service:', (err as Error)?.message || err)\n }\n\n // Register rate limiter service (singleton via globalThis \u2014 reused across request containers)\n // getCachedRateLimiterService() never throws; returns null on failure\n const rateLimiterService = getCachedRateLimiterService()\n if (rateLimiterService) {\n container.register({ rateLimiterService: asValue(rateLimiterService) })\n }\n\n // Register search module\n try {\n // Get configs from global registry (registered during app bootstrap)\n const searchModuleConfigs = getSearchModuleConfigs()\n registerSearchModule(container as any, { moduleConfigs: searchModuleConfigs })\n\n // Register searchModuleConfigs in container so status API can access vector-enabled entities\n container.register({\n searchModuleConfigs: asValue(searchModuleConfigs),\n })\n\n // Register search delete event subscriber\n // Note: search.index_record is now handled by auto-discovered fulltext_upsert.ts subscriber\n try {\n const searchIndexer = container.resolve('searchIndexer') as any\n if (searchIndexer && eventBus) {\n eventBus.registerModuleSubscribers([\n {\n event: searchDeleteMetadata.event,\n persistent: searchDeleteMetadata.persistent,\n handler: createSearchDeleteSubscriber(searchIndexer),\n },\n ])\n }\n } catch {\n // searchIndexer may not be available\n }\n } catch (err) {\n console.warn('[search] Failed to register search module:', (err as Error)?.message || err)\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { AwilixContainer } from 'awilix'\nimport { asValue } from 'awilix'\nimport type { ModuleSubscriber } from '@open-mercato/shared/modules/registry'\nimport { createEventBus } from '@open-mercato/events/index'\nimport { setGlobalEventBus } from '@open-mercato/shared/modules/events'\nimport { createCacheService } from '@open-mercato/cache'\nimport type { CacheStrategy } from '@open-mercato/cache'\nimport { createKmsService } from '@open-mercato/shared/lib/encryption/kms'\nimport { TenantDataEncryptionService } from '@open-mercato/shared/lib/encryption/tenantDataEncryptionService'\nimport { registerTenantEncryptionSubscriber } from '@open-mercato/shared/lib/encryption/subscriber'\nimport { isTenantDataEncryptionEnabled } from '@open-mercato/shared/lib/encryption/toggles'\nimport { getSearchModuleConfigs } from '@open-mercato/shared/modules/search'\nimport {\n registerSearchModule,\n createSearchDeleteSubscriber,\n searchDeleteMetadata,\n} from '@open-mercato/search'\nimport { RateLimiterService } from '@open-mercato/shared/lib/ratelimit/service'\nimport { readRateLimitConfig } from '@open-mercato/shared/lib/ratelimit/config'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('core')\n\n// Use globalThis to survive tsx/webpack module duplication (same pattern as container.ts DI registrars)\nconst RL_GLOBAL_KEY = '__openMercatoRateLimiterService__'\nconst RL_SHUTDOWN_KEY = '__openMercatoRateLimiterShutdown__'\n\nconst CACHE_GLOBAL_KEY = '__openMercatoCacheService__'\nconst CACHE_SHUTDOWN_KEY = '__openMercatoCacheShutdown__'\n\n// Escape hatch: set OM_CACHE_SINGLETON=off to fall back to the legacy\n// per-request cache instance (e.g. to isolate a regression). Default ON.\nfunction isCacheSingletonEnabled(): boolean {\n const raw = process.env.OM_CACHE_SINGLETON\n if (raw === undefined) return true\n const normalized = raw.trim().toLowerCase()\n if (!normalized.length) return true\n return !(normalized === '0' || normalized === 'off' || normalized === 'false' || normalized === 'no')\n}\n\n/**\n * Process-wide cache service singleton, mirroring getCachedRateLimiterService.\n *\n * bootstrap() previously built a fresh cache per request container, so under\n * the default memory strategy every cross-request cache was a no-op (each\n * instance is process-local) and under sqlite each request leaked a native\n * handle. Reusing one instance is safe by construction: tenant scope resolves\n * per-call via AsyncLocalStorage (packages/cache/src/tenantContext.ts), so the\n * service holds no request-bound state.\n *\n * Returns null when disabled via the escape hatch or when creation fails, so\n * the caller falls back to a per-request instance.\n */\nexport function getCachedCacheService(): CacheStrategy | null {\n if (!isCacheSingletonEnabled()) return null\n let service = (globalThis as any)[CACHE_GLOBAL_KEY] as CacheStrategy | null ?? null\n if (!service) {\n try {\n try {\n service = createCacheService()\n } catch (err) {\n logger.warn('Cache service initialization failed; falling back to memory strategy', { err })\n service = createCacheService({ strategy: 'memory' })\n }\n ;(globalThis as any)[CACHE_GLOBAL_KEY] = service\n\n // Register shutdown hook once to close persistent handles (sqlite/redis) on process exit\n if (!(globalThis as any)[CACHE_SHUTDOWN_KEY]) {\n const shutdown = () => { service?.close?.().catch(() => {}) }\n process.once('SIGTERM', shutdown)\n process.once('SIGINT', shutdown)\n ;(globalThis as any)[CACHE_SHUTDOWN_KEY] = true\n }\n } catch (err) {\n logger.warn('Failed to create cache service', { component: 'cache', err })\n }\n }\n return service\n}\n\nexport function getCachedRateLimiterService(): RateLimiterService | null {\n let service = (globalThis as any)[RL_GLOBAL_KEY] as RateLimiterService | null ?? null\n if (!service) {\n try {\n const rateLimitConfig = readRateLimitConfig()\n service = new RateLimiterService(rateLimitConfig)\n // Fire-and-forget async init (only needed for Redis strategy;\n // memory strategy works synchronously, and Redis has an in-memory\n // insurance limiter so the first few requests are still protected)\n service.initialize().catch((err) => {\n logger.warn('Async initialization failed', { component: 'ratelimit', err })\n })\n ;(globalThis as any)[RL_GLOBAL_KEY] = service\n\n // Register shutdown hook once to disconnect Redis on process exit\n if (!(globalThis as any)[RL_SHUTDOWN_KEY]) {\n const shutdown = () => { service?.destroy().catch(() => {}) }\n process.once('SIGTERM', shutdown)\n process.once('SIGINT', shutdown)\n ;(globalThis as any)[RL_SHUTDOWN_KEY] = true\n }\n } catch (err) {\n logger.warn('Failed to create rate limiter service', { component: 'ratelimit', err })\n }\n }\n return service\n}\n\nexport async function bootstrap(container: AwilixContainer) {\n // Register the cache service. Prefer the process-wide singleton so caches\n // survive across request containers; fall back to a per-request instance\n // when the singleton is disabled or fails to build.\n let cache: any = getCachedCacheService()\n if (!cache) {\n try {\n cache = createCacheService()\n } catch (err: any) {\n logger.warn('Cache service initialization failed; falling back to memory strategy', { err })\n cache = createCacheService({ strategy: 'memory' })\n }\n }\n container.register({ cache: asValue(cache) })\n\n // Create and register the DI-aware event bus\n let eventBus: any\n try {\n // Support both QUEUE_STRATEGY and legacy EVENTS_STRATEGY env vars\n const strategyEnv = process.env.QUEUE_STRATEGY || process.env.EVENTS_STRATEGY\n const queueStrategy = strategyEnv === 'async' || strategyEnv === 'redis' ? 'async' : 'local'\n eventBus = createEventBus({ resolve: container.resolve.bind(container) as any, queueStrategy })\n } catch (err: any) {\n // Fall back to local strategy to avoid breaking the app on misconfiguration\n logger.warn('Event bus initialization failed; falling back to local strategy', { err })\n try {\n eventBus = createEventBus({ resolve: container.resolve.bind(container) as any, queueStrategy: 'local' })\n } catch {\n // In extreme cases, provide a no-op bus to avoid crashes\n eventBus = {\n emit: async () => {},\n on: () => {},\n registerModuleSubscribers: () => {},\n clearQueue: async () => ({ removed: 0 }),\n }\n }\n }\n container.register({ eventBus: asValue(eventBus) })\n // Wire the global event bus so createModuleEvents().emit works outside DI context\n setGlobalEventBus(eventBus)\n // Auto-register discovered module subscribers\n try {\n let loadedModules: any[] = []\n try {\n const { getModules } = await import('@open-mercato/shared/lib/i18n/server')\n loadedModules = getModules()\n } catch {}\n const subs = loadedModules.flatMap((m) =>\n (m.subscribers || []).map((subscriber: ModuleSubscriber) => ({\n ...subscriber,\n moduleId: subscriber.moduleId ?? m.id,\n })),\n )\n if (subs.length) (container.resolve as any)('eventBus').registerModuleSubscribers(subs)\n\n // Extract sync subscribers and register in the sync-subscriber-store\n const syncSubs = subs.filter((s: any) => s.sync === true)\n if (syncSubs.length) {\n try {\n const { registerSyncSubscribers } = await import('@open-mercato/shared/lib/crud/sync-subscriber-store')\n registerSyncSubscribers(\n syncSubs.map((s: any) => ({\n metadata: { event: s.event, sync: true as const, priority: s.priority, id: s.id },\n handler: s.handler,\n })),\n )\n } catch {\n // sync-subscriber-store may not be available\n }\n }\n } catch (err) {\n logger.error(\"Failed to register module subscribers:\", { err });\n }\n\n // KMS + tenant encryption\n const kmsService = createKmsService()\n container.register({ kmsService: asValue(kmsService) })\n try {\n const em = container.resolve('em') as EntityManager\n const cacheService = (() => {\n try { return container.resolve('cache') as any } catch { return null }\n })()\n const tenantEncryptionService = new TenantDataEncryptionService(em, { cache: cacheService, kms: kmsService })\n container.register({ tenantEncryptionService: asValue(tenantEncryptionService) })\n if (isTenantDataEncryptionEnabled() && kmsService.isHealthy()) {\n try {\n registerTenantEncryptionSubscriber(em, tenantEncryptionService)\n } catch (err) {\n logger.warn('Failed to register MikroORM encryption subscriber', { component: 'encryption', err })\n }\n } else if (isTenantDataEncryptionEnabled() && !kmsService.isHealthy()) {\n logger.warn('Vault/KMS unhealthy - tenant data encryption is disabled until recovery', { component: 'encryption' })\n }\n } catch (err) {\n logger.warn('Failed to initialize tenant encryption service', { component: 'encryption', err })\n }\n\n // Register rate limiter service (singleton via globalThis \u2014 reused across request containers)\n // getCachedRateLimiterService() never throws; returns null on failure\n const rateLimiterService = getCachedRateLimiterService()\n if (rateLimiterService) {\n container.register({ rateLimiterService: asValue(rateLimiterService) })\n }\n\n // Register search module\n try {\n // Get configs from global registry (registered during app bootstrap)\n const searchModuleConfigs = getSearchModuleConfigs()\n registerSearchModule(container as any, { moduleConfigs: searchModuleConfigs })\n\n // Register searchModuleConfigs in container so status API can access vector-enabled entities\n container.register({\n searchModuleConfigs: asValue(searchModuleConfigs),\n })\n\n // Register search delete event subscriber\n // Note: search.index_record is now handled by auto-discovered fulltext_upsert.ts subscriber\n try {\n const searchIndexer = container.resolve('searchIndexer') as any\n if (searchIndexer && eventBus) {\n eventBus.registerModuleSubscribers([\n {\n event: searchDeleteMetadata.event,\n persistent: searchDeleteMetadata.persistent,\n handler: createSearchDeleteSubscriber(searchIndexer),\n },\n ])\n }\n } catch {\n // searchIndexer may not be available\n }\n } catch (err) {\n logger.warn('Failed to register search module', { component: 'search', err })\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -51,7 +51,8 @@ async function runQueueDrainFromEnv() {
51
51
  jobLimit,
52
52
  queueBaseDir: process.env.QUEUE_BASE_DIR
53
53
  });
54
- console.log(JSON.stringify({ processed }));
54
+ process.stdout.write(`${JSON.stringify({ processed })}
55
+ `);
55
56
  }
56
57
  const currentFile = fileURLToPath(import.meta.url);
57
58
  const invokedFile = process.argv[1] ? path.resolve(process.argv[1]) : null;
@@ -59,7 +60,8 @@ if (invokedFile === currentFile) {
59
60
  runQueueDrainFromEnv().then(() => {
60
61
  process.exit(0);
61
62
  }).catch((error) => {
62
- console.error(error);
63
+ process.stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}
64
+ `);
63
65
  process.exit(1);
64
66
  });
65
67
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/helpers/integration/queue-runner.ts"],
4
- "sourcesContent": ["import path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { bootstrapFromAppRoot } from '@open-mercato/shared/lib/bootstrap/dynamicLoader'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { createQueue } from '@open-mercato/queue'\n\nexport type QueueDrainRunnerOptions = {\n appRoot: string\n jobLimit: number\n queueBaseDir?: string\n}\n\ntype BootstrapData = Awaited<ReturnType<typeof bootstrapFromAppRoot>>\n\nconst bootstrapCache = new Map<string, Promise<BootstrapData>>()\n\nfunction getBootstrapData(appRoot: string): Promise<BootstrapData> {\n const resolvedAppRoot = path.resolve(appRoot)\n const cached = bootstrapCache.get(resolvedAppRoot)\n if (cached) return cached\n const promise = bootstrapFromAppRoot(resolvedAppRoot)\n bootstrapCache.set(resolvedAppRoot, promise)\n return promise\n}\n\nexport async function drainQueueFromAppRoot(\n queueName: string,\n options: QueueDrainRunnerOptions,\n): Promise<number> {\n const data = await getBootstrapData(options.appRoot)\n const worker = data.modules\n .flatMap((module) => module.workers ?? [])\n .find((entry) => entry.queue === queueName)\n if (!worker) return 0\n\n const container = await createRequestContainer()\n const queue = createQueue(queueName, 'local', {\n baseDir: path.resolve(\n options.queueBaseDir?.trim()\n || process.env.QUEUE_BASE_DIR?.trim()\n || path.resolve(options.appRoot, '.mercato/queue'),\n ),\n concurrency: 1,\n })\n const resolve = <T = unknown>(name: string): T => container.resolve(name) as T\n\n try {\n let processedJobs = 0\n while (true) {\n const result = await queue.process(\n async (job, ctx) => {\n await Promise.resolve(worker.handler(job, { ...ctx, resolve }))\n },\n { limit: options.jobLimit },\n )\n const handled = result.processed + result.failed\n processedJobs += handled\n if (handled === 0) return processedJobs\n }\n } finally {\n await queue.close()\n }\n}\n\nexport async function runQueueDrainFromEnv(): Promise<void> {\n const queueName = process.env.OM_INTEGRATION_QUEUE_NAME?.trim()\n const appRoot = process.env.OM_INTEGRATION_APP_ROOT?.trim()\n const jobLimit = Number.parseInt(process.env.OM_INTEGRATION_QUEUE_JOB_LIMIT || '100', 10) || 100\n if (!queueName || !appRoot) throw new Error('Missing queue drain environment')\n\n const processed = await drainQueueFromAppRoot(queueName, {\n appRoot: path.resolve(appRoot),\n jobLimit,\n queueBaseDir: process.env.QUEUE_BASE_DIR,\n })\n console.log(JSON.stringify({ processed }))\n}\n\nconst currentFile = fileURLToPath(import.meta.url)\nconst invokedFile = process.argv[1] ? path.resolve(process.argv[1]) : null\n\nif (invokedFile === currentFile) {\n runQueueDrainFromEnv()\n .then(() => {\n process.exit(0)\n })\n .catch((error) => {\n console.error(error)\n process.exit(1)\n })\n}\n"],
5
- "mappings": "AAAA,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAC9B,SAAS,4BAA4B;AACrC,SAAS,8BAA8B;AACvC,SAAS,mBAAmB;AAU5B,MAAM,iBAAiB,oBAAI,IAAoC;AAE/D,SAAS,iBAAiB,SAAyC;AACjE,QAAM,kBAAkB,KAAK,QAAQ,OAAO;AAC5C,QAAM,SAAS,eAAe,IAAI,eAAe;AACjD,MAAI,OAAQ,QAAO;AACnB,QAAM,UAAU,qBAAqB,eAAe;AACpD,iBAAe,IAAI,iBAAiB,OAAO;AAC3C,SAAO;AACT;AAEA,eAAsB,sBACpB,WACA,SACiB;AACjB,QAAM,OAAO,MAAM,iBAAiB,QAAQ,OAAO;AACnD,QAAM,SAAS,KAAK,QACjB,QAAQ,CAAC,WAAW,OAAO,WAAW,CAAC,CAAC,EACxC,KAAK,CAAC,UAAU,MAAM,UAAU,SAAS;AAC5C,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,QAAQ,YAAY,WAAW,SAAS;AAAA,IAC5C,SAAS,KAAK;AAAA,MACZ,QAAQ,cAAc,KAAK,KACxB,QAAQ,IAAI,gBAAgB,KAAK,KACjC,KAAK,QAAQ,QAAQ,SAAS,gBAAgB;AAAA,IACnD;AAAA,IACA,aAAa;AAAA,EACf,CAAC;AACD,QAAM,UAAU,CAAc,SAAoB,UAAU,QAAQ,IAAI;AAExE,MAAI;AACF,QAAI,gBAAgB;AACpB,WAAO,MAAM;AACX,YAAM,SAAS,MAAM,MAAM;AAAA,QACzB,OAAO,KAAK,QAAQ;AAClB,gBAAM,QAAQ,QAAQ,OAAO,QAAQ,KAAK,EAAE,GAAG,KAAK,QAAQ,CAAC,CAAC;AAAA,QAChE;AAAA,QACA,EAAE,OAAO,QAAQ,SAAS;AAAA,MAC5B;AACA,YAAM,UAAU,OAAO,YAAY,OAAO;AAC1C,uBAAiB;AACjB,UAAI,YAAY,EAAG,QAAO;AAAA,IAC5B;AAAA,EACF,UAAE;AACA,UAAM,MAAM,MAAM;AAAA,EACpB;AACF;AAEA,eAAsB,uBAAsC;AAC1D,QAAM,YAAY,QAAQ,IAAI,2BAA2B,KAAK;AAC9D,QAAM,UAAU,QAAQ,IAAI,yBAAyB,KAAK;AAC1D,QAAM,WAAW,OAAO,SAAS,QAAQ,IAAI,kCAAkC,OAAO,EAAE,KAAK;AAC7F,MAAI,CAAC,aAAa,CAAC,QAAS,OAAM,IAAI,MAAM,iCAAiC;AAE7E,QAAM,YAAY,MAAM,sBAAsB,WAAW;AAAA,IACvD,SAAS,KAAK,QAAQ,OAAO;AAAA,IAC7B;AAAA,IACA,cAAc,QAAQ,IAAI;AAAA,EAC5B,CAAC;AACD,UAAQ,IAAI,KAAK,UAAU,EAAE,UAAU,CAAC,CAAC;AAC3C;AAEA,MAAM,cAAc,cAAc,YAAY,GAAG;AACjD,MAAM,cAAc,QAAQ,KAAK,CAAC,IAAI,KAAK,QAAQ,QAAQ,KAAK,CAAC,CAAC,IAAI;AAEtE,IAAI,gBAAgB,aAAa;AAC/B,uBAAqB,EAClB,KAAK,MAAM;AACV,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,YAAQ,MAAM,KAAK;AACnB,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACL;",
4
+ "sourcesContent": ["import path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { bootstrapFromAppRoot } from '@open-mercato/shared/lib/bootstrap/dynamicLoader'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { createQueue } from '@open-mercato/queue'\n\nexport type QueueDrainRunnerOptions = {\n appRoot: string\n jobLimit: number\n queueBaseDir?: string\n}\n\ntype BootstrapData = Awaited<ReturnType<typeof bootstrapFromAppRoot>>\n\nconst bootstrapCache = new Map<string, Promise<BootstrapData>>()\n\nfunction getBootstrapData(appRoot: string): Promise<BootstrapData> {\n const resolvedAppRoot = path.resolve(appRoot)\n const cached = bootstrapCache.get(resolvedAppRoot)\n if (cached) return cached\n const promise = bootstrapFromAppRoot(resolvedAppRoot)\n bootstrapCache.set(resolvedAppRoot, promise)\n return promise\n}\n\nexport async function drainQueueFromAppRoot(\n queueName: string,\n options: QueueDrainRunnerOptions,\n): Promise<number> {\n const data = await getBootstrapData(options.appRoot)\n const worker = data.modules\n .flatMap((module) => module.workers ?? [])\n .find((entry) => entry.queue === queueName)\n if (!worker) return 0\n\n const container = await createRequestContainer()\n const queue = createQueue(queueName, 'local', {\n baseDir: path.resolve(\n options.queueBaseDir?.trim()\n || process.env.QUEUE_BASE_DIR?.trim()\n || path.resolve(options.appRoot, '.mercato/queue'),\n ),\n concurrency: 1,\n })\n const resolve = <T = unknown>(name: string): T => container.resolve(name) as T\n\n try {\n let processedJobs = 0\n while (true) {\n const result = await queue.process(\n async (job, ctx) => {\n await Promise.resolve(worker.handler(job, { ...ctx, resolve }))\n },\n { limit: options.jobLimit },\n )\n const handled = result.processed + result.failed\n processedJobs += handled\n if (handled === 0) return processedJobs\n }\n } finally {\n await queue.close()\n }\n}\n\nexport async function runQueueDrainFromEnv(): Promise<void> {\n const queueName = process.env.OM_INTEGRATION_QUEUE_NAME?.trim()\n const appRoot = process.env.OM_INTEGRATION_APP_ROOT?.trim()\n const jobLimit = Number.parseInt(process.env.OM_INTEGRATION_QUEUE_JOB_LIMIT || '100', 10) || 100\n if (!queueName || !appRoot) throw new Error('Missing queue drain environment')\n\n const processed = await drainQueueFromAppRoot(queueName, {\n appRoot: path.resolve(appRoot),\n jobLimit,\n queueBaseDir: process.env.QUEUE_BASE_DIR,\n })\n process.stdout.write(`${JSON.stringify({ processed })}\\n`)\n}\n\nconst currentFile = fileURLToPath(import.meta.url)\nconst invokedFile = process.argv[1] ? path.resolve(process.argv[1]) : null\n\nif (invokedFile === currentFile) {\n runQueueDrainFromEnv()\n .then(() => {\n process.exit(0)\n })\n .catch((error) => {\n process.stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}\\n`)\n process.exit(1)\n })\n}\n"],
5
+ "mappings": "AAAA,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAC9B,SAAS,4BAA4B;AACrC,SAAS,8BAA8B;AACvC,SAAS,mBAAmB;AAU5B,MAAM,iBAAiB,oBAAI,IAAoC;AAE/D,SAAS,iBAAiB,SAAyC;AACjE,QAAM,kBAAkB,KAAK,QAAQ,OAAO;AAC5C,QAAM,SAAS,eAAe,IAAI,eAAe;AACjD,MAAI,OAAQ,QAAO;AACnB,QAAM,UAAU,qBAAqB,eAAe;AACpD,iBAAe,IAAI,iBAAiB,OAAO;AAC3C,SAAO;AACT;AAEA,eAAsB,sBACpB,WACA,SACiB;AACjB,QAAM,OAAO,MAAM,iBAAiB,QAAQ,OAAO;AACnD,QAAM,SAAS,KAAK,QACjB,QAAQ,CAAC,WAAW,OAAO,WAAW,CAAC,CAAC,EACxC,KAAK,CAAC,UAAU,MAAM,UAAU,SAAS;AAC5C,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,QAAQ,YAAY,WAAW,SAAS;AAAA,IAC5C,SAAS,KAAK;AAAA,MACZ,QAAQ,cAAc,KAAK,KACxB,QAAQ,IAAI,gBAAgB,KAAK,KACjC,KAAK,QAAQ,QAAQ,SAAS,gBAAgB;AAAA,IACnD;AAAA,IACA,aAAa;AAAA,EACf,CAAC;AACD,QAAM,UAAU,CAAc,SAAoB,UAAU,QAAQ,IAAI;AAExE,MAAI;AACF,QAAI,gBAAgB;AACpB,WAAO,MAAM;AACX,YAAM,SAAS,MAAM,MAAM;AAAA,QACzB,OAAO,KAAK,QAAQ;AAClB,gBAAM,QAAQ,QAAQ,OAAO,QAAQ,KAAK,EAAE,GAAG,KAAK,QAAQ,CAAC,CAAC;AAAA,QAChE;AAAA,QACA,EAAE,OAAO,QAAQ,SAAS;AAAA,MAC5B;AACA,YAAM,UAAU,OAAO,YAAY,OAAO;AAC1C,uBAAiB;AACjB,UAAI,YAAY,EAAG,QAAO;AAAA,IAC5B;AAAA,EACF,UAAE;AACA,UAAM,MAAM,MAAM;AAAA,EACpB;AACF;AAEA,eAAsB,uBAAsC;AAC1D,QAAM,YAAY,QAAQ,IAAI,2BAA2B,KAAK;AAC9D,QAAM,UAAU,QAAQ,IAAI,yBAAyB,KAAK;AAC1D,QAAM,WAAW,OAAO,SAAS,QAAQ,IAAI,kCAAkC,OAAO,EAAE,KAAK;AAC7F,MAAI,CAAC,aAAa,CAAC,QAAS,OAAM,IAAI,MAAM,iCAAiC;AAE7E,QAAM,YAAY,MAAM,sBAAsB,WAAW;AAAA,IACvD,SAAS,KAAK,QAAQ,OAAO;AAAA,IAC7B;AAAA,IACA,cAAc,QAAQ,IAAI;AAAA,EAC5B,CAAC;AACD,UAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,EAAE,UAAU,CAAC,CAAC;AAAA,CAAI;AAC3D;AAEA,MAAM,cAAc,cAAc,YAAY,GAAG;AACjD,MAAM,cAAc,QAAQ,KAAK,CAAC,IAAI,KAAK,QAAQ,QAAQ,KAAK,CAAC,CAAC,IAAI;AAEtE,IAAI,gBAAgB,aAAa;AAC/B,uBAAqB,EAClB,KAAK,MAAM;AACV,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,YAAQ,OAAO,MAAM,GAAG,iBAAiB,QAAQ,MAAM,SAAS,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,CAAI;AACjG,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACL;",
6
6
  "names": []
7
7
  }
@@ -5,6 +5,8 @@ import { createKmsService } from "@open-mercato/shared/lib/encryption/kms";
5
5
  import { encryptWithAesGcm, decryptWithAesGcm } from "@open-mercato/shared/lib/encryption/aes";
6
6
  import { getSharedApiKeyAuthCache } from "@open-mercato/shared/lib/auth/apiKeyAuthCache";
7
7
  import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
8
+ import { createLogger } from "@open-mercato/shared/lib/logger";
9
+ const logger = createLogger("api_keys").child({ component: "api-key-service" });
8
10
  const BCRYPT_COST = 10;
9
11
  async function encryptSessionSecret(secret, tenantId) {
10
12
  if (!tenantId) return null;
@@ -151,12 +153,12 @@ async function findSessionApiKeyWithSecret(em, sessionToken) {
151
153
  const record = await findApiKeyBySessionToken(em, sessionToken);
152
154
  if (!record) return null;
153
155
  if (!record.sessionSecretEncrypted) {
154
- console.warn("[ApiKeyService] Session key has no encrypted secret:", sessionToken.slice(0, 12));
156
+ logger.warn("Session key has no encrypted secret", { apiKeyId: record.id });
155
157
  return null;
156
158
  }
157
159
  const secret = await decryptSessionSecret(record.sessionSecretEncrypted, record.tenantId ?? null);
158
160
  if (!secret) {
159
- console.warn("[ApiKeyService] Failed to decrypt session secret:", sessionToken.slice(0, 12));
161
+ logger.warn("Failed to decrypt session secret", { apiKeyId: record.id });
160
162
  return null;
161
163
  }
162
164
  return { key: record, secret };
@@ -187,7 +189,7 @@ async function withOnetimeApiKey(em, input, fn) {
187
189
  await em.persist(record).flush();
188
190
  getSharedApiKeyAuthCache().invalidateByKeyId(record.id);
189
191
  } catch (error) {
190
- console.error("[withOnetimeApiKey] Failed to soft-delete one-time API key:", error);
192
+ logger.error("Failed to soft-delete one-time API key", { err: error });
191
193
  }
192
194
  }
193
195
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/api_keys/services/apiKeyService.ts"],
4
- "sourcesContent": ["import { randomBytes } from 'node:crypto'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { hash, compare } from 'bcryptjs'\nimport type { RbacService } from '@open-mercato/core/modules/auth/services/rbacService'\nimport { Role } from '@open-mercato/core/modules/auth/data/entities'\nimport { ApiKey } from '../data/entities'\nimport { createKmsService } from '@open-mercato/shared/lib/encryption/kms'\nimport { encryptWithAesGcm, decryptWithAesGcm } from '@open-mercato/shared/lib/encryption/aes'\nimport { getSharedApiKeyAuthCache } from '@open-mercato/shared/lib/auth/apiKeyAuthCache'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\n\nconst BCRYPT_COST = 10\n\n// =============================================================================\n// Session Secret Encryption Helpers\n// =============================================================================\n\n/**\n * Encrypt an API key secret for storage.\n * Uses tenant-specific DEK if available, otherwise returns null.\n */\nasync function encryptSessionSecret(\n secret: string,\n tenantId: string | null\n): Promise<string | null> {\n if (!tenantId) return null\n\n const kms = createKmsService()\n if (!kms.isHealthy()) return null\n\n const dek = await kms.getTenantDek(tenantId)\n if (!dek) {\n // Try to create a DEK if one doesn't exist\n const created = await kms.createTenantDek(tenantId)\n if (!created) return null\n const encrypted = encryptWithAesGcm(secret, created.key)\n return encrypted.value\n }\n\n const encrypted = encryptWithAesGcm(secret, dek.key)\n return encrypted.value\n}\n\n/**\n * Decrypt an API key secret from storage.\n * Returns null if decryption fails or no DEK available.\n */\nasync function decryptSessionSecret(\n encrypted: string,\n tenantId: string | null\n): Promise<string | null> {\n if (!tenantId || !encrypted) return null\n\n const kms = createKmsService()\n if (!kms.isHealthy()) return null\n\n const dek = await kms.getTenantDek(tenantId)\n if (!dek) return null\n\n return decryptWithAesGcm(encrypted, dek.key)\n}\n\nexport type CreateApiKeyInput = {\n name: string\n description?: string | null\n tenantId?: string | null\n organizationId?: string | null\n roles?: string[]\n expiresAt?: Date | null\n createdBy?: string | null\n}\n\nexport type ApiKeyWithSecret = {\n record: ApiKey\n secret: string\n}\n\nexport function generateApiKeySecret(): { secret: string; prefix: string } {\n const short = randomBytes(4).toString('hex')\n const body = randomBytes(24).toString('hex')\n const secret = `omk_${short}.${body}`\n const prefix = secret.slice(0, 12)\n return { secret, prefix }\n}\n\nexport async function hashApiKey(secret: string): Promise<string> {\n return hash(secret, BCRYPT_COST)\n}\n\nexport async function verifyApiKey(secret: string, keyHash: string): Promise<boolean> {\n return compare(secret, keyHash)\n}\n\nexport async function createApiKey(\n em: EntityManager,\n input: CreateApiKeyInput,\n opts: { rbac?: RbacService } = {},\n): Promise<ApiKeyWithSecret> {\n const { secret, prefix } = generateApiKeySecret()\n const keyHash = await hashApiKey(secret)\n const record = em.create(ApiKey, {\n name: input.name,\n description: input.description ?? null,\n tenantId: input.tenantId ?? null,\n organizationId: input.organizationId ?? null,\n keyHash,\n keyPrefix: prefix,\n rolesJson: Array.isArray(input.roles) ? input.roles : [],\n createdBy: input.createdBy ?? null,\n expiresAt: input.expiresAt ?? null,\n createdAt: new Date(),\n })\n await em.persist(record).flush()\n if (opts.rbac) {\n await opts.rbac.invalidateUserCache(`api_key:${record.id}`)\n }\n return { record, secret }\n}\n\nexport async function deleteApiKey(\n em: EntityManager,\n id: string,\n opts: { rbac?: RbacService } = {},\n): Promise<void> {\n const record = await em.findOne(ApiKey, { id })\n if (!record) return\n record.deletedAt = new Date()\n await em.persist(record).flush()\n getSharedApiKeyAuthCache().invalidateByKeyId(record.id)\n if (opts.rbac) {\n await opts.rbac.invalidateUserCache(`api_key:${record.id}`)\n }\n}\n\nexport async function findApiKeyBySecret(em: EntityManager, secret: string): Promise<ApiKey | null> {\n if (!secret) return null\n // Extract prefix from the secret for fast candidate lookup\n const prefix = secret.slice(0, 12)\n // Find candidates by prefix (fast index lookup)\n const candidates = await em.find(ApiKey, { keyPrefix: prefix, deletedAt: null })\n // Verify each candidate with bcrypt until we find a match\n for (const candidate of candidates) {\n if (candidate.expiresAt && candidate.expiresAt.getTime() < Date.now()) continue\n const isValid = await verifyApiKey(secret, candidate.keyHash)\n if (isValid) return candidate\n }\n return null\n}\n\n// =============================================================================\n// Session-scoped API Keys (for AI Chat ephemeral authorization)\n// =============================================================================\n\nexport type CreateSessionApiKeyInput = {\n sessionToken: string\n userId: string\n userRoles: string[]\n tenantId?: string | null\n organizationId?: string | null\n ttlMinutes?: number\n}\n\n/**\n * Generate a unique session token for ephemeral API keys.\n * Format: sess_{32 hex chars}\n */\nexport function generateSessionToken(): string {\n return `sess_${randomBytes(16).toString('hex')}`\n}\n\n/**\n * Create an ephemeral API key scoped to a chat session.\n * The key inherits the user's roles and expires after ttlMinutes (default 30).\n * The API key secret is encrypted and stored so it can be recovered for API calls.\n */\nexport async function createSessionApiKey(\n em: EntityManager,\n input: CreateSessionApiKeyInput\n): Promise<{ keyId: string; secret: string; sessionToken: string }> {\n const { secret, prefix } = generateApiKeySecret()\n const ttl = input.ttlMinutes ?? 30\n const expiresAt = new Date(Date.now() + ttl * 60 * 1000)\n const keyHash = await hashApiKey(secret)\n\n // Encrypt the secret for later retrieval (used by MCP server for API calls)\n const encryptedSecret = await encryptSessionSecret(secret, input.tenantId ?? null)\n\n const record = em.create(ApiKey, {\n name: `__session_${input.sessionToken}__`,\n description: 'Ephemeral session API key for AI chat',\n tenantId: input.tenantId ?? null,\n organizationId: input.organizationId ?? null,\n keyHash,\n keyPrefix: prefix,\n rolesJson: input.userRoles,\n createdBy: input.userId,\n sessionToken: input.sessionToken,\n sessionUserId: input.userId,\n sessionSecretEncrypted: encryptedSecret,\n expiresAt,\n createdAt: new Date(),\n })\n\n await em.persist(record).flush()\n\n return {\n keyId: record.id,\n secret,\n sessionToken: input.sessionToken,\n }\n}\n\n/**\n * Find an API key by its session token.\n * Returns null if not found, expired, or deleted.\n */\nexport async function findApiKeyBySessionToken(\n em: EntityManager,\n sessionToken: string\n): Promise<ApiKey | null> {\n if (!sessionToken) return null\n\n const record = await em.findOne(ApiKey, {\n sessionToken,\n deletedAt: null,\n })\n\n if (!record) return null\n if (record.expiresAt && record.expiresAt.getTime() < Date.now()) return null\n\n return record\n}\n\n/**\n * Bind an OpenCode session id to the api_key row that owns this chat session.\n *\n * Called by the chat dispatcher the first time we see the `done` event for a\n * freshly minted session token. From that point on,\n * `findApiKeyByOpencodeSessionId(em, opencodeSessionId)` returns the same row,\n * which the ai-assistant runtime uses to assert ownership on every resume.\n *\n * Throws when the session token has been deleted/expired, and when the api_key\n * row is already bound to a DIFFERENT OpenCode session (defensive: this should\n * never happen in practice because each chat mints a new session token, but we\n * fail closed instead of silently overwriting).\n *\n * Idempotent when the row is already bound to the same OpenCode session id.\n */\nexport async function bindOpencodeSessionToApiKey(\n em: EntityManager,\n sessionToken: string,\n opencodeSessionId: string\n): Promise<void> {\n if (!sessionToken) throw new Error('Session token not found or expired')\n if (!opencodeSessionId) throw new Error('OpenCode session id is required')\n\n const row = await findApiKeyBySessionToken(em, sessionToken)\n if (!row) throw new Error('Session token not found or expired')\n\n if (row.opencodeSessionId === opencodeSessionId) return\n if (row.opencodeSessionId && row.opencodeSessionId !== opencodeSessionId) {\n throw new Error('Session token already bound to a different OpenCode session')\n }\n\n row.opencodeSessionId = opencodeSessionId\n await em.persist(row).flush()\n}\n\n/**\n * Find an api_key row by its bound OpenCode session id.\n *\n * Returns null if no active row matches, or if the matched row is expired\n * (same contract as `findApiKeyBySessionToken`). Uses\n * `findOneWithDecryption` so encrypted-at-rest fields on the row are decrypted\n * before the ai-assistant runtime inspects `sessionUserId` / `tenantId` /\n * `organizationId` for the ownership check.\n */\nexport async function findApiKeyByOpencodeSessionId(\n em: EntityManager,\n opencodeSessionId: string\n): Promise<ApiKey | null> {\n if (!opencodeSessionId) return null\n\n const record = await findOneWithDecryption(\n em,\n ApiKey,\n { opencodeSessionId, deletedAt: null } as any,\n )\n\n if (!record) return null\n if (record.expiresAt && record.expiresAt.getTime() < Date.now()) return null\n\n return record\n}\n\n/**\n * Find a session API key with its decrypted secret.\n * Returns null if not found, expired, deleted, or decryption fails.\n * This is used by the MCP server to recover the API key secret for making\n * authenticated API calls on behalf of the user.\n */\nexport async function findSessionApiKeyWithSecret(\n em: EntityManager,\n sessionToken: string\n): Promise<{ key: ApiKey; secret: string } | null> {\n const record = await findApiKeyBySessionToken(em, sessionToken)\n if (!record) return null\n\n // If no encrypted secret stored, cannot recover\n if (!record.sessionSecretEncrypted) {\n console.warn('[ApiKeyService] Session key has no encrypted secret:', sessionToken.slice(0, 12))\n return null\n }\n\n // Decrypt the secret\n const secret = await decryptSessionSecret(record.sessionSecretEncrypted, record.tenantId ?? null)\n if (!secret) {\n console.warn('[ApiKeyService] Failed to decrypt session secret:', sessionToken.slice(0, 12))\n return null\n }\n\n return { key: record, secret }\n}\n\n/**\n * Delete an ephemeral API key by its session token.\n */\nexport async function deleteSessionApiKey(\n em: EntityManager,\n sessionToken: string\n): Promise<void> {\n const record = await em.findOne(ApiKey, { sessionToken, deletedAt: null })\n if (!record) return\n\n record.deletedAt = new Date()\n await em.persist(record).flush()\n getSharedApiKeyAuthCache().invalidateByKeyId(record.id)\n}\n\n/**\n * Execute a function with a one-time API key\n *\n * Creates a temporary API key, executes the function, and deletes the key.\n * Perfect for workflow activities that need authenticated access without\n * storing long-lived credentials.\n *\n * @param em - Entity manager\n * @param input - API key configuration\n * @param fn - Function to execute with the API key secret\n * @returns Result of the function\n */\nconst ONETIME_KEY_MAX_TTL_MS = 5 * 60 * 1000\n\nexport async function withOnetimeApiKey<T>(\n em: EntityManager,\n input: CreateApiKeyInput,\n fn: (secret: string) => Promise<T>\n): Promise<T> {\n const maxExpiresAt = new Date(Date.now() + ONETIME_KEY_MAX_TTL_MS)\n const safeExpiresAt = input.expiresAt && input.expiresAt < maxExpiresAt\n ? input.expiresAt\n : maxExpiresAt\n\n const { record, secret } = await createApiKey(em, {\n ...input,\n name: input.name || '__onetime__',\n description: input.description || 'One-time API key',\n expiresAt: safeExpiresAt,\n })\n\n try {\n const result = await fn(secret)\n return result\n } finally {\n try {\n record.deletedAt = new Date()\n await em.persist(record).flush()\n getSharedApiKeyAuthCache().invalidateByKeyId(record.id)\n } catch (error) {\n console.error('[withOnetimeApiKey] Failed to soft-delete one-time API key:', error)\n }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { randomBytes } from 'node:crypto'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { hash, compare } from 'bcryptjs'\nimport type { RbacService } from '@open-mercato/core/modules/auth/services/rbacService'\nimport { Role } from '@open-mercato/core/modules/auth/data/entities'\nimport { ApiKey } from '../data/entities'\nimport { createKmsService } from '@open-mercato/shared/lib/encryption/kms'\nimport { encryptWithAesGcm, decryptWithAesGcm } from '@open-mercato/shared/lib/encryption/aes'\nimport { getSharedApiKeyAuthCache } from '@open-mercato/shared/lib/auth/apiKeyAuthCache'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('api_keys').child({ component: 'api-key-service' })\n\nconst BCRYPT_COST = 10\n\n// =============================================================================\n// Session Secret Encryption Helpers\n// =============================================================================\n\n/**\n * Encrypt an API key secret for storage.\n * Uses tenant-specific DEK if available, otherwise returns null.\n */\nasync function encryptSessionSecret(\n secret: string,\n tenantId: string | null\n): Promise<string | null> {\n if (!tenantId) return null\n\n const kms = createKmsService()\n if (!kms.isHealthy()) return null\n\n const dek = await kms.getTenantDek(tenantId)\n if (!dek) {\n // Try to create a DEK if one doesn't exist\n const created = await kms.createTenantDek(tenantId)\n if (!created) return null\n const encrypted = encryptWithAesGcm(secret, created.key)\n return encrypted.value\n }\n\n const encrypted = encryptWithAesGcm(secret, dek.key)\n return encrypted.value\n}\n\n/**\n * Decrypt an API key secret from storage.\n * Returns null if decryption fails or no DEK available.\n */\nasync function decryptSessionSecret(\n encrypted: string,\n tenantId: string | null\n): Promise<string | null> {\n if (!tenantId || !encrypted) return null\n\n const kms = createKmsService()\n if (!kms.isHealthy()) return null\n\n const dek = await kms.getTenantDek(tenantId)\n if (!dek) return null\n\n return decryptWithAesGcm(encrypted, dek.key)\n}\n\nexport type CreateApiKeyInput = {\n name: string\n description?: string | null\n tenantId?: string | null\n organizationId?: string | null\n roles?: string[]\n expiresAt?: Date | null\n createdBy?: string | null\n}\n\nexport type ApiKeyWithSecret = {\n record: ApiKey\n secret: string\n}\n\nexport function generateApiKeySecret(): { secret: string; prefix: string } {\n const short = randomBytes(4).toString('hex')\n const body = randomBytes(24).toString('hex')\n const secret = `omk_${short}.${body}`\n const prefix = secret.slice(0, 12)\n return { secret, prefix }\n}\n\nexport async function hashApiKey(secret: string): Promise<string> {\n return hash(secret, BCRYPT_COST)\n}\n\nexport async function verifyApiKey(secret: string, keyHash: string): Promise<boolean> {\n return compare(secret, keyHash)\n}\n\nexport async function createApiKey(\n em: EntityManager,\n input: CreateApiKeyInput,\n opts: { rbac?: RbacService } = {},\n): Promise<ApiKeyWithSecret> {\n const { secret, prefix } = generateApiKeySecret()\n const keyHash = await hashApiKey(secret)\n const record = em.create(ApiKey, {\n name: input.name,\n description: input.description ?? null,\n tenantId: input.tenantId ?? null,\n organizationId: input.organizationId ?? null,\n keyHash,\n keyPrefix: prefix,\n rolesJson: Array.isArray(input.roles) ? input.roles : [],\n createdBy: input.createdBy ?? null,\n expiresAt: input.expiresAt ?? null,\n createdAt: new Date(),\n })\n await em.persist(record).flush()\n if (opts.rbac) {\n await opts.rbac.invalidateUserCache(`api_key:${record.id}`)\n }\n return { record, secret }\n}\n\nexport async function deleteApiKey(\n em: EntityManager,\n id: string,\n opts: { rbac?: RbacService } = {},\n): Promise<void> {\n const record = await em.findOne(ApiKey, { id })\n if (!record) return\n record.deletedAt = new Date()\n await em.persist(record).flush()\n getSharedApiKeyAuthCache().invalidateByKeyId(record.id)\n if (opts.rbac) {\n await opts.rbac.invalidateUserCache(`api_key:${record.id}`)\n }\n}\n\nexport async function findApiKeyBySecret(em: EntityManager, secret: string): Promise<ApiKey | null> {\n if (!secret) return null\n // Extract prefix from the secret for fast candidate lookup\n const prefix = secret.slice(0, 12)\n // Find candidates by prefix (fast index lookup)\n const candidates = await em.find(ApiKey, { keyPrefix: prefix, deletedAt: null })\n // Verify each candidate with bcrypt until we find a match\n for (const candidate of candidates) {\n if (candidate.expiresAt && candidate.expiresAt.getTime() < Date.now()) continue\n const isValid = await verifyApiKey(secret, candidate.keyHash)\n if (isValid) return candidate\n }\n return null\n}\n\n// =============================================================================\n// Session-scoped API Keys (for AI Chat ephemeral authorization)\n// =============================================================================\n\nexport type CreateSessionApiKeyInput = {\n sessionToken: string\n userId: string\n userRoles: string[]\n tenantId?: string | null\n organizationId?: string | null\n ttlMinutes?: number\n}\n\n/**\n * Generate a unique session token for ephemeral API keys.\n * Format: sess_{32 hex chars}\n */\nexport function generateSessionToken(): string {\n return `sess_${randomBytes(16).toString('hex')}`\n}\n\n/**\n * Create an ephemeral API key scoped to a chat session.\n * The key inherits the user's roles and expires after ttlMinutes (default 30).\n * The API key secret is encrypted and stored so it can be recovered for API calls.\n */\nexport async function createSessionApiKey(\n em: EntityManager,\n input: CreateSessionApiKeyInput\n): Promise<{ keyId: string; secret: string; sessionToken: string }> {\n const { secret, prefix } = generateApiKeySecret()\n const ttl = input.ttlMinutes ?? 30\n const expiresAt = new Date(Date.now() + ttl * 60 * 1000)\n const keyHash = await hashApiKey(secret)\n\n // Encrypt the secret for later retrieval (used by MCP server for API calls)\n const encryptedSecret = await encryptSessionSecret(secret, input.tenantId ?? null)\n\n const record = em.create(ApiKey, {\n name: `__session_${input.sessionToken}__`,\n description: 'Ephemeral session API key for AI chat',\n tenantId: input.tenantId ?? null,\n organizationId: input.organizationId ?? null,\n keyHash,\n keyPrefix: prefix,\n rolesJson: input.userRoles,\n createdBy: input.userId,\n sessionToken: input.sessionToken,\n sessionUserId: input.userId,\n sessionSecretEncrypted: encryptedSecret,\n expiresAt,\n createdAt: new Date(),\n })\n\n await em.persist(record).flush()\n\n return {\n keyId: record.id,\n secret,\n sessionToken: input.sessionToken,\n }\n}\n\n/**\n * Find an API key by its session token.\n * Returns null if not found, expired, or deleted.\n */\nexport async function findApiKeyBySessionToken(\n em: EntityManager,\n sessionToken: string\n): Promise<ApiKey | null> {\n if (!sessionToken) return null\n\n const record = await em.findOne(ApiKey, {\n sessionToken,\n deletedAt: null,\n })\n\n if (!record) return null\n if (record.expiresAt && record.expiresAt.getTime() < Date.now()) return null\n\n return record\n}\n\n/**\n * Bind an OpenCode session id to the api_key row that owns this chat session.\n *\n * Called by the chat dispatcher the first time we see the `done` event for a\n * freshly minted session token. From that point on,\n * `findApiKeyByOpencodeSessionId(em, opencodeSessionId)` returns the same row,\n * which the ai-assistant runtime uses to assert ownership on every resume.\n *\n * Throws when the session token has been deleted/expired, and when the api_key\n * row is already bound to a DIFFERENT OpenCode session (defensive: this should\n * never happen in practice because each chat mints a new session token, but we\n * fail closed instead of silently overwriting).\n *\n * Idempotent when the row is already bound to the same OpenCode session id.\n */\nexport async function bindOpencodeSessionToApiKey(\n em: EntityManager,\n sessionToken: string,\n opencodeSessionId: string\n): Promise<void> {\n if (!sessionToken) throw new Error('Session token not found or expired')\n if (!opencodeSessionId) throw new Error('OpenCode session id is required')\n\n const row = await findApiKeyBySessionToken(em, sessionToken)\n if (!row) throw new Error('Session token not found or expired')\n\n if (row.opencodeSessionId === opencodeSessionId) return\n if (row.opencodeSessionId && row.opencodeSessionId !== opencodeSessionId) {\n throw new Error('Session token already bound to a different OpenCode session')\n }\n\n row.opencodeSessionId = opencodeSessionId\n await em.persist(row).flush()\n}\n\n/**\n * Find an api_key row by its bound OpenCode session id.\n *\n * Returns null if no active row matches, or if the matched row is expired\n * (same contract as `findApiKeyBySessionToken`). Uses\n * `findOneWithDecryption` so encrypted-at-rest fields on the row are decrypted\n * before the ai-assistant runtime inspects `sessionUserId` / `tenantId` /\n * `organizationId` for the ownership check.\n */\nexport async function findApiKeyByOpencodeSessionId(\n em: EntityManager,\n opencodeSessionId: string\n): Promise<ApiKey | null> {\n if (!opencodeSessionId) return null\n\n const record = await findOneWithDecryption(\n em,\n ApiKey,\n { opencodeSessionId, deletedAt: null } as any,\n )\n\n if (!record) return null\n if (record.expiresAt && record.expiresAt.getTime() < Date.now()) return null\n\n return record\n}\n\n/**\n * Find a session API key with its decrypted secret.\n * Returns null if not found, expired, deleted, or decryption fails.\n * This is used by the MCP server to recover the API key secret for making\n * authenticated API calls on behalf of the user.\n */\nexport async function findSessionApiKeyWithSecret(\n em: EntityManager,\n sessionToken: string\n): Promise<{ key: ApiKey; secret: string } | null> {\n const record = await findApiKeyBySessionToken(em, sessionToken)\n if (!record) return null\n\n // If no encrypted secret stored, cannot recover\n if (!record.sessionSecretEncrypted) {\n logger.warn('Session key has no encrypted secret', { apiKeyId: record.id })\n return null\n }\n\n // Decrypt the secret\n const secret = await decryptSessionSecret(record.sessionSecretEncrypted, record.tenantId ?? null)\n if (!secret) {\n logger.warn('Failed to decrypt session secret', { apiKeyId: record.id })\n return null\n }\n\n return { key: record, secret }\n}\n\n/**\n * Delete an ephemeral API key by its session token.\n */\nexport async function deleteSessionApiKey(\n em: EntityManager,\n sessionToken: string\n): Promise<void> {\n const record = await em.findOne(ApiKey, { sessionToken, deletedAt: null })\n if (!record) return\n\n record.deletedAt = new Date()\n await em.persist(record).flush()\n getSharedApiKeyAuthCache().invalidateByKeyId(record.id)\n}\n\n/**\n * Execute a function with a one-time API key\n *\n * Creates a temporary API key, executes the function, and deletes the key.\n * Perfect for workflow activities that need authenticated access without\n * storing long-lived credentials.\n *\n * @param em - Entity manager\n * @param input - API key configuration\n * @param fn - Function to execute with the API key secret\n * @returns Result of the function\n */\nconst ONETIME_KEY_MAX_TTL_MS = 5 * 60 * 1000\n\nexport async function withOnetimeApiKey<T>(\n em: EntityManager,\n input: CreateApiKeyInput,\n fn: (secret: string) => Promise<T>\n): Promise<T> {\n const maxExpiresAt = new Date(Date.now() + ONETIME_KEY_MAX_TTL_MS)\n const safeExpiresAt = input.expiresAt && input.expiresAt < maxExpiresAt\n ? input.expiresAt\n : maxExpiresAt\n\n const { record, secret } = await createApiKey(em, {\n ...input,\n name: input.name || '__onetime__',\n description: input.description || 'One-time API key',\n expiresAt: safeExpiresAt,\n })\n\n try {\n const result = await fn(secret)\n return result\n } finally {\n try {\n record.deletedAt = new Date()\n await em.persist(record).flush()\n getSharedApiKeyAuthCache().invalidateByKeyId(record.id)\n } catch (error) {\n logger.error('Failed to soft-delete one-time API key', { err: error })\n }\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["encrypted"]
7
7
  }
@@ -18,6 +18,8 @@ import {
18
18
  validateImageMagicBytes
19
19
  } from "@open-mercato/core/modules/attachments/lib/imageSafety";
20
20
  import { StorageDriverFactory } from "../../../../lib/drivers/index.js";
21
+ import { createLogger } from "@open-mercato/shared/lib/logger";
22
+ const logger = createLogger("attachments").child({ component: "image" });
21
23
  const querySchema = z.object({
22
24
  width: z.coerce.number().int().min(1).max(4e3).optional(),
23
25
  height: z.coerce.number().int().min(1).max(4e3).optional(),
@@ -101,7 +103,7 @@ async function GET(req, context) {
101
103
  buffer = await transformer.toBuffer();
102
104
  if (cacheKey) {
103
105
  void writeThumbnailCache(attachment.partitionCode, attachment.id, cacheKey, buffer).catch((cacheError) => {
104
- console.error("attachments.image.cache.write failed", cacheError);
106
+ logger.error("Thumbnail cache write failed", { err: cacheError });
105
107
  });
106
108
  }
107
109
  }
@@ -117,7 +119,7 @@ async function GET(req, context) {
117
119
  }
118
120
  });
119
121
  } catch (error) {
120
- console.error("attachments.image.read failed", error);
122
+ logger.error("Image read failed", { err: error });
121
123
  return NextResponse.json({ error: "Failed to render image" }, { status: 500 });
122
124
  }
123
125
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../../src/modules/attachments/api/image/%5Bid%5D/%5B%5B...slug%5D%5D/route.ts"],
4
- "sourcesContent": ["import { NextRequest, NextResponse } from 'next/server'\nimport sharp from 'sharp'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { Attachment, AttachmentPartition } from '@open-mercato/core/modules/attachments/data/entities'\nimport {\n buildThumbnailCacheKey,\n readThumbnailCache,\n writeThumbnailCache,\n} from '@open-mercato/core/modules/attachments/lib/thumbnailCache'\nimport { canRenderInlineAttachment } from '@open-mercato/core/modules/attachments/lib/security'\nimport { checkAttachmentAccess, isSuperAdminAuth } from '@open-mercato/core/modules/attachments/lib/access'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { attachmentsTag, imageQuerySchema, attachmentErrorSchema } from '../../../openapi'\nimport {\n MAX_IMAGE_SOURCE_PIXELS,\n validateImageDimensions,\n validateImageMagicBytes,\n} from '@open-mercato/core/modules/attachments/lib/imageSafety'\nimport { StorageDriverFactory } from '../../../../lib/drivers'\n\nconst querySchema = z.object({\n width: z.coerce.number().int().min(1).max(4000).optional(),\n height: z.coerce.number().int().min(1).max(4000).optional(),\n cropType: z.enum(['cover', 'contain']).optional(),\n})\n\nexport const metadata = {\n GET: { requireAuth: false },\n}\n\nexport async function GET(\n req: NextRequest,\n context: { params: Promise<{ id: string; slug?: string[] | undefined }> }\n) {\n const auth = await getAuthFromRequest(req)\n const { id } = await context.params\n if (!id) {\n return NextResponse.json({ error: 'Attachment id is required' }, { status: 400 })\n }\n const parsedQuery = querySchema.safeParse(\n Object.fromEntries(new URL(req.url).searchParams.entries())\n )\n if (!parsedQuery.success) {\n return NextResponse.json({ error: 'Invalid size parameters' }, { status: 400 })\n }\n const { width, height, cropType } = parsedQuery.data\n\n const { resolve } = await createRequestContainer()\n const em = resolve('em') as EntityManager\n const storageDriverFactory =\n (resolve('storageDriverFactory') as StorageDriverFactory | null) ?? new StorageDriverFactory(em)\n\n const findFilter: Record<string, unknown> = { id }\n if (auth && !isSuperAdminAuth(auth)) {\n if (auth.tenantId) findFilter.tenantId = auth.tenantId\n if (auth.orgId) findFilter.organizationId = auth.orgId\n }\n const attachment = await em.findOne(Attachment, findFilter)\n if (!attachment) {\n return NextResponse.json({ error: 'Not found' }, { status: 404 })\n }\n if (!canRenderInlineAttachment(attachment.mimeType)) {\n return NextResponse.json({ error: 'Unsupported media type' }, { status: 400 })\n }\n const partition = await em.findOne(AttachmentPartition, { code: attachment.partitionCode })\n if (!partition) {\n return NextResponse.json({ error: 'Partition misconfigured' }, { status: 500 })\n }\n const access = checkAttachmentAccess(auth, attachment, partition)\n if (!access.ok) {\n const message = access.status === 401 ? 'Unauthorized' : 'Forbidden'\n return NextResponse.json({ error: message }, { status: access.status })\n }\n\n const driver = await storageDriverFactory.resolveForPartition(attachment.partitionCode, {\n tenantId: attachment.tenantId ?? '',\n organizationId: attachment.organizationId ?? '',\n })\n const cacheKey = buildThumbnailCacheKey(width, height, cropType)\n try {\n let buffer: Buffer | null = null\n if (cacheKey) {\n buffer = await readThumbnailCache(attachment.partitionCode, attachment.id, cacheKey)\n }\n if (!buffer) {\n const { buffer: input } = await driver.read(attachment.partitionCode, attachment.storagePath)\n const magicBytesValidation = validateImageMagicBytes(input, attachment.mimeType)\n if (!magicBytesValidation.ok) {\n return NextResponse.json({ error: magicBytesValidation.error }, { status: magicBytesValidation.status })\n }\n\n const dimensionsValidation = await validateImageDimensions(input)\n if (!dimensionsValidation.ok) {\n return NextResponse.json({ error: dimensionsValidation.error }, { status: dimensionsValidation.status })\n }\n\n let transformer = sharp(input, {\n failOn: 'error',\n limitInputPixels: MAX_IMAGE_SOURCE_PIXELS,\n })\n if (width || height) {\n const resizeOptions: sharp.ResizeOptions = {\n width: width || undefined,\n height: height || undefined,\n fit: cropType === 'contain' ? 'contain' : 'cover',\n }\n if (cropType === 'contain') {\n resizeOptions.background = { r: 0, g: 0, b: 0, alpha: 0 }\n }\n transformer = transformer.resize(resizeOptions)\n }\n buffer = await transformer.toBuffer()\n if (cacheKey) {\n void writeThumbnailCache(attachment.partitionCode, attachment.id, cacheKey, buffer).catch((cacheError) => {\n console.error('attachments.image.cache.write failed', cacheError)\n })\n }\n }\n if (!buffer) {\n return NextResponse.json({ error: 'Failed to render image' }, { status: 500 })\n }\n const responseBody = new Uint8Array(buffer)\n\n return new NextResponse(responseBody, {\n headers: {\n 'Content-Type': attachment.mimeType || 'image/jpeg',\n 'Cache-Control': partition.isPublic ? 'public, max-age=3600' : 'private, max-age=60',\n 'X-Content-Type-Options': 'nosniff',\n },\n })\n } catch (error) {\n console.error('attachments.image.read failed', error)\n return NextResponse.json({ error: 'Failed to render image' }, { status: 500 })\n }\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: attachmentsTag,\n summary: 'Serve resized images',\n methods: {\n GET: {\n summary: 'Serve image with optional resizing',\n description: 'Returns an image attachment with optional on-the-fly resizing and cropping. Resized images are cached for performance. Only works with image MIME types. Path parameter: {id} - Attachment UUID. Query parameters: ?width=N (1-4000 pixels), ?height=N (1-4000 pixels), ?cropType=cover|contain (resize behavior).',\n responses: [\n {\n status: 200,\n description: 'Binary image content (Content-Type: image/jpeg, image/png, etc.)',\n schema: z.any().describe('Binary image content - actual Content-Type header set to image MIME type, not application/json'),\n },\n ],\n errors: [\n { status: 400, description: 'Invalid parameters, missing ID, or non-image attachment', schema: attachmentErrorSchema },\n { status: 401, description: 'Unauthorized - authentication required for private partitions', schema: attachmentErrorSchema },\n { status: 403, description: 'Forbidden - insufficient permissions', schema: attachmentErrorSchema },\n { status: 404, description: 'Image not found', schema: attachmentErrorSchema },\n { status: 500, description: 'Partition misconfigured or image rendering failed', schema: attachmentErrorSchema },\n ],\n },\n },\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { NextRequest, NextResponse } from 'next/server'\nimport sharp from 'sharp'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { Attachment, AttachmentPartition } from '@open-mercato/core/modules/attachments/data/entities'\nimport {\n buildThumbnailCacheKey,\n readThumbnailCache,\n writeThumbnailCache,\n} from '@open-mercato/core/modules/attachments/lib/thumbnailCache'\nimport { canRenderInlineAttachment } from '@open-mercato/core/modules/attachments/lib/security'\nimport { checkAttachmentAccess, isSuperAdminAuth } from '@open-mercato/core/modules/attachments/lib/access'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { attachmentsTag, imageQuerySchema, attachmentErrorSchema } from '../../../openapi'\nimport {\n MAX_IMAGE_SOURCE_PIXELS,\n validateImageDimensions,\n validateImageMagicBytes,\n} from '@open-mercato/core/modules/attachments/lib/imageSafety'\nimport { StorageDriverFactory } from '../../../../lib/drivers'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('attachments').child({ component: 'image' })\n\nconst querySchema = z.object({\n width: z.coerce.number().int().min(1).max(4000).optional(),\n height: z.coerce.number().int().min(1).max(4000).optional(),\n cropType: z.enum(['cover', 'contain']).optional(),\n})\n\nexport const metadata = {\n GET: { requireAuth: false },\n}\n\nexport async function GET(\n req: NextRequest,\n context: { params: Promise<{ id: string; slug?: string[] | undefined }> }\n) {\n const auth = await getAuthFromRequest(req)\n const { id } = await context.params\n if (!id) {\n return NextResponse.json({ error: 'Attachment id is required' }, { status: 400 })\n }\n const parsedQuery = querySchema.safeParse(\n Object.fromEntries(new URL(req.url).searchParams.entries())\n )\n if (!parsedQuery.success) {\n return NextResponse.json({ error: 'Invalid size parameters' }, { status: 400 })\n }\n const { width, height, cropType } = parsedQuery.data\n\n const { resolve } = await createRequestContainer()\n const em = resolve('em') as EntityManager\n const storageDriverFactory =\n (resolve('storageDriverFactory') as StorageDriverFactory | null) ?? new StorageDriverFactory(em)\n\n const findFilter: Record<string, unknown> = { id }\n if (auth && !isSuperAdminAuth(auth)) {\n if (auth.tenantId) findFilter.tenantId = auth.tenantId\n if (auth.orgId) findFilter.organizationId = auth.orgId\n }\n const attachment = await em.findOne(Attachment, findFilter)\n if (!attachment) {\n return NextResponse.json({ error: 'Not found' }, { status: 404 })\n }\n if (!canRenderInlineAttachment(attachment.mimeType)) {\n return NextResponse.json({ error: 'Unsupported media type' }, { status: 400 })\n }\n const partition = await em.findOne(AttachmentPartition, { code: attachment.partitionCode })\n if (!partition) {\n return NextResponse.json({ error: 'Partition misconfigured' }, { status: 500 })\n }\n const access = checkAttachmentAccess(auth, attachment, partition)\n if (!access.ok) {\n const message = access.status === 401 ? 'Unauthorized' : 'Forbidden'\n return NextResponse.json({ error: message }, { status: access.status })\n }\n\n const driver = await storageDriverFactory.resolveForPartition(attachment.partitionCode, {\n tenantId: attachment.tenantId ?? '',\n organizationId: attachment.organizationId ?? '',\n })\n const cacheKey = buildThumbnailCacheKey(width, height, cropType)\n try {\n let buffer: Buffer | null = null\n if (cacheKey) {\n buffer = await readThumbnailCache(attachment.partitionCode, attachment.id, cacheKey)\n }\n if (!buffer) {\n const { buffer: input } = await driver.read(attachment.partitionCode, attachment.storagePath)\n const magicBytesValidation = validateImageMagicBytes(input, attachment.mimeType)\n if (!magicBytesValidation.ok) {\n return NextResponse.json({ error: magicBytesValidation.error }, { status: magicBytesValidation.status })\n }\n\n const dimensionsValidation = await validateImageDimensions(input)\n if (!dimensionsValidation.ok) {\n return NextResponse.json({ error: dimensionsValidation.error }, { status: dimensionsValidation.status })\n }\n\n let transformer = sharp(input, {\n failOn: 'error',\n limitInputPixels: MAX_IMAGE_SOURCE_PIXELS,\n })\n if (width || height) {\n const resizeOptions: sharp.ResizeOptions = {\n width: width || undefined,\n height: height || undefined,\n fit: cropType === 'contain' ? 'contain' : 'cover',\n }\n if (cropType === 'contain') {\n resizeOptions.background = { r: 0, g: 0, b: 0, alpha: 0 }\n }\n transformer = transformer.resize(resizeOptions)\n }\n buffer = await transformer.toBuffer()\n if (cacheKey) {\n void writeThumbnailCache(attachment.partitionCode, attachment.id, cacheKey, buffer).catch((cacheError) => {\n logger.error('Thumbnail cache write failed', { err: cacheError })\n })\n }\n }\n if (!buffer) {\n return NextResponse.json({ error: 'Failed to render image' }, { status: 500 })\n }\n const responseBody = new Uint8Array(buffer)\n\n return new NextResponse(responseBody, {\n headers: {\n 'Content-Type': attachment.mimeType || 'image/jpeg',\n 'Cache-Control': partition.isPublic ? 'public, max-age=3600' : 'private, max-age=60',\n 'X-Content-Type-Options': 'nosniff',\n },\n })\n } catch (error) {\n logger.error('Image read failed', { err: error })\n return NextResponse.json({ error: 'Failed to render image' }, { status: 500 })\n }\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: attachmentsTag,\n summary: 'Serve resized images',\n methods: {\n GET: {\n summary: 'Serve image with optional resizing',\n description: 'Returns an image attachment with optional on-the-fly resizing and cropping. Resized images are cached for performance. Only works with image MIME types. Path parameter: {id} - Attachment UUID. Query parameters: ?width=N (1-4000 pixels), ?height=N (1-4000 pixels), ?cropType=cover|contain (resize behavior).',\n responses: [\n {\n status: 200,\n description: 'Binary image content (Content-Type: image/jpeg, image/png, etc.)',\n schema: z.any().describe('Binary image content - actual Content-Type header set to image MIME type, not application/json'),\n },\n ],\n errors: [\n { status: 400, description: 'Invalid parameters, missing ID, or non-image attachment', schema: attachmentErrorSchema },\n { status: 401, description: 'Unauthorized - authentication required for private partitions', schema: attachmentErrorSchema },\n { status: 403, description: 'Forbidden - insufficient permissions', schema: attachmentErrorSchema },\n { status: 404, description: 'Image not found', schema: attachmentErrorSchema },\n { status: 500, description: 'Partition misconfigured or image rendering failed', schema: attachmentErrorSchema },\n ],\n },\n },\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -20,6 +20,8 @@ import {
20
20
  attachmentDetailResponseSchema,
21
21
  attachmentErrorSchema
22
22
  } from "../../openapi.js";
23
+ import { createLogger } from "@open-mercato/shared/lib/logger";
24
+ const logger = createLogger("attachments").child({ component: "library" });
23
25
  const updateSchema = z.object({
24
26
  tags: z.array(z.string()).optional(),
25
27
  assignments: z.array(
@@ -161,7 +163,7 @@ async function PATCH(req, ctx) {
161
163
  }
162
164
  });
163
165
  } catch (error) {
164
- console.error("[attachments] failed to persist custom attributes", error);
166
+ logger.error("Failed to persist custom attributes", { err: error });
165
167
  return NextResponse.json({ error: "Failed to save attachment attributes." }, { status: 500 });
166
168
  }
167
169
  if (dataEngine) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/attachments/api/library/%5Bid%5D/route.ts"],
4
- "sourcesContent": ["import { NextRequest, NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { Attachment, AttachmentPartition } from '../../../data/entities'\nimport {\n mergeAttachmentMetadata,\n normalizeAttachmentAssignments,\n normalizeAttachmentTags,\n readAttachmentMetadata,\n} from '../../../lib/metadata'\nimport type { StorageDriverFactory } from '../../../lib/drivers'\nimport { splitCustomFieldPayload, loadCustomFieldValues } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { emitCrudSideEffects, setCustomFieldsIfAny } from '@open-mercato/shared/lib/commands/helpers'\nimport { normalizeCustomFieldResponse } from '@open-mercato/shared/lib/custom-fields/normalize'\nimport { E } from '#generated/entities.ids.generated'\nimport type { QueryEngine } from '@open-mercato/shared/lib/query/types'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { attachmentCrudEvents, attachmentCrudIndexer } from '../../../lib/crud'\nimport { applyAssignmentEnrichments, resolveAssignmentEnrichments } from '../../../lib/assignmentDetails'\nimport {\n attachmentsTag,\n attachmentDetailResponseSchema,\n attachmentErrorSchema,\n} from '../../openapi'\n\nconst updateSchema = z.object({\n tags: z.array(z.string()).optional(),\n assignments: z\n .array(\n z.object({\n type: z.string().min(1),\n id: z.string().min(1),\n href: z.string().nullable().optional(),\n label: z.string().nullable().optional(),\n }),\n )\n .optional(),\n})\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['attachments.view'] },\n PATCH: { requireAuth: true, requireFeatures: ['attachments.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['attachments.manage'] },\n}\n\ntype RouteParams = { id: string }\ntype RouteContext = { params: Promise<RouteParams> }\n\nasync function resolveAttachmentId(ctx: RouteContext): Promise<string | null> {\n const params = ctx?.params\n try {\n const { id } = await params\n if (typeof id === 'string' && id.trim().length) {\n return id\n }\n return null\n } catch {\n return null\n }\n}\n\nexport async function GET(req: NextRequest, ctx: RouteContext) {\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.tenantId || (!auth.orgId && !auth.isSuperAdmin)) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n const attachmentId = await resolveAttachmentId(ctx)\n if (!attachmentId) {\n return NextResponse.json({ error: 'Attachment id is required' }, { status: 400 })\n }\n const { resolve } = await createRequestContainer()\n const em = resolve('em') as EntityManager\n let queryEngine: QueryEngine | null = null\n try {\n queryEngine = resolve('queryEngine') as QueryEngine\n } catch {\n queryEngine = null\n }\n const findFilter: Record<string, unknown> = {\n id: attachmentId,\n tenantId: auth.tenantId,\n }\n if (auth.orgId) {\n findFilter.organizationId = auth.orgId\n }\n const record = await em.findOne(Attachment, findFilter)\n if (!record) {\n return NextResponse.json({ error: 'Attachment not found' }, { status: 404 })\n }\n const metadata = readAttachmentMetadata(record.storageMetadata)\n const partition = record.partitionCode\n ? await em.findOne(AttachmentPartition, { code: record.partitionCode })\n : null\n const customFieldValues = await loadCustomFieldValues({\n em,\n entityId: E.attachments.attachment,\n recordIds: [record.id],\n tenantIdByRecord: { [record.id]: record.tenantId ?? auth.tenantId ?? null },\n organizationIdByRecord: { [record.id]: record.organizationId ?? auth.orgId ?? null },\n tenantFallbacks: [auth.tenantId ?? null].filter((value): value is string => !!value),\n })\n const customFields = normalizeCustomFieldResponse(customFieldValues[record.id])\n const assignments = metadata.assignments ?? []\n const enrichments = await resolveAssignmentEnrichments(assignments, {\n queryEngine,\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n })\n const enrichedAssignments = applyAssignmentEnrichments(assignments, enrichments)\n return NextResponse.json({\n item: {\n id: record.id,\n fileName: record.fileName,\n fileSize: record.fileSize,\n mimeType: record.mimeType,\n partitionCode: record.partitionCode,\n partitionTitle: partition?.title ?? null,\n tags: metadata.tags ?? [],\n assignments: enrichedAssignments,\n content: record.content && record.content.trim() ? record.content : null,\n customFields,\n },\n })\n}\n\nexport async function PATCH(req: NextRequest, ctx: RouteContext) {\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n const attachmentId = await resolveAttachmentId(ctx)\n if (!attachmentId) {\n return NextResponse.json({ error: 'Attachment id is required' }, { status: 400 })\n }\n const rawBody = await req.json().catch(() => null)\n const { base, custom } = splitCustomFieldPayload(rawBody)\n const parsed = updateSchema.safeParse(base)\n if (!parsed.success) {\n return NextResponse.json({ error: 'Invalid payload' }, { status: 400 })\n }\n const { resolve } = await createRequestContainer()\n const em = resolve('em') as EntityManager\n let queryEngine: QueryEngine | null = null\n try {\n queryEngine = resolve('queryEngine') as QueryEngine\n } catch {\n queryEngine = null\n }\n const dataEngine = resolve('dataEngine') as DataEngine\n const patchFilter: Record<string, unknown> = {\n id: attachmentId,\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n }\n const record = await em.findOne(Attachment, patchFilter)\n if (!record) {\n return NextResponse.json({ error: 'Attachment not found' }, { status: 404 })\n }\n const patch: Record<string, unknown> = {}\n if (parsed.data.tags) patch.tags = normalizeAttachmentTags(parsed.data.tags)\n if (parsed.data.assignments) patch.assignments = normalizeAttachmentAssignments(parsed.data.assignments)\n record.storageMetadata = mergeAttachmentMetadata(record.storageMetadata, patch)\n // Commit the metadata mutation and the custom-field write atomically so a\n // custom-field failure cannot leave the attachment metadata partially updated.\n try {\n await em.transactional(async (tx) => {\n await tx.flush()\n if (dataEngine && custom && Object.keys(custom).length) {\n await setCustomFieldsIfAny({\n dataEngine,\n entityId: E.attachments.attachment,\n recordId: record.id,\n tenantId: record.tenantId ?? auth.tenantId ?? null,\n organizationId: record.organizationId ?? auth.orgId ?? null,\n values: custom,\n })\n }\n })\n } catch (error) {\n console.error('[attachments] failed to persist custom attributes', error)\n return NextResponse.json({ error: 'Failed to save attachment attributes.' }, { status: 500 })\n }\n\n if (dataEngine) {\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId ?? auth.orgId ?? null,\n tenantId: record.tenantId ?? auth.tenantId ?? null,\n },\n events: attachmentCrudEvents,\n indexer: attachmentCrudIndexer,\n })\n await dataEngine.flushOrmEntityChanges()\n }\n\n const metadata = readAttachmentMetadata(record.storageMetadata)\n const assignments = metadata.assignments ?? []\n const enrichments = await resolveAssignmentEnrichments(assignments, {\n queryEngine,\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n })\n const enrichedAssignments = applyAssignmentEnrichments(assignments, enrichments)\n return NextResponse.json({\n ok: true,\n item: {\n id: record.id,\n tags: metadata.tags ?? [],\n assignments: enrichedAssignments,\n customFields: normalizeCustomFieldResponse(custom ?? null),\n },\n })\n}\n\nexport async function DELETE(req: NextRequest, ctx: RouteContext) {\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n const attachmentId = await resolveAttachmentId(ctx)\n if (!attachmentId) {\n return NextResponse.json({ error: 'Attachment id is required' }, { status: 400 })\n }\n const { resolve } = await createRequestContainer()\n const em = resolve('em') as EntityManager\n const dataEngine = resolve('dataEngine') as DataEngine\n const storageDriverFactory = resolve('storageDriverFactory') as StorageDriverFactory\n const deleteFilter: Record<string, unknown> = {\n id: attachmentId,\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n }\n const record = await em.findOne(Attachment, deleteFilter)\n if (!record) {\n return NextResponse.json({ error: 'Attachment not found' }, { status: 404 })\n }\n const deleteDriver = await storageDriverFactory.resolveForPartition(record.partitionCode, {\n tenantId: record.tenantId ?? auth.tenantId,\n organizationId: record.organizationId ?? auth.orgId,\n })\n // Commit the DB row removal before deleting the irreversible storage file so a\n // failed commit cannot leave a dangling record whose backing file is already gone.\n const recordPartitionCode = record.partitionCode\n const recordStoragePath = record.storagePath\n await em.remove(record).flush()\n await deleteDriver.delete(recordPartitionCode, recordStoragePath)\n\n if (dataEngine) {\n await emitCrudSideEffects({\n dataEngine,\n action: 'deleted',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId ?? auth.orgId ?? null,\n tenantId: record.tenantId ?? auth.tenantId ?? null,\n },\n events: attachmentCrudEvents,\n indexer: attachmentCrudIndexer,\n })\n await dataEngine.flushOrmEntityChanges()\n }\n\n return NextResponse.json({ ok: true })\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: attachmentsTag,\n summary: 'Attachment detail management',\n methods: {\n GET: {\n summary: 'Get attachment details',\n description: 'Returns complete details of an attachment including metadata, tags, assignments, and custom fields.',\n responses: [\n { status: 200, description: 'Attachment details', schema: attachmentDetailResponseSchema },\n ],\n errors: [\n { status: 400, description: 'Invalid attachment ID', schema: attachmentErrorSchema },\n { status: 401, description: 'Unauthorized', schema: attachmentErrorSchema },\n { status: 404, description: 'Attachment not found', schema: attachmentErrorSchema },\n ],\n },\n PATCH: {\n summary: 'Update attachment metadata',\n description: 'Updates attachment tags, assignments, and custom fields. Emits CRUD side effects for indexing and events.',\n requestBody: {\n contentType: 'application/json',\n schema: updateSchema,\n },\n responses: [\n { status: 200, description: 'Attachment updated successfully', schema: z.object({ ok: z.literal(true), item: z.any() }) },\n ],\n errors: [\n { status: 400, description: 'Invalid payload or attachment ID', schema: attachmentErrorSchema },\n { status: 401, description: 'Unauthorized', schema: attachmentErrorSchema },\n { status: 404, description: 'Attachment not found', schema: attachmentErrorSchema },\n { status: 500, description: 'Failed to save attributes', schema: attachmentErrorSchema },\n ],\n },\n DELETE: {\n summary: 'Delete attachment',\n description: 'Permanently deletes an attachment file from storage and database. Emits CRUD side effects.',\n responses: [\n { status: 200, description: 'Attachment deleted successfully', schema: z.object({ ok: z.literal(true) }) },\n ],\n errors: [\n { status: 400, description: 'Invalid attachment ID', schema: attachmentErrorSchema },\n { status: 401, description: 'Unauthorized', schema: attachmentErrorSchema },\n { status: 404, description: 'Attachment not found', schema: attachmentErrorSchema },\n ],\n },\n },\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { NextRequest, NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { Attachment, AttachmentPartition } from '../../../data/entities'\nimport {\n mergeAttachmentMetadata,\n normalizeAttachmentAssignments,\n normalizeAttachmentTags,\n readAttachmentMetadata,\n} from '../../../lib/metadata'\nimport type { StorageDriverFactory } from '../../../lib/drivers'\nimport { splitCustomFieldPayload, loadCustomFieldValues } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { emitCrudSideEffects, setCustomFieldsIfAny } from '@open-mercato/shared/lib/commands/helpers'\nimport { normalizeCustomFieldResponse } from '@open-mercato/shared/lib/custom-fields/normalize'\nimport { E } from '#generated/entities.ids.generated'\nimport type { QueryEngine } from '@open-mercato/shared/lib/query/types'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { attachmentCrudEvents, attachmentCrudIndexer } from '../../../lib/crud'\nimport { applyAssignmentEnrichments, resolveAssignmentEnrichments } from '../../../lib/assignmentDetails'\nimport {\n attachmentsTag,\n attachmentDetailResponseSchema,\n attachmentErrorSchema,\n} from '../../openapi'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('attachments').child({ component: 'library' })\n\nconst updateSchema = z.object({\n tags: z.array(z.string()).optional(),\n assignments: z\n .array(\n z.object({\n type: z.string().min(1),\n id: z.string().min(1),\n href: z.string().nullable().optional(),\n label: z.string().nullable().optional(),\n }),\n )\n .optional(),\n})\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['attachments.view'] },\n PATCH: { requireAuth: true, requireFeatures: ['attachments.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['attachments.manage'] },\n}\n\ntype RouteParams = { id: string }\ntype RouteContext = { params: Promise<RouteParams> }\n\nasync function resolveAttachmentId(ctx: RouteContext): Promise<string | null> {\n const params = ctx?.params\n try {\n const { id } = await params\n if (typeof id === 'string' && id.trim().length) {\n return id\n }\n return null\n } catch {\n return null\n }\n}\n\nexport async function GET(req: NextRequest, ctx: RouteContext) {\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.tenantId || (!auth.orgId && !auth.isSuperAdmin)) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n const attachmentId = await resolveAttachmentId(ctx)\n if (!attachmentId) {\n return NextResponse.json({ error: 'Attachment id is required' }, { status: 400 })\n }\n const { resolve } = await createRequestContainer()\n const em = resolve('em') as EntityManager\n let queryEngine: QueryEngine | null = null\n try {\n queryEngine = resolve('queryEngine') as QueryEngine\n } catch {\n queryEngine = null\n }\n const findFilter: Record<string, unknown> = {\n id: attachmentId,\n tenantId: auth.tenantId,\n }\n if (auth.orgId) {\n findFilter.organizationId = auth.orgId\n }\n const record = await em.findOne(Attachment, findFilter)\n if (!record) {\n return NextResponse.json({ error: 'Attachment not found' }, { status: 404 })\n }\n const metadata = readAttachmentMetadata(record.storageMetadata)\n const partition = record.partitionCode\n ? await em.findOne(AttachmentPartition, { code: record.partitionCode })\n : null\n const customFieldValues = await loadCustomFieldValues({\n em,\n entityId: E.attachments.attachment,\n recordIds: [record.id],\n tenantIdByRecord: { [record.id]: record.tenantId ?? auth.tenantId ?? null },\n organizationIdByRecord: { [record.id]: record.organizationId ?? auth.orgId ?? null },\n tenantFallbacks: [auth.tenantId ?? null].filter((value): value is string => !!value),\n })\n const customFields = normalizeCustomFieldResponse(customFieldValues[record.id])\n const assignments = metadata.assignments ?? []\n const enrichments = await resolveAssignmentEnrichments(assignments, {\n queryEngine,\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n })\n const enrichedAssignments = applyAssignmentEnrichments(assignments, enrichments)\n return NextResponse.json({\n item: {\n id: record.id,\n fileName: record.fileName,\n fileSize: record.fileSize,\n mimeType: record.mimeType,\n partitionCode: record.partitionCode,\n partitionTitle: partition?.title ?? null,\n tags: metadata.tags ?? [],\n assignments: enrichedAssignments,\n content: record.content && record.content.trim() ? record.content : null,\n customFields,\n },\n })\n}\n\nexport async function PATCH(req: NextRequest, ctx: RouteContext) {\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n const attachmentId = await resolveAttachmentId(ctx)\n if (!attachmentId) {\n return NextResponse.json({ error: 'Attachment id is required' }, { status: 400 })\n }\n const rawBody = await req.json().catch(() => null)\n const { base, custom } = splitCustomFieldPayload(rawBody)\n const parsed = updateSchema.safeParse(base)\n if (!parsed.success) {\n return NextResponse.json({ error: 'Invalid payload' }, { status: 400 })\n }\n const { resolve } = await createRequestContainer()\n const em = resolve('em') as EntityManager\n let queryEngine: QueryEngine | null = null\n try {\n queryEngine = resolve('queryEngine') as QueryEngine\n } catch {\n queryEngine = null\n }\n const dataEngine = resolve('dataEngine') as DataEngine\n const patchFilter: Record<string, unknown> = {\n id: attachmentId,\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n }\n const record = await em.findOne(Attachment, patchFilter)\n if (!record) {\n return NextResponse.json({ error: 'Attachment not found' }, { status: 404 })\n }\n const patch: Record<string, unknown> = {}\n if (parsed.data.tags) patch.tags = normalizeAttachmentTags(parsed.data.tags)\n if (parsed.data.assignments) patch.assignments = normalizeAttachmentAssignments(parsed.data.assignments)\n record.storageMetadata = mergeAttachmentMetadata(record.storageMetadata, patch)\n // Commit the metadata mutation and the custom-field write atomically so a\n // custom-field failure cannot leave the attachment metadata partially updated.\n try {\n await em.transactional(async (tx) => {\n await tx.flush()\n if (dataEngine && custom && Object.keys(custom).length) {\n await setCustomFieldsIfAny({\n dataEngine,\n entityId: E.attachments.attachment,\n recordId: record.id,\n tenantId: record.tenantId ?? auth.tenantId ?? null,\n organizationId: record.organizationId ?? auth.orgId ?? null,\n values: custom,\n })\n }\n })\n } catch (error) {\n logger.error('Failed to persist custom attributes', { err: error })\n return NextResponse.json({ error: 'Failed to save attachment attributes.' }, { status: 500 })\n }\n\n if (dataEngine) {\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId ?? auth.orgId ?? null,\n tenantId: record.tenantId ?? auth.tenantId ?? null,\n },\n events: attachmentCrudEvents,\n indexer: attachmentCrudIndexer,\n })\n await dataEngine.flushOrmEntityChanges()\n }\n\n const metadata = readAttachmentMetadata(record.storageMetadata)\n const assignments = metadata.assignments ?? []\n const enrichments = await resolveAssignmentEnrichments(assignments, {\n queryEngine,\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n })\n const enrichedAssignments = applyAssignmentEnrichments(assignments, enrichments)\n return NextResponse.json({\n ok: true,\n item: {\n id: record.id,\n tags: metadata.tags ?? [],\n assignments: enrichedAssignments,\n customFields: normalizeCustomFieldResponse(custom ?? null),\n },\n })\n}\n\nexport async function DELETE(req: NextRequest, ctx: RouteContext) {\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n const attachmentId = await resolveAttachmentId(ctx)\n if (!attachmentId) {\n return NextResponse.json({ error: 'Attachment id is required' }, { status: 400 })\n }\n const { resolve } = await createRequestContainer()\n const em = resolve('em') as EntityManager\n const dataEngine = resolve('dataEngine') as DataEngine\n const storageDriverFactory = resolve('storageDriverFactory') as StorageDriverFactory\n const deleteFilter: Record<string, unknown> = {\n id: attachmentId,\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n }\n const record = await em.findOne(Attachment, deleteFilter)\n if (!record) {\n return NextResponse.json({ error: 'Attachment not found' }, { status: 404 })\n }\n const deleteDriver = await storageDriverFactory.resolveForPartition(record.partitionCode, {\n tenantId: record.tenantId ?? auth.tenantId,\n organizationId: record.organizationId ?? auth.orgId,\n })\n // Commit the DB row removal before deleting the irreversible storage file so a\n // failed commit cannot leave a dangling record whose backing file is already gone.\n const recordPartitionCode = record.partitionCode\n const recordStoragePath = record.storagePath\n await em.remove(record).flush()\n await deleteDriver.delete(recordPartitionCode, recordStoragePath)\n\n if (dataEngine) {\n await emitCrudSideEffects({\n dataEngine,\n action: 'deleted',\n entity: record,\n identifiers: {\n id: record.id,\n organizationId: record.organizationId ?? auth.orgId ?? null,\n tenantId: record.tenantId ?? auth.tenantId ?? null,\n },\n events: attachmentCrudEvents,\n indexer: attachmentCrudIndexer,\n })\n await dataEngine.flushOrmEntityChanges()\n }\n\n return NextResponse.json({ ok: true })\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: attachmentsTag,\n summary: 'Attachment detail management',\n methods: {\n GET: {\n summary: 'Get attachment details',\n description: 'Returns complete details of an attachment including metadata, tags, assignments, and custom fields.',\n responses: [\n { status: 200, description: 'Attachment details', schema: attachmentDetailResponseSchema },\n ],\n errors: [\n { status: 400, description: 'Invalid attachment ID', schema: attachmentErrorSchema },\n { status: 401, description: 'Unauthorized', schema: attachmentErrorSchema },\n { status: 404, description: 'Attachment not found', schema: attachmentErrorSchema },\n ],\n },\n PATCH: {\n summary: 'Update attachment metadata',\n description: 'Updates attachment tags, assignments, and custom fields. Emits CRUD side effects for indexing and events.',\n requestBody: {\n contentType: 'application/json',\n schema: updateSchema,\n },\n responses: [\n { status: 200, description: 'Attachment updated successfully', schema: z.object({ ok: z.literal(true), item: z.any() }) },\n ],\n errors: [\n { status: 400, description: 'Invalid payload or attachment ID', schema: attachmentErrorSchema },\n { status: 401, description: 'Unauthorized', schema: attachmentErrorSchema },\n { status: 404, description: 'Attachment not found', schema: attachmentErrorSchema },\n { status: 500, description: 'Failed to save attributes', schema: attachmentErrorSchema },\n ],\n },\n DELETE: {\n summary: 'Delete attachment',\n description: 'Permanently deletes an attachment file from storage and database. Emits CRUD side effects.',\n responses: [\n { status: 200, description: 'Attachment deleted successfully', schema: z.object({ ok: z.literal(true) }) },\n ],\n errors: [\n { status: 400, description: 'Invalid attachment ID', schema: attachmentErrorSchema },\n { status: 401, description: 'Unauthorized', schema: attachmentErrorSchema },\n { status: 404, description: 'Attachment not found', schema: attachmentErrorSchema },\n ],\n },\n },\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["metadata"]
7
7
  }