@open-mercato/core 0.6.5-develop.4384.1.ce2ec6eaaa → 0.6.5-develop.4393.1.de282b5dfd

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 (533) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/generated/entities/channel_ingest_dead_letter/index.js +25 -0
  3. package/dist/generated/entities/channel_ingest_dead_letter/index.js.map +7 -0
  4. package/dist/generated/entities/channel_thread_mapping/index.js +25 -0
  5. package/dist/generated/entities/channel_thread_mapping/index.js.map +7 -0
  6. package/dist/generated/entities/channel_thread_token/index.js +17 -0
  7. package/dist/generated/entities/channel_thread_token/index.js.map +7 -0
  8. package/dist/generated/entities/communication_channel/index.js +43 -0
  9. package/dist/generated/entities/communication_channel/index.js.map +7 -0
  10. package/dist/generated/entities/customer_interaction/index.js +4 -0
  11. package/dist/generated/entities/customer_interaction/index.js.map +2 -2
  12. package/dist/generated/entities/external_conversation/index.js +25 -0
  13. package/dist/generated/entities/external_conversation/index.js.map +7 -0
  14. package/dist/generated/entities/external_message/index.js +25 -0
  15. package/dist/generated/entities/external_message/index.js.map +7 -0
  16. package/dist/generated/entities/integration_credentials/index.js +3 -1
  17. package/dist/generated/entities/integration_credentials/index.js.map +2 -2
  18. package/dist/generated/entities/message/index.js +2 -0
  19. package/dist/generated/entities/message/index.js.map +2 -2
  20. package/dist/generated/entities/message_channel_link/index.js +33 -0
  21. package/dist/generated/entities/message_channel_link/index.js.map +7 -0
  22. package/dist/generated/entities/message_reaction/index.js +25 -0
  23. package/dist/generated/entities/message_reaction/index.js.map +7 -0
  24. package/dist/generated/entities.ids.generated.js +11 -0
  25. package/dist/generated/entities.ids.generated.js.map +2 -2
  26. package/dist/generated/entity-fields-registry.js +117 -0
  27. package/dist/generated/entity-fields-registry.js.map +2 -2
  28. package/dist/helpers/integration/authFixtures.js +2 -1
  29. package/dist/helpers/integration/authFixtures.js.map +2 -2
  30. package/dist/helpers/integration/communicationChannelsFixtures.js +58 -0
  31. package/dist/helpers/integration/communicationChannelsFixtures.js.map +7 -0
  32. package/dist/modules/communication_channels/acl.js +47 -0
  33. package/dist/modules/communication_channels/acl.js.map +7 -0
  34. package/dist/modules/communication_channels/api/delete/channels/[id]/route.js +133 -0
  35. package/dist/modules/communication_channels/api/delete/channels/[id]/route.js.map +7 -0
  36. package/dist/modules/communication_channels/api/delete/messages/[messageId]/reactions/[reactionId]/route.js +113 -0
  37. package/dist/modules/communication_channels/api/delete/messages/[messageId]/reactions/[reactionId]/route.js.map +7 -0
  38. package/dist/modules/communication_channels/api/get/channels/[id]/health/route.js +138 -0
  39. package/dist/modules/communication_channels/api/get/channels/[id]/health/route.js.map +7 -0
  40. package/dist/modules/communication_channels/api/get/channels/[id]/route.js +93 -0
  41. package/dist/modules/communication_channels/api/get/channels/[id]/route.js.map +7 -0
  42. package/dist/modules/communication_channels/api/get/channels/route.js +96 -0
  43. package/dist/modules/communication_channels/api/get/channels/route.js.map +7 -0
  44. package/dist/modules/communication_channels/api/get/me/channels/route.js +82 -0
  45. package/dist/modules/communication_channels/api/get/me/channels/route.js.map +7 -0
  46. package/dist/modules/communication_channels/api/get/oauth/[provider]/callback/route.js +274 -0
  47. package/dist/modules/communication_channels/api/get/oauth/[provider]/callback/route.js.map +7 -0
  48. package/dist/modules/communication_channels/api/post/channels/[id]/import-history/route.js +168 -0
  49. package/dist/modules/communication_channels/api/post/channels/[id]/import-history/route.js.map +7 -0
  50. package/dist/modules/communication_channels/api/post/channels/[id]/poll-now/route.js +143 -0
  51. package/dist/modules/communication_channels/api/post/channels/[id]/poll-now/route.js.map +7 -0
  52. package/dist/modules/communication_channels/api/post/channels/[id]/push/register/route.js +127 -0
  53. package/dist/modules/communication_channels/api/post/channels/[id]/push/register/route.js.map +7 -0
  54. package/dist/modules/communication_channels/api/post/channels/[id]/set-primary/route.js +99 -0
  55. package/dist/modules/communication_channels/api/post/channels/[id]/set-primary/route.js.map +7 -0
  56. package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js +197 -0
  57. package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js.map +7 -0
  58. package/dist/modules/communication_channels/api/post/channels/connect/credentials/route.js +124 -0
  59. package/dist/modules/communication_channels/api/post/channels/connect/credentials/route.js.map +7 -0
  60. package/dist/modules/communication_channels/api/post/messages/[messageId]/reactions/route.js +120 -0
  61. package/dist/modules/communication_channels/api/post/messages/[messageId]/reactions/route.js.map +7 -0
  62. package/dist/modules/communication_channels/api/post/oauth/[provider]/initiate/route.js +157 -0
  63. package/dist/modules/communication_channels/api/post/oauth/[provider]/initiate/route.js.map +7 -0
  64. package/dist/modules/communication_channels/api/post/send-as-user/route.js +115 -0
  65. package/dist/modules/communication_channels/api/post/send-as-user/route.js.map +7 -0
  66. package/dist/modules/communication_channels/api/post/test-seed/route.js +217 -0
  67. package/dist/modules/communication_channels/api/post/test-seed/route.js.map +7 -0
  68. package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js +175 -0
  69. package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js.map +7 -0
  70. package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js +123 -0
  71. package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js.map +7 -0
  72. package/dist/modules/communication_channels/api/put/threads/[threadId]/assign/route.js +117 -0
  73. package/dist/modules/communication_channels/api/put/threads/[threadId]/assign/route.js.map +7 -0
  74. package/dist/modules/communication_channels/backend/communication_channels/channels/[id]/page.js +180 -0
  75. package/dist/modules/communication_channels/backend/communication_channels/channels/[id]/page.js.map +7 -0
  76. package/dist/modules/communication_channels/backend/communication_channels/channels/[id]/page.meta.js +36 -0
  77. package/dist/modules/communication_channels/backend/communication_channels/channels/[id]/page.meta.js.map +7 -0
  78. package/dist/modules/communication_channels/backend/communication_channels/channels/page.js +107 -0
  79. package/dist/modules/communication_channels/backend/communication_channels/channels/page.js.map +7 -0
  80. package/dist/modules/communication_channels/backend/communication_channels/channels/page.meta.js +38 -0
  81. package/dist/modules/communication_channels/backend/communication_channels/channels/page.meta.js.map +7 -0
  82. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js +727 -0
  83. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js.map +7 -0
  84. package/dist/modules/communication_channels/backend/profile/communication-channels/page.meta.js +38 -0
  85. package/dist/modules/communication_channels/backend/profile/communication-channels/page.meta.js.map +7 -0
  86. package/dist/modules/communication_channels/commands/connect-credential-channel.js +154 -0
  87. package/dist/modules/communication_channels/commands/connect-credential-channel.js.map +7 -0
  88. package/dist/modules/communication_channels/commands/delete-channel.js +137 -0
  89. package/dist/modules/communication_channels/commands/delete-channel.js.map +7 -0
  90. package/dist/modules/communication_channels/commands/deliver-outbound-message.js +400 -0
  91. package/dist/modules/communication_channels/commands/deliver-outbound-message.js.map +7 -0
  92. package/dist/modules/communication_channels/commands/disconnect-channel.js +163 -0
  93. package/dist/modules/communication_channels/commands/disconnect-channel.js.map +7 -0
  94. package/dist/modules/communication_channels/commands/ingest-inbound-message.js +413 -0
  95. package/dist/modules/communication_channels/commands/ingest-inbound-message.js.map +7 -0
  96. package/dist/modules/communication_channels/commands/interceptors.js +68 -0
  97. package/dist/modules/communication_channels/commands/interceptors.js.map +7 -0
  98. package/dist/modules/communication_channels/commands/process-inbound-reaction.js +198 -0
  99. package/dist/modules/communication_channels/commands/process-inbound-reaction.js.map +7 -0
  100. package/dist/modules/communication_channels/commands/push-register.js +146 -0
  101. package/dist/modules/communication_channels/commands/push-register.js.map +7 -0
  102. package/dist/modules/communication_channels/commands/push-renew.js +23 -0
  103. package/dist/modules/communication_channels/commands/push-renew.js.map +7 -0
  104. package/dist/modules/communication_channels/commands/push-unregister.js +108 -0
  105. package/dist/modules/communication_channels/commands/push-unregister.js.map +7 -0
  106. package/dist/modules/communication_channels/commands/queue-import-history.js +113 -0
  107. package/dist/modules/communication_channels/commands/queue-import-history.js.map +7 -0
  108. package/dist/modules/communication_channels/commands/reassign-conversation.js +193 -0
  109. package/dist/modules/communication_channels/commands/reassign-conversation.js.map +7 -0
  110. package/dist/modules/communication_channels/commands/set-primary-channel.js +114 -0
  111. package/dist/modules/communication_channels/commands/set-primary-channel.js.map +7 -0
  112. package/dist/modules/communication_channels/commands/toggle-outbound-reaction.js +260 -0
  113. package/dist/modules/communication_channels/commands/toggle-outbound-reaction.js.map +7 -0
  114. package/dist/modules/communication_channels/data/enrichers.js +286 -0
  115. package/dist/modules/communication_channels/data/enrichers.js.map +7 -0
  116. package/dist/modules/communication_channels/data/entities.js +447 -0
  117. package/dist/modules/communication_channels/data/entities.js.map +7 -0
  118. package/dist/modules/communication_channels/data/extensions.js +67 -0
  119. package/dist/modules/communication_channels/data/extensions.js.map +7 -0
  120. package/dist/modules/communication_channels/data/validators.js +123 -0
  121. package/dist/modules/communication_channels/data/validators.js.map +7 -0
  122. package/dist/modules/communication_channels/di.js +35 -0
  123. package/dist/modules/communication_channels/di.js.map +7 -0
  124. package/dist/modules/communication_channels/encryption.js +12 -0
  125. package/dist/modules/communication_channels/encryption.js.map +7 -0
  126. package/dist/modules/communication_channels/events.js +124 -0
  127. package/dist/modules/communication_channels/events.js.map +7 -0
  128. package/dist/modules/communication_channels/index.js +20 -0
  129. package/dist/modules/communication_channels/index.js.map +7 -0
  130. package/dist/modules/communication_channels/lib/access-control.js +43 -0
  131. package/dist/modules/communication_channels/lib/access-control.js.map +7 -0
  132. package/dist/modules/communication_channels/lib/adapter-compat.js +36 -0
  133. package/dist/modules/communication_channels/lib/adapter-compat.js.map +7 -0
  134. package/dist/modules/communication_channels/lib/adapter-registry-singleton.js +22 -0
  135. package/dist/modules/communication_channels/lib/adapter-registry-singleton.js.map +7 -0
  136. package/dist/modules/communication_channels/lib/adapter.js +1 -0
  137. package/dist/modules/communication_channels/lib/adapter.js.map +7 -0
  138. package/dist/modules/communication_channels/lib/connect-channel.js +95 -0
  139. package/dist/modules/communication_channels/lib/connect-channel.js.map +7 -0
  140. package/dist/modules/communication_channels/lib/contact-resolver.js +79 -0
  141. package/dist/modules/communication_channels/lib/contact-resolver.js.map +7 -0
  142. package/dist/modules/communication_channels/lib/credential-refresh.js +97 -0
  143. package/dist/modules/communication_channels/lib/credential-refresh.js.map +7 -0
  144. package/dist/modules/communication_channels/lib/dead-letter.js +62 -0
  145. package/dist/modules/communication_channels/lib/dead-letter.js.map +7 -0
  146. package/dist/modules/communication_channels/lib/email-capabilities.js +47 -0
  147. package/dist/modules/communication_channels/lib/email-capabilities.js.map +7 -0
  148. package/dist/modules/communication_channels/lib/email-contact.js +14 -0
  149. package/dist/modules/communication_channels/lib/email-contact.js.map +7 -0
  150. package/dist/modules/communication_channels/lib/email-mime.js +259 -0
  151. package/dist/modules/communication_channels/lib/email-mime.js.map +7 -0
  152. package/dist/modules/communication_channels/lib/error-classification.js +101 -0
  153. package/dist/modules/communication_channels/lib/error-classification.js.map +7 -0
  154. package/dist/modules/communication_channels/lib/gmail-pubsub-jwt.js +185 -0
  155. package/dist/modules/communication_channels/lib/gmail-pubsub-jwt.js.map +7 -0
  156. package/dist/modules/communication_channels/lib/mutation-guards.js +114 -0
  157. package/dist/modules/communication_channels/lib/mutation-guards.js.map +7 -0
  158. package/dist/modules/communication_channels/lib/oauth-client-config.js +32 -0
  159. package/dist/modules/communication_channels/lib/oauth-client-config.js.map +7 -0
  160. package/dist/modules/communication_channels/lib/oauth-state.js +128 -0
  161. package/dist/modules/communication_channels/lib/oauth-state.js.map +7 -0
  162. package/dist/modules/communication_channels/lib/oauth-token.js +45 -0
  163. package/dist/modules/communication_channels/lib/oauth-token.js.map +7 -0
  164. package/dist/modules/communication_channels/lib/pg-errors.js +11 -0
  165. package/dist/modules/communication_channels/lib/pg-errors.js.map +7 -0
  166. package/dist/modules/communication_channels/lib/provider-health.js +24 -0
  167. package/dist/modules/communication_channels/lib/provider-health.js.map +7 -0
  168. package/dist/modules/communication_channels/lib/push-state.js +19 -0
  169. package/dist/modules/communication_channels/lib/push-state.js.map +7 -0
  170. package/dist/modules/communication_channels/lib/queue.js +54 -0
  171. package/dist/modules/communication_channels/lib/queue.js.map +7 -0
  172. package/dist/modules/communication_channels/lib/reaction-processor-types.js +5 -0
  173. package/dist/modules/communication_channels/lib/reaction-processor-types.js.map +7 -0
  174. package/dist/modules/communication_channels/lib/reaction-semantics.js +11 -0
  175. package/dist/modules/communication_channels/lib/reaction-semantics.js.map +7 -0
  176. package/dist/modules/communication_channels/lib/registry.js +67 -0
  177. package/dist/modules/communication_channels/lib/registry.js.map +7 -0
  178. package/dist/modules/communication_channels/lib/route-mutation-guard.js +43 -0
  179. package/dist/modules/communication_channels/lib/route-mutation-guard.js.map +7 -0
  180. package/dist/modules/communication_channels/lib/sanitize-channel-html.js +96 -0
  181. package/dist/modules/communication_channels/lib/sanitize-channel-html.js.map +7 -0
  182. package/dist/modules/communication_channels/lib/send-as-user.js +194 -0
  183. package/dist/modules/communication_channels/lib/send-as-user.js.map +7 -0
  184. package/dist/modules/communication_channels/lib/system-user.js +22 -0
  185. package/dist/modules/communication_channels/lib/system-user.js.map +7 -0
  186. package/dist/modules/communication_channels/lib/test-seed.js +68 -0
  187. package/dist/modules/communication_channels/lib/test-seed.js.map +7 -0
  188. package/dist/modules/communication_channels/lib/thread-matcher.js +263 -0
  189. package/dist/modules/communication_channels/lib/thread-matcher.js.map +7 -0
  190. package/dist/modules/communication_channels/lib/thread-token.js +219 -0
  191. package/dist/modules/communication_channels/lib/thread-token.js.map +7 -0
  192. package/dist/modules/communication_channels/lib/use-connect-channel.js +61 -0
  193. package/dist/modules/communication_channels/lib/use-connect-channel.js.map +7 -0
  194. package/dist/modules/communication_channels/migrations/Migration20260526134719_communication_channels.js +50 -0
  195. package/dist/modules/communication_channels/migrations/Migration20260526134719_communication_channels.js.map +7 -0
  196. package/dist/modules/communication_channels/migrations/Migration20260527195446_communication_channels.js +19 -0
  197. package/dist/modules/communication_channels/migrations/Migration20260527195446_communication_channels.js.map +7 -0
  198. package/dist/modules/communication_channels/migrations/Migration20260529231848_communication_channels.js +13 -0
  199. package/dist/modules/communication_channels/migrations/Migration20260529231848_communication_channels.js.map +7 -0
  200. package/dist/modules/communication_channels/migrations/Migration20260531120000_communication_channels.js +17 -0
  201. package/dist/modules/communication_channels/migrations/Migration20260531120000_communication_channels.js.map +7 -0
  202. package/dist/modules/communication_channels/notifications.client.js +51 -0
  203. package/dist/modules/communication_channels/notifications.client.js.map +7 -0
  204. package/dist/modules/communication_channels/notifications.handlers.js +53 -0
  205. package/dist/modules/communication_channels/notifications.handlers.js.map +7 -0
  206. package/dist/modules/communication_channels/notifications.js +56 -0
  207. package/dist/modules/communication_channels/notifications.js.map +7 -0
  208. package/dist/modules/communication_channels/setup.js +105 -0
  209. package/dist/modules/communication_channels/setup.js.map +7 -0
  210. package/dist/modules/communication_channels/subscribers/channel-requires-reauth-notification.js +71 -0
  211. package/dist/modules/communication_channels/subscribers/channel-requires-reauth-notification.js.map +7 -0
  212. package/dist/modules/communication_channels/subscribers/outbound-bridge.js +103 -0
  213. package/dist/modules/communication_channels/subscribers/outbound-bridge.js.map +7 -0
  214. package/dist/modules/communication_channels/subscribers/user-deleted-cascade.js +51 -0
  215. package/dist/modules/communication_channels/subscribers/user-deleted-cascade.js.map +7 -0
  216. package/dist/modules/communication_channels/widgets/components.js +7 -0
  217. package/dist/modules/communication_channels/widgets/components.js.map +7 -0
  218. package/dist/modules/communication_channels/widgets/injection/channel-badge/widget.client.js +18 -0
  219. package/dist/modules/communication_channels/widgets/injection/channel-badge/widget.client.js.map +7 -0
  220. package/dist/modules/communication_channels/widgets/injection/channel-badge/widget.js +30 -0
  221. package/dist/modules/communication_channels/widgets/injection/channel-badge/widget.js.map +7 -0
  222. package/dist/modules/communication_channels/widgets/injection/channel-info-panel/widget.client.js +185 -0
  223. package/dist/modules/communication_channels/widgets/injection/channel-info-panel/widget.client.js.map +7 -0
  224. package/dist/modules/communication_channels/widgets/injection/channel-info-panel/widget.js +17 -0
  225. package/dist/modules/communication_channels/widgets/injection/channel-info-panel/widget.js.map +7 -0
  226. package/dist/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.client.js +44 -0
  227. package/dist/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.client.js.map +7 -0
  228. package/dist/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.js +17 -0
  229. package/dist/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.js.map +7 -0
  230. package/dist/modules/communication_channels/widgets/injection/profile-channels-menu/widget.js +23 -0
  231. package/dist/modules/communication_channels/widgets/injection/profile-channels-menu/widget.js.map +7 -0
  232. package/dist/modules/communication_channels/widgets/injection/reaction-bar/widget.client.js +141 -0
  233. package/dist/modules/communication_channels/widgets/injection/reaction-bar/widget.client.js.map +7 -0
  234. package/dist/modules/communication_channels/widgets/injection/reaction-bar/widget.js +17 -0
  235. package/dist/modules/communication_channels/widgets/injection/reaction-bar/widget.js.map +7 -0
  236. package/dist/modules/communication_channels/widgets/injection-table.js +38 -0
  237. package/dist/modules/communication_channels/widgets/injection-table.js.map +7 -0
  238. package/dist/modules/communication_channels/widgets/notifications/ChannelRequiresReauthRenderer.js +25 -0
  239. package/dist/modules/communication_channels/widgets/notifications/ChannelRequiresReauthRenderer.js.map +7 -0
  240. package/dist/modules/communication_channels/widgets/notifications/MessageReceivedRenderer.js +19 -0
  241. package/dist/modules/communication_channels/widgets/notifications/MessageReceivedRenderer.js.map +7 -0
  242. package/dist/modules/communication_channels/widgets/notifications/index.js +7 -0
  243. package/dist/modules/communication_channels/widgets/notifications/index.js.map +7 -0
  244. package/dist/modules/communication_channels/workers/channel-import-history.js +185 -0
  245. package/dist/modules/communication_channels/workers/channel-import-history.js.map +7 -0
  246. package/dist/modules/communication_channels/workers/gmail-history-sync.js +154 -0
  247. package/dist/modules/communication_channels/workers/gmail-history-sync.js.map +7 -0
  248. package/dist/modules/communication_channels/workers/gmail-renew-watch.js +95 -0
  249. package/dist/modules/communication_channels/workers/gmail-renew-watch.js.map +7 -0
  250. package/dist/modules/communication_channels/workers/inbound-processor.js +56 -0
  251. package/dist/modules/communication_channels/workers/inbound-processor.js.map +7 -0
  252. package/dist/modules/communication_channels/workers/outbound-delivery.js +85 -0
  253. package/dist/modules/communication_channels/workers/outbound-delivery.js.map +7 -0
  254. package/dist/modules/communication_channels/workers/poll-channel.js +240 -0
  255. package/dist/modules/communication_channels/workers/poll-channel.js.map +7 -0
  256. package/dist/modules/communication_channels/workers/poll-tick.js +132 -0
  257. package/dist/modules/communication_channels/workers/poll-tick.js.map +7 -0
  258. package/dist/modules/communication_channels/workers/reaction-processor.js +192 -0
  259. package/dist/modules/communication_channels/workers/reaction-processor.js.map +7 -0
  260. package/dist/modules/customers/acl.js +18 -0
  261. package/dist/modules/customers/acl.js.map +2 -2
  262. package/dist/modules/customers/api/activities/route.js +9 -0
  263. package/dist/modules/customers/api/activities/route.js.map +2 -2
  264. package/dist/modules/customers/api/companies/[id]/route.js +18 -7
  265. package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
  266. package/dist/modules/customers/api/interactions/[id]/visibility/route.js +151 -0
  267. package/dist/modules/customers/api/interactions/[id]/visibility/route.js.map +7 -0
  268. package/dist/modules/customers/api/interactions/counts/route.js +6 -0
  269. package/dist/modules/customers/api/interactions/counts/route.js.map +2 -2
  270. package/dist/modules/customers/api/interactions/route.js +26 -7
  271. package/dist/modules/customers/api/interactions/route.js.map +2 -2
  272. package/dist/modules/customers/api/people/[id]/email-threads/route.js +82 -0
  273. package/dist/modules/customers/api/people/[id]/email-threads/route.js.map +7 -0
  274. package/dist/modules/customers/api/people/[id]/emails/route.js +157 -0
  275. package/dist/modules/customers/api/people/[id]/emails/route.js.map +7 -0
  276. package/dist/modules/customers/api/people/[id]/route.js +12 -4
  277. package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
  278. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +10 -0
  279. package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
  280. package/dist/modules/customers/commands/deals.js +46 -5
  281. package/dist/modules/customers/commands/deals.js.map +2 -2
  282. package/dist/modules/customers/commands/interactions.js +16 -0
  283. package/dist/modules/customers/commands/interactions.js.map +2 -2
  284. package/dist/modules/customers/components/detail/ActivityCard.js +32 -0
  285. package/dist/modules/customers/components/detail/ActivityCard.js.map +2 -2
  286. package/dist/modules/customers/components/detail/ComposeEmailDialog.js +242 -0
  287. package/dist/modules/customers/components/detail/ComposeEmailDialog.js.map +7 -0
  288. package/dist/modules/customers/components/detail/DealForm.js +2 -1
  289. package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
  290. package/dist/modules/customers/components/detail/DealsSection.js +10 -0
  291. package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
  292. package/dist/modules/customers/components/detail/EmailCardActions.js +179 -0
  293. package/dist/modules/customers/components/detail/EmailCardActions.js.map +7 -0
  294. package/dist/modules/customers/components/detail/EmailReplyForwardActions.js +52 -0
  295. package/dist/modules/customers/components/detail/EmailReplyForwardActions.js.map +7 -0
  296. package/dist/modules/customers/components/detail/PersonDetailTabs.js +7 -1
  297. package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
  298. package/dist/modules/customers/components/detail/PersonEmailThreadsTab.js +366 -0
  299. package/dist/modules/customers/components/detail/PersonEmailThreadsTab.js.map +7 -0
  300. package/dist/modules/customers/data/enrichers.js +133 -2
  301. package/dist/modules/customers/data/enrichers.js.map +2 -2
  302. package/dist/modules/customers/data/entities.js +18 -0
  303. package/dist/modules/customers/data/entities.js.map +2 -2
  304. package/dist/modules/customers/data/extensions.js +16 -0
  305. package/dist/modules/customers/data/extensions.js.map +7 -0
  306. package/dist/modules/customers/encryption.js +11 -0
  307. package/dist/modules/customers/encryption.js.map +2 -2
  308. package/dist/modules/customers/events.js +4 -1
  309. package/dist/modules/customers/events.js.map +2 -2
  310. package/dist/modules/customers/lib/findPeopleByAddresses.js +64 -0
  311. package/dist/modules/customers/lib/findPeopleByAddresses.js.map +7 -0
  312. package/dist/modules/customers/lib/kysely.js.map +2 -2
  313. package/dist/modules/customers/lib/link-channel-message-handler.js +303 -0
  314. package/dist/modules/customers/lib/link-channel-message-handler.js.map +7 -0
  315. package/dist/modules/customers/lib/personEmailThreads.js +205 -0
  316. package/dist/modules/customers/lib/personEmailThreads.js.map +7 -0
  317. package/dist/modules/customers/lib/visibilityFilter.js +51 -0
  318. package/dist/modules/customers/lib/visibilityFilter.js.map +7 -0
  319. package/dist/modules/customers/migrations/Migration20260527012240_customers.js +20 -0
  320. package/dist/modules/customers/migrations/Migration20260527012240_customers.js.map +7 -0
  321. package/dist/modules/customers/setup.js +2 -1
  322. package/dist/modules/customers/setup.js.map +2 -2
  323. package/dist/modules/customers/subscribers/link-channel-message-received.js +12 -0
  324. package/dist/modules/customers/subscribers/link-channel-message-received.js.map +7 -0
  325. package/dist/modules/customers/subscribers/link-channel-message-sent.js +12 -0
  326. package/dist/modules/customers/subscribers/link-channel-message-sent.js.map +7 -0
  327. package/dist/modules/integrations/data/entities.js +8 -1
  328. package/dist/modules/integrations/data/entities.js.map +2 -2
  329. package/dist/modules/integrations/lib/credentials-service.js +29 -14
  330. package/dist/modules/integrations/lib/credentials-service.js.map +2 -2
  331. package/dist/modules/integrations/migrations/Migration20260526154136_integrations.js +15 -0
  332. package/dist/modules/integrations/migrations/Migration20260526154136_integrations.js.map +7 -0
  333. package/dist/modules/messages/commands/messages.js +70 -8
  334. package/dist/modules/messages/commands/messages.js.map +2 -2
  335. package/dist/modules/messages/components/ComposeMessagePageClient.js +24 -13
  336. package/dist/modules/messages/components/ComposeMessagePageClient.js.map +2 -2
  337. package/dist/modules/messages/components/MessageDetailPageClient.js +39 -2
  338. package/dist/modules/messages/components/MessageDetailPageClient.js.map +2 -2
  339. package/dist/modules/messages/components/MessagesInboxPageClient.js +1 -0
  340. package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
  341. package/dist/modules/messages/data/entities.js +8 -1
  342. package/dist/modules/messages/data/entities.js.map +2 -2
  343. package/dist/modules/messages/migrations/Migration20260531130000.js +15 -0
  344. package/dist/modules/messages/migrations/Migration20260531130000.js.map +7 -0
  345. package/dist/modules/messages/widgets/injection-table.js +7 -0
  346. package/dist/modules/messages/widgets/injection-table.js.map +7 -0
  347. package/generated/entities/channel_ingest_dead_letter/index.ts +11 -0
  348. package/generated/entities/channel_thread_mapping/index.ts +11 -0
  349. package/generated/entities/channel_thread_token/index.ts +7 -0
  350. package/generated/entities/communication_channel/index.ts +20 -0
  351. package/generated/entities/customer_interaction/index.ts +2 -0
  352. package/generated/entities/external_conversation/index.ts +11 -0
  353. package/generated/entities/external_message/index.ts +11 -0
  354. package/generated/entities/integration_credentials/index.ts +1 -0
  355. package/generated/entities/message/index.ts +1 -0
  356. package/generated/entities/message_channel_link/index.ts +15 -0
  357. package/generated/entities/message_reaction/index.ts +11 -0
  358. package/generated/entities.ids.generated.ts +11 -0
  359. package/generated/entity-fields-registry.ts +117 -0
  360. package/package.json +9 -7
  361. package/src/helpers/integration/authFixtures.ts +4 -1
  362. package/src/helpers/integration/communicationChannelsFixtures.ts +124 -0
  363. package/src/modules/communication_channels/acl.ts +43 -0
  364. package/src/modules/communication_channels/api/delete/channels/[id]/route.ts +163 -0
  365. package/src/modules/communication_channels/api/delete/messages/[messageId]/reactions/[reactionId]/route.ts +143 -0
  366. package/src/modules/communication_channels/api/get/channels/[id]/health/route.ts +173 -0
  367. package/src/modules/communication_channels/api/get/channels/[id]/route.ts +111 -0
  368. package/src/modules/communication_channels/api/get/channels/route.ts +109 -0
  369. package/src/modules/communication_channels/api/get/me/channels/route.ts +100 -0
  370. package/src/modules/communication_channels/api/get/oauth/[provider]/callback/route.ts +355 -0
  371. package/src/modules/communication_channels/api/post/channels/[id]/import-history/route.ts +206 -0
  372. package/src/modules/communication_channels/api/post/channels/[id]/poll-now/route.ts +174 -0
  373. package/src/modules/communication_channels/api/post/channels/[id]/push/register/route.ts +158 -0
  374. package/src/modules/communication_channels/api/post/channels/[id]/set-primary/route.ts +114 -0
  375. package/src/modules/communication_channels/api/post/channels/[id]/test-send/route.ts +241 -0
  376. package/src/modules/communication_channels/api/post/channels/connect/credentials/route.ts +134 -0
  377. package/src/modules/communication_channels/api/post/messages/[messageId]/reactions/route.ts +143 -0
  378. package/src/modules/communication_channels/api/post/oauth/[provider]/initiate/route.ts +192 -0
  379. package/src/modules/communication_channels/api/post/send-as-user/route.ts +125 -0
  380. package/src/modules/communication_channels/api/post/test-seed/route.ts +267 -0
  381. package/src/modules/communication_channels/api/post/webhook/[provider]/route.ts +227 -0
  382. package/src/modules/communication_channels/api/post/webhooks/gmail/route.ts +161 -0
  383. package/src/modules/communication_channels/api/put/threads/[threadId]/assign/route.ts +132 -0
  384. package/src/modules/communication_channels/backend/communication_channels/channels/[id]/page.meta.ts +34 -0
  385. package/src/modules/communication_channels/backend/communication_channels/channels/[id]/page.tsx +250 -0
  386. package/src/modules/communication_channels/backend/communication_channels/channels/page.meta.ts +36 -0
  387. package/src/modules/communication_channels/backend/communication_channels/channels/page.tsx +137 -0
  388. package/src/modules/communication_channels/backend/profile/communication-channels/page.meta.ts +36 -0
  389. package/src/modules/communication_channels/backend/profile/communication-channels/page.tsx +907 -0
  390. package/src/modules/communication_channels/commands/connect-credential-channel.ts +243 -0
  391. package/src/modules/communication_channels/commands/delete-channel.ts +193 -0
  392. package/src/modules/communication_channels/commands/deliver-outbound-message.ts +579 -0
  393. package/src/modules/communication_channels/commands/disconnect-channel.ts +241 -0
  394. package/src/modules/communication_channels/commands/ingest-inbound-message.ts +602 -0
  395. package/src/modules/communication_channels/commands/interceptors.ts +104 -0
  396. package/src/modules/communication_channels/commands/process-inbound-reaction.ts +265 -0
  397. package/src/modules/communication_channels/commands/push-register.ts +203 -0
  398. package/src/modules/communication_channels/commands/push-renew.ts +49 -0
  399. package/src/modules/communication_channels/commands/push-unregister.ts +168 -0
  400. package/src/modules/communication_channels/commands/queue-import-history.ts +180 -0
  401. package/src/modules/communication_channels/commands/reassign-conversation.ts +273 -0
  402. package/src/modules/communication_channels/commands/set-primary-channel.ts +154 -0
  403. package/src/modules/communication_channels/commands/toggle-outbound-reaction.ts +347 -0
  404. package/src/modules/communication_channels/data/enrichers.ts +413 -0
  405. package/src/modules/communication_channels/data/entities.ts +546 -0
  406. package/src/modules/communication_channels/data/extensions.ts +76 -0
  407. package/src/modules/communication_channels/data/validators.ts +138 -0
  408. package/src/modules/communication_channels/di.ts +40 -0
  409. package/src/modules/communication_channels/encryption.ts +44 -0
  410. package/src/modules/communication_channels/events.ts +122 -0
  411. package/src/modules/communication_channels/i18n/de.json +138 -0
  412. package/src/modules/communication_channels/i18n/en.json +138 -0
  413. package/src/modules/communication_channels/i18n/es.json +138 -0
  414. package/src/modules/communication_channels/i18n/pl.json +138 -0
  415. package/src/modules/communication_channels/index.ts +19 -0
  416. package/src/modules/communication_channels/lib/access-control.ts +110 -0
  417. package/src/modules/communication_channels/lib/adapter-compat.ts +57 -0
  418. package/src/modules/communication_channels/lib/adapter-registry-singleton.ts +35 -0
  419. package/src/modules/communication_channels/lib/adapter.ts +605 -0
  420. package/src/modules/communication_channels/lib/connect-channel.ts +163 -0
  421. package/src/modules/communication_channels/lib/contact-resolver.ts +162 -0
  422. package/src/modules/communication_channels/lib/credential-refresh.ts +197 -0
  423. package/src/modules/communication_channels/lib/dead-letter.ts +87 -0
  424. package/src/modules/communication_channels/lib/email-capabilities.ts +60 -0
  425. package/src/modules/communication_channels/lib/email-contact.ts +17 -0
  426. package/src/modules/communication_channels/lib/email-mime.ts +425 -0
  427. package/src/modules/communication_channels/lib/error-classification.ts +144 -0
  428. package/src/modules/communication_channels/lib/gmail-pubsub-jwt.ts +278 -0
  429. package/src/modules/communication_channels/lib/mutation-guards.ts +215 -0
  430. package/src/modules/communication_channels/lib/oauth-client-config.ts +79 -0
  431. package/src/modules/communication_channels/lib/oauth-state.ts +228 -0
  432. package/src/modules/communication_channels/lib/oauth-token.ts +81 -0
  433. package/src/modules/communication_channels/lib/pg-errors.ts +12 -0
  434. package/src/modules/communication_channels/lib/provider-health.ts +47 -0
  435. package/src/modules/communication_channels/lib/push-state.ts +38 -0
  436. package/src/modules/communication_channels/lib/queue.ts +66 -0
  437. package/src/modules/communication_channels/lib/reaction-processor-types.ts +51 -0
  438. package/src/modules/communication_channels/lib/reaction-semantics.ts +48 -0
  439. package/src/modules/communication_channels/lib/registry.ts +99 -0
  440. package/src/modules/communication_channels/lib/route-mutation-guard.ts +68 -0
  441. package/src/modules/communication_channels/lib/sanitize-channel-html.ts +129 -0
  442. package/src/modules/communication_channels/lib/send-as-user.ts +284 -0
  443. package/src/modules/communication_channels/lib/system-user.ts +74 -0
  444. package/src/modules/communication_channels/lib/test-seed.ts +140 -0
  445. package/src/modules/communication_channels/lib/thread-matcher.ts +430 -0
  446. package/src/modules/communication_channels/lib/thread-token.ts +355 -0
  447. package/src/modules/communication_channels/lib/use-connect-channel.ts +73 -0
  448. package/src/modules/communication_channels/migrations/.snapshot-open-mercato.json +2142 -0
  449. package/src/modules/communication_channels/migrations/Migration20260526134719_communication_channels.ts +55 -0
  450. package/src/modules/communication_channels/migrations/Migration20260527195446_communication_channels.ts +20 -0
  451. package/src/modules/communication_channels/migrations/Migration20260529231848_communication_channels.ts +13 -0
  452. package/src/modules/communication_channels/migrations/Migration20260531120000_communication_channels.ts +24 -0
  453. package/src/modules/communication_channels/notifications.client.ts +50 -0
  454. package/src/modules/communication_channels/notifications.handlers.ts +86 -0
  455. package/src/modules/communication_channels/notifications.ts +52 -0
  456. package/src/modules/communication_channels/setup.ts +158 -0
  457. package/src/modules/communication_channels/subscribers/channel-requires-reauth-notification.ts +118 -0
  458. package/src/modules/communication_channels/subscribers/outbound-bridge.ts +175 -0
  459. package/src/modules/communication_channels/subscribers/user-deleted-cascade.ts +100 -0
  460. package/src/modules/communication_channels/widgets/components.ts +36 -0
  461. package/src/modules/communication_channels/widgets/injection/channel-badge/widget.client.tsx +38 -0
  462. package/src/modules/communication_channels/widgets/injection/channel-badge/widget.ts +51 -0
  463. package/src/modules/communication_channels/widgets/injection/channel-info-panel/widget.client.tsx +278 -0
  464. package/src/modules/communication_channels/widgets/injection/channel-info-panel/widget.ts +24 -0
  465. package/src/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.client.tsx +63 -0
  466. package/src/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.ts +29 -0
  467. package/src/modules/communication_channels/widgets/injection/profile-channels-menu/widget.ts +34 -0
  468. package/src/modules/communication_channels/widgets/injection/reaction-bar/widget.client.tsx +177 -0
  469. package/src/modules/communication_channels/widgets/injection/reaction-bar/widget.ts +26 -0
  470. package/src/modules/communication_channels/widgets/injection-table.ts +47 -0
  471. package/src/modules/communication_channels/widgets/notifications/ChannelRequiresReauthRenderer.tsx +48 -0
  472. package/src/modules/communication_channels/widgets/notifications/MessageReceivedRenderer.tsx +45 -0
  473. package/src/modules/communication_channels/widgets/notifications/index.ts +2 -0
  474. package/src/modules/communication_channels/workers/channel-import-history.ts +252 -0
  475. package/src/modules/communication_channels/workers/gmail-history-sync.ts +223 -0
  476. package/src/modules/communication_channels/workers/gmail-renew-watch.ts +141 -0
  477. package/src/modules/communication_channels/workers/inbound-processor.ts +114 -0
  478. package/src/modules/communication_channels/workers/outbound-delivery.ts +155 -0
  479. package/src/modules/communication_channels/workers/poll-channel.ts +391 -0
  480. package/src/modules/communication_channels/workers/poll-tick.ts +210 -0
  481. package/src/modules/communication_channels/workers/reaction-processor.ts +264 -0
  482. package/src/modules/customers/acl.ts +18 -0
  483. package/src/modules/customers/api/activities/route.ts +13 -0
  484. package/src/modules/customers/api/companies/[id]/route.ts +21 -1
  485. package/src/modules/customers/api/interactions/[id]/visibility/route.ts +179 -0
  486. package/src/modules/customers/api/interactions/counts/route.ts +10 -0
  487. package/src/modules/customers/api/interactions/route.ts +51 -5
  488. package/src/modules/customers/api/people/[id]/email-threads/route.ts +92 -0
  489. package/src/modules/customers/api/people/[id]/emails/route.ts +184 -0
  490. package/src/modules/customers/api/people/[id]/route.ts +17 -2
  491. package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +11 -1
  492. package/src/modules/customers/commands/deals.ts +65 -6
  493. package/src/modules/customers/commands/interactions.ts +30 -0
  494. package/src/modules/customers/components/detail/ActivityCard.tsx +48 -0
  495. package/src/modules/customers/components/detail/ComposeEmailDialog.tsx +329 -0
  496. package/src/modules/customers/components/detail/DealForm.tsx +2 -1
  497. package/src/modules/customers/components/detail/DealsSection.tsx +26 -0
  498. package/src/modules/customers/components/detail/EmailCardActions.tsx +258 -0
  499. package/src/modules/customers/components/detail/EmailReplyForwardActions.tsx +53 -0
  500. package/src/modules/customers/components/detail/PersonDetailTabs.tsx +8 -1
  501. package/src/modules/customers/components/detail/PersonEmailThreadsTab.tsx +448 -0
  502. package/src/modules/customers/data/enrichers.ts +252 -1
  503. package/src/modules/customers/data/entities.ts +46 -1
  504. package/src/modules/customers/data/extensions.ts +26 -0
  505. package/src/modules/customers/encryption.ts +11 -0
  506. package/src/modules/customers/events.ts +4 -0
  507. package/src/modules/customers/i18n/de.json +41 -0
  508. package/src/modules/customers/i18n/en.json +41 -0
  509. package/src/modules/customers/i18n/es.json +41 -0
  510. package/src/modules/customers/i18n/pl.json +41 -0
  511. package/src/modules/customers/lib/findPeopleByAddresses.ts +107 -0
  512. package/src/modules/customers/lib/kysely.ts +16 -0
  513. package/src/modules/customers/lib/link-channel-message-handler.ts +571 -0
  514. package/src/modules/customers/lib/personEmailThreads.ts +325 -0
  515. package/src/modules/customers/lib/visibilityFilter.ts +152 -0
  516. package/src/modules/customers/migrations/.snapshot-open-mercato.json +61 -0
  517. package/src/modules/customers/migrations/Migration20260527012240_customers.ts +23 -0
  518. package/src/modules/customers/setup.ts +1 -0
  519. package/src/modules/customers/subscribers/link-channel-message-received.ts +21 -0
  520. package/src/modules/customers/subscribers/link-channel-message-sent.ts +21 -0
  521. package/src/modules/integrations/AGENTS.md +9 -0
  522. package/src/modules/integrations/data/entities.ts +21 -1
  523. package/src/modules/integrations/lib/credentials-service.ts +49 -13
  524. package/src/modules/integrations/migrations/.snapshot-open-mercato.json +26 -1
  525. package/src/modules/integrations/migrations/Migration20260526154136_integrations.ts +15 -0
  526. package/src/modules/messages/commands/messages.ts +101 -8
  527. package/src/modules/messages/components/ComposeMessagePageClient.tsx +17 -0
  528. package/src/modules/messages/components/MessageDetailPageClient.tsx +43 -0
  529. package/src/modules/messages/components/MessagesInboxPageClient.tsx +4 -0
  530. package/src/modules/messages/data/entities.ts +11 -0
  531. package/src/modules/messages/migrations/.snapshot-open-mercato.json +18 -0
  532. package/src/modules/messages/migrations/Migration20260531130000.ts +15 -0
  533. package/src/modules/messages/widgets/injection-table.ts +29 -0
@@ -23,6 +23,7 @@ import { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuarde
23
23
  import { createTranslatorWithFallback } from '@open-mercato/shared/lib/i18n/translate'
24
24
 
25
25
  import { ActivitiesSection } from '../../../../components/detail/ActivitiesSection'
26
+ import { PersonEmailThreadsTab } from '../../../../components/detail/PersonEmailThreadsTab'
26
27
  import { ActivitiesCard } from '../../../../components/detail/ActivitiesCard'
27
28
  import type { ActivityKind } from '../../../../components/detail/ActivitiesAddNewMenu'
28
29
  import { DealsSection } from '../../../../components/detail/DealsSection'
@@ -421,7 +422,7 @@ export default function PersonDetailV2Page({ params }: { params?: { id?: string
421
422
  <Page>
422
423
  <PageBody>
423
424
  <div className="space-y-4">
424
- {/* UMES header injection */}
425
+ {/* UMES header injection (third-party extensions) */}
425
426
  <InjectionSpot spotId="detail:customers.person:header" context={injectionContext} data={data} />
426
427
  <InjectionSpot spotId="detail:customers.person:status-badges" context={injectionContext} data={data} />
427
428
 
@@ -519,6 +520,15 @@ export default function PersonDetailV2Page({ params }: { params?: { id?: string
519
520
  )
520
521
  }
521
522
 
523
+ if (activeTab === 'emails') {
524
+ return (
525
+ <PersonEmailThreadsTab
526
+ personId={personId}
527
+ defaultRecipient={data.person?.primaryEmail ?? null}
528
+ />
529
+ )
530
+ }
531
+
522
532
  if (activeTab === 'deals') {
523
533
  return (
524
534
  <DealsSection
@@ -110,6 +110,34 @@ async function resolvePipelineStageValue(
110
110
  return entry?.value ?? stage.label
111
111
  }
112
112
 
113
+ function resolvePipelineAssignment(input: {
114
+ pipelineId?: string | null
115
+ pipelineStageId?: string | null
116
+ stageSnapshot: PipelineStageSnapshot | null
117
+ }): { pipelineId: string | null; pipelineStageId: string | null } {
118
+ const requestedPipelineId = input.pipelineId ?? null
119
+ const requestedPipelineStageId = input.pipelineStageId ?? null
120
+
121
+ if (requestedPipelineStageId && !input.stageSnapshot) {
122
+ throw new CrudHttpError(400, { error: 'Pipeline stage not found' })
123
+ }
124
+
125
+ if (
126
+ requestedPipelineId &&
127
+ input.stageSnapshot &&
128
+ input.stageSnapshot.pipelineId !== requestedPipelineId
129
+ ) {
130
+ throw new CrudHttpError(400, {
131
+ error: 'Pipeline stage does not belong to the selected pipeline',
132
+ })
133
+ }
134
+
135
+ return {
136
+ pipelineId: requestedPipelineId ?? input.stageSnapshot?.pipelineId ?? null,
137
+ pipelineStageId: requestedPipelineStageId,
138
+ }
139
+ }
140
+
113
141
  async function upsertDealStageTransition(
114
142
  em: EntityManager,
115
143
  input: {
@@ -369,12 +397,21 @@ const createDealCommand: CommandHandler<DealCreateInput, { dealId: string }> = {
369
397
  const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)
370
398
  let deal!: CustomerDeal
371
399
  let stageSnapshot: PipelineStageSnapshot | null = null
400
+ let pipelineAssignment: { pipelineId: string | null; pipelineStageId: string | null } = {
401
+ pipelineId: null,
402
+ pipelineStageId: null,
403
+ }
372
404
  let resolvedPipelineStageLabel: string | null = null
373
405
  await withAtomicFlush(em, [
374
406
  async () => {
375
407
  stageSnapshot = parsed.pipelineStageId
376
408
  ? await loadPipelineStageSnapshot(em, parsed.pipelineStageId, parsed.tenantId, parsed.organizationId)
377
409
  : null
410
+ pipelineAssignment = resolvePipelineAssignment({
411
+ pipelineId: parsed.pipelineId,
412
+ pipelineStageId: parsed.pipelineStageId,
413
+ stageSnapshot,
414
+ })
378
415
  resolvedPipelineStageLabel = stageSnapshot
379
416
  ? (await ensureDictionaryEntry(em, {
380
417
  tenantId: parsed.tenantId,
@@ -392,8 +429,8 @@ const createDealCommand: CommandHandler<DealCreateInput, { dealId: string }> = {
392
429
  description: parsed.description ?? null,
393
430
  status: parsed.status ?? 'open',
394
431
  pipelineStage: resolvedPipelineStageLabel,
395
- pipelineId: parsed.pipelineId ?? null,
396
- pipelineStageId: parsed.pipelineStageId ?? null,
432
+ pipelineId: pipelineAssignment.pipelineId,
433
+ pipelineStageId: pipelineAssignment.pipelineStageId,
397
434
  valueAmount: toNumericString(parsed.valueAmount),
398
435
  valueCurrency: parsed.valueCurrency ?? null,
399
436
  probability: parsed.probability ?? null,
@@ -507,14 +544,34 @@ const updateDealCommand: CommandHandler<DealUpdateInput, { dealId: string }> = {
507
544
  const normalizedTransitionAuthorUserId = normalizeAuthorUserId(null, ctx.auth)
508
545
 
509
546
  let nextStageSnapshot: PipelineStageSnapshot | null = null
547
+ let nextPipelineAssignment: { pipelineId: string | null; pipelineStageId: string | null } = {
548
+ pipelineId: record.pipelineId ?? null,
549
+ pipelineStageId: record.pipelineStageId ?? null,
550
+ }
510
551
  let nextPipelineStageLabel: string | null = null
511
552
  let resolvedCurrentPipelineStageLabel: string | null = null
512
553
 
513
554
  await withAtomicFlush(em, [
514
555
  async () => {
515
- nextStageSnapshot = parsed.pipelineStageId
516
- ? await loadPipelineStageSnapshot(em, parsed.pipelineStageId, record.tenantId, record.organizationId)
556
+ const pipelineAssignmentChanged =
557
+ parsed.pipelineId !== undefined || parsed.pipelineStageId !== undefined
558
+ const requestedPipelineStageId =
559
+ parsed.pipelineStageId !== undefined
560
+ ? parsed.pipelineStageId ?? null
561
+ : record.pipelineStageId ?? null
562
+ const requestedPipelineId =
563
+ parsed.pipelineId !== undefined ? parsed.pipelineId ?? null : record.pipelineId ?? null
564
+
565
+ nextStageSnapshot = requestedPipelineStageId && (pipelineAssignmentChanged || !record.pipelineStage)
566
+ ? await loadPipelineStageSnapshot(em, requestedPipelineStageId, record.tenantId, record.organizationId)
517
567
  : null
568
+ if (pipelineAssignmentChanged) {
569
+ nextPipelineAssignment = resolvePipelineAssignment({
570
+ pipelineId: requestedPipelineId,
571
+ pipelineStageId: requestedPipelineStageId,
572
+ stageSnapshot: nextStageSnapshot,
573
+ })
574
+ }
518
575
  nextPipelineStageLabel = nextStageSnapshot
519
576
  ? (await ensureDictionaryEntry(em, {
520
577
  tenantId: record.tenantId,
@@ -533,8 +590,10 @@ const updateDealCommand: CommandHandler<DealUpdateInput, { dealId: string }> = {
533
590
  if (parsed.description !== undefined) record.description = parsed.description ?? null
534
591
  if (parsed.status !== undefined) record.status = parsed.status ?? record.status
535
592
  if (parsed.pipelineStage !== undefined) record.pipelineStage = parsed.pipelineStage ?? null
536
- if (parsed.pipelineId !== undefined) record.pipelineId = parsed.pipelineId ?? null
537
- if (parsed.pipelineStageId !== undefined) record.pipelineStageId = parsed.pipelineStageId ?? null
593
+ if (parsed.pipelineId !== undefined || (parsed.pipelineStageId !== undefined && nextStageSnapshot)) {
594
+ record.pipelineId = nextPipelineAssignment.pipelineId
595
+ }
596
+ if (parsed.pipelineStageId !== undefined) record.pipelineStageId = nextPipelineAssignment.pipelineStageId
538
597
 
539
598
  if (nextPipelineStageLabel && (parsed.pipelineStageId !== undefined || !record.pipelineStage)) {
540
599
  record.pipelineStage = nextPipelineStageLabel
@@ -41,6 +41,7 @@ import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
41
41
  import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
42
42
  import type { CrudIndexerConfig, CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'
43
43
  import { recomputeNextInteraction } from '../lib/interactionProjection'
44
+ import { canChangeEmailVisibility } from '../lib/visibilityFilter'
44
45
 
45
46
  const INTERACTION_ENTITY_ID = 'customers:customer_interaction'
46
47
  const interactionCrudIndexer: CrudIndexerConfig<CustomerInteraction> = {
@@ -454,6 +455,35 @@ const updateInteractionCommand: CommandHandler<InteractionUpdateInput, { interac
454
455
  ensureTenantScope(ctx, interaction.tenantId)
455
456
  ensureOrganizationScope(ctx, interaction.organizationId)
456
457
 
458
+ // Email visibility is an access-controlled field: only the interaction's
459
+ // author may change a
460
+ // private email's visibility (mirrors the dedicated PATCH .../visibility
461
+ // route). Enforce it here — the single persistence path — so the generic
462
+ // update route (PUT /api/interactions) cannot bypass the gate. Evaluated
463
+ // against the row's pre-mutation author/type. 404 (not 403) keeps the
464
+ // existence-masking consistent with the dedicated route.
465
+ if (
466
+ parsed.visibility !== undefined &&
467
+ interaction.interactionType === 'email' &&
468
+ (parsed.visibility ?? null) !== (interaction.visibility ?? null)
469
+ ) {
470
+ const actorUserId = (ctx.auth as { sub?: string | null } | null)?.sub ?? null
471
+ if (
472
+ !canChangeEmailVisibility({
473
+ interactionType: interaction.interactionType,
474
+ currentVisibility: interaction.visibility,
475
+ nextVisibility: parsed.visibility,
476
+ authorUserId: interaction.authorUserId,
477
+ actorUserId,
478
+ // v1 strict owner-only: only the author may flip visibility; no admin
479
+ // bypass (canChangeEmailVisibility ignores caller features in v1).
480
+ userFeatures: undefined,
481
+ })
482
+ ) {
483
+ throw new CrudHttpError(404, { error: 'Email not found' })
484
+ }
485
+ }
486
+
457
487
  if (parsed.dealId !== undefined) {
458
488
  if (parsed.dealId) {
459
489
  await requireDealInScope(trx, parsed.dealId, interaction.tenantId, interaction.organizationId)
@@ -11,6 +11,7 @@ import { useT } from '@open-mercato/shared/lib/i18n/context'
11
11
  import { cn } from '@open-mercato/shared/lib/utils'
12
12
  import type { InteractionSummary } from './types'
13
13
  import { ActivityAiActions } from './ActivityAiActions'
14
+ import { EmailCardActions, type EmailCardWidgetData } from './EmailCardActions'
14
15
 
15
16
  type GuardedMutationRunner = <T,>(
16
17
  operation: () => Promise<T>,
@@ -72,6 +73,42 @@ function resolveTarget(activity: InteractionSummary): string | null {
72
73
  return null
73
74
  }
74
75
 
76
+ /**
77
+ * Build the `EmailCardWidgetData` for the email-card-actions injection spot.
78
+ * Email metadata (rfcMessageId, addresses, threading headers, current visibility,
79
+ * and the author flag) is populated server-side by `interactionEmailCardEnricher`
80
+ * and surfaced via the `_integrations.email` passthrough; missing values fall
81
+ * back to null.
82
+ */
83
+ function buildEmailCardWidgetData(activity: InteractionSummary): EmailCardWidgetData {
84
+ const integrations = activity._integrations as Record<string, unknown> | undefined
85
+ const emailMeta = (integrations?.email ?? {}) as Record<string, unknown>
86
+ return {
87
+ interactionId: activity.id,
88
+ // The MessageChannelLink UUID stored on the interaction row.
89
+ externalMessageId:
90
+ typeof emailMeta.externalMessageId === 'string' ? emailMeta.externalMessageId : null,
91
+ // RFC2822 Message-ID (e.g. "<abc@mail.gmail.com>") for In-Reply-To / References headers.
92
+ rfcMessageId:
93
+ typeof emailMeta.rfcMessageId === 'string' ? emailMeta.rfcMessageId : null,
94
+ // entityId is the CustomerEntity id — on a person detail page this IS the personId.
95
+ personId: activity.entityId ?? null,
96
+ fromAddress:
97
+ typeof emailMeta.fromAddress === 'string' ? emailMeta.fromAddress : null,
98
+ toAddresses: Array.isArray(emailMeta.toAddresses) ? (emailMeta.toAddresses as string[]) : null,
99
+ ccAddresses: Array.isArray(emailMeta.ccAddresses) ? (emailMeta.ccAddresses as string[]) : null,
100
+ subject: activity.title ?? null,
101
+ inReplyTo:
102
+ typeof emailMeta.inReplyTo === 'string' ? emailMeta.inReplyTo : null,
103
+ references: Array.isArray(emailMeta.references) ? (emailMeta.references as string[]) : null,
104
+ currentVisibility:
105
+ emailMeta.currentVisibility === 'private' || emailMeta.currentVisibility === 'shared'
106
+ ? emailMeta.currentVisibility
107
+ : null,
108
+ isAuthor: typeof emailMeta.isAuthor === 'boolean' ? emailMeta.isAuthor : null,
109
+ }
110
+ }
111
+
75
112
  export function ActivityCard({ activity, onOpen, onChanged, runMutation }: ActivityCardProps) {
76
113
  const t = useT()
77
114
  const timestamp = activity.occurredAt ?? activity.scheduledAt ?? activity.createdAt
@@ -194,6 +231,17 @@ export function ActivityCard({ activity, onOpen, onChanged, runMutation }: Activ
194
231
  <ActivityAiActions activityType={activity.interactionType} />
195
232
  </div>
196
233
 
234
+ {activity.interactionType === 'email' ? (
235
+ <div
236
+ className="mt-1"
237
+ onClick={(event) => event.stopPropagation()}
238
+ onKeyDown={(event) => event.stopPropagation()}
239
+ role="presentation"
240
+ >
241
+ <EmailCardActions data={buildEmailCardWidgetData(activity)} />
242
+ </div>
243
+ ) : null}
244
+
197
245
  {snippet ? (
198
246
  <p className="mt-2 text-sm text-muted-foreground">{snippet}</p>
199
247
  ) : null}
@@ -0,0 +1,329 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@open-mercato/ui/primitives/dialog'
5
+ import { Button } from '@open-mercato/ui/primitives/button'
6
+ import { Input } from '@open-mercato/ui/primitives/input'
7
+ import { Label } from '@open-mercato/ui/primitives/label'
8
+ import { Textarea } from '@open-mercato/ui/primitives/textarea'
9
+ import { RadioGroup } from '@open-mercato/ui/primitives/radio'
10
+ import { RadioField } from '@open-mercato/ui/primitives/radio-field'
11
+ import {
12
+ Select,
13
+ SelectContent,
14
+ SelectItem,
15
+ SelectTrigger,
16
+ SelectValue,
17
+ } from '@open-mercato/ui/primitives/select'
18
+ import { useT } from '@open-mercato/shared/lib/i18n/context'
19
+
20
+ export interface ComposeEmailChannel {
21
+ id: string
22
+ displayName: string
23
+ externalIdentifier?: string | null
24
+ providerKey: 'gmail' | 'imap' | string
25
+ isPrimary?: boolean
26
+ }
27
+
28
+ export interface ComposeEmailValues {
29
+ userChannelId: string
30
+ to: string[]
31
+ cc?: string[]
32
+ bcc?: string[]
33
+ subject: string
34
+ body: string
35
+ bodyFormat: 'text' | 'html'
36
+ visibility: 'private' | 'shared'
37
+ inReplyTo?: string
38
+ references?: string[]
39
+ /** When replying, the messages.message id of the parent so the reply joins its thread. */
40
+ parentMessageId?: string
41
+ }
42
+
43
+ export interface ComposeEmailDialogProps {
44
+ open: boolean
45
+ onOpenChange: (open: boolean) => void
46
+ defaultRecipient?: string | null
47
+ channels: ComposeEmailChannel[]
48
+ replyTo?: {
49
+ inReplyTo?: string
50
+ references?: string[]
51
+ to: string[]
52
+ cc?: string[]
53
+ subject: string
54
+ parentMessageId?: string
55
+ } | null
56
+ onSend: (values: ComposeEmailValues) => Promise<{ messageId: string | null }>
57
+ }
58
+
59
+ function parseRecipients(raw: string): string[] {
60
+ return raw
61
+ .split(/[,;\s]+/)
62
+ .map((s) => s.trim())
63
+ .filter(Boolean)
64
+ }
65
+
66
+ function defaultChannelId(channels: ComposeEmailChannel[]): string {
67
+ const primary = channels.find((c) => c.isPrimary)
68
+ return primary?.id ?? channels[0]?.id ?? ''
69
+ }
70
+
71
+ /** Single source of truth for the dialog's seeded form values (reply prefill, default recipient, primary channel). */
72
+ function deriveComposeInitialState(
73
+ replyTo: ComposeEmailDialogProps['replyTo'],
74
+ defaultRecipient: string | null | undefined,
75
+ channels: ComposeEmailChannel[],
76
+ ): { to: string; cc: string; showCc: boolean; subject: string; channelId: string } {
77
+ const cc = replyTo?.cc && replyTo.cc.length > 0 ? replyTo.cc.join(', ') : ''
78
+ return {
79
+ to: replyTo ? replyTo.to.join(', ') : (defaultRecipient ?? ''),
80
+ cc,
81
+ showCc: Boolean(cc),
82
+ subject: replyTo?.subject ?? '',
83
+ channelId: defaultChannelId(channels),
84
+ }
85
+ }
86
+
87
+ export function ComposeEmailDialog({
88
+ open,
89
+ onOpenChange,
90
+ channels,
91
+ defaultRecipient,
92
+ replyTo,
93
+ onSend,
94
+ }: ComposeEmailDialogProps) {
95
+ const t = useT()
96
+
97
+ const initial = React.useMemo(
98
+ () => deriveComposeInitialState(replyTo, defaultRecipient, channels),
99
+ [replyTo, defaultRecipient, channels],
100
+ )
101
+
102
+ const [to, setTo] = React.useState(initial.to)
103
+ const [showCc, setShowCc] = React.useState(initial.showCc)
104
+ const [cc, setCc] = React.useState(initial.cc)
105
+ const [subject, setSubject] = React.useState(initial.subject)
106
+ const [body, setBody] = React.useState('')
107
+ const [visibility, setVisibility] = React.useState<'private' | 'shared'>('private')
108
+ const [channelId, setChannelId] = React.useState(initial.channelId)
109
+ const [busy, setBusy] = React.useState(false)
110
+ const [error, setError] = React.useState<string | null>(null)
111
+
112
+ // Reset the form whenever the dialog (re)opens or its seed inputs change.
113
+ React.useEffect(() => {
114
+ if (!open) return
115
+ const next = deriveComposeInitialState(replyTo, defaultRecipient, channels)
116
+ setTo(next.to)
117
+ setCc(next.cc)
118
+ setShowCc(next.showCc)
119
+ setSubject(next.subject)
120
+ setBody('')
121
+ setVisibility('private')
122
+ setChannelId(next.channelId)
123
+ setError(null)
124
+ setBusy(false)
125
+ }, [open, replyTo, defaultRecipient, channels])
126
+
127
+ const toList = React.useMemo(() => parseRecipients(to), [to])
128
+ const isSendDisabled =
129
+ busy ||
130
+ toList.length === 0 ||
131
+ subject.trim().length === 0 ||
132
+ body.trim().length === 0 ||
133
+ !channelId
134
+
135
+ const handleSend = React.useCallback(async () => {
136
+ setError(null)
137
+ setBusy(true)
138
+ try {
139
+ const ccList = showCc ? parseRecipients(cc) : undefined
140
+ const values: ComposeEmailValues = {
141
+ userChannelId: channelId,
142
+ to: toList,
143
+ cc: ccList && ccList.length > 0 ? ccList : undefined,
144
+ subject: subject.trim(),
145
+ body: body.trim(),
146
+ bodyFormat: 'text',
147
+ visibility,
148
+ inReplyTo: replyTo?.inReplyTo,
149
+ references: replyTo?.references,
150
+ parentMessageId: replyTo?.parentMessageId,
151
+ }
152
+ await onSend(values)
153
+ onOpenChange(false)
154
+ } catch (err) {
155
+ const message = err instanceof Error ? err.message : String(err)
156
+ setError(message)
157
+ } finally {
158
+ setBusy(false)
159
+ }
160
+ }, [showCc, cc, channelId, toList, subject, body, visibility, replyTo, onSend, onOpenChange])
161
+
162
+ const handleKeyDown = React.useCallback(
163
+ (event: React.KeyboardEvent) => {
164
+ if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {
165
+ if (!isSendDisabled) {
166
+ void handleSend()
167
+ }
168
+ }
169
+ },
170
+ [isSendDisabled, handleSend],
171
+ )
172
+
173
+ return (
174
+ <Dialog open={open} onOpenChange={onOpenChange}>
175
+ <DialogContent className="sm:max-w-2xl" onKeyDown={handleKeyDown}>
176
+ <DialogHeader>
177
+ <DialogTitle>
178
+ {replyTo
179
+ ? t('customers.email.compose.replyTitle', 'Reply')
180
+ : t('customers.email.compose.title', 'Compose email')}
181
+ </DialogTitle>
182
+ </DialogHeader>
183
+
184
+ <div className="flex flex-col gap-4">
185
+ {/* To */}
186
+ <div className="flex flex-col gap-1.5">
187
+ <div className="flex items-center justify-between">
188
+ <Label htmlFor="compose-to">
189
+ {t('customers.email.compose.to', 'To')}
190
+ </Label>
191
+ {!showCc && (
192
+ <Button
193
+ type="button"
194
+ variant="link"
195
+ size="2xs"
196
+ className="text-muted-foreground hover:text-foreground"
197
+ onClick={() => setShowCc(true)}
198
+ aria-label={t('customers.email.compose.addCc.ariaLabel', 'Add Cc recipients')}
199
+ >
200
+ {t('customers.email.compose.addCc', '+ Cc')}
201
+ </Button>
202
+ )}
203
+ </div>
204
+ <Input
205
+ id="compose-to"
206
+ value={to}
207
+ onChange={(e) => setTo(e.target.value)}
208
+ placeholder={t('customers.email.compose.toPlaceholder', 'recipient@example.com')}
209
+ autoComplete="off"
210
+ />
211
+ </div>
212
+
213
+ {/* Cc (collapsible) */}
214
+ {showCc && (
215
+ <div className="flex flex-col gap-1.5">
216
+ <Label htmlFor="compose-cc">
217
+ {t('customers.email.compose.cc', 'Cc')}
218
+ </Label>
219
+ <Input
220
+ id="compose-cc"
221
+ value={cc}
222
+ onChange={(e) => setCc(e.target.value)}
223
+ placeholder={t('customers.email.compose.ccPlaceholder', 'cc@example.com')}
224
+ autoComplete="off"
225
+ />
226
+ </div>
227
+ )}
228
+
229
+ {/* Subject */}
230
+ <div className="flex flex-col gap-1.5">
231
+ <Label htmlFor="compose-subject">
232
+ {t('customers.email.compose.subject', 'Subject')}
233
+ </Label>
234
+ <Input
235
+ id="compose-subject"
236
+ value={subject}
237
+ onChange={(e) => setSubject(e.target.value)}
238
+ placeholder={t('customers.email.compose.subjectPlaceholder', 'Email subject')}
239
+ />
240
+ </div>
241
+
242
+ {/* Body */}
243
+ <div className="flex flex-col gap-1.5">
244
+ <Label htmlFor="compose-body">
245
+ {t('customers.email.compose.body', 'Body')}
246
+ </Label>
247
+ <Textarea
248
+ id="compose-body"
249
+ value={body}
250
+ onChange={(e) => setBody(e.target.value)}
251
+ placeholder={t('customers.email.compose.bodyPlaceholder', 'Write your message...')}
252
+ rows={8}
253
+ />
254
+ </div>
255
+
256
+ {/* Visibility */}
257
+ <div className="flex flex-col gap-2">
258
+ <Label>
259
+ {t('customers.email.compose.visibility', 'Visibility')}
260
+ </Label>
261
+ <RadioGroup
262
+ value={visibility}
263
+ onValueChange={(val) => setVisibility(val as 'private' | 'shared')}
264
+ className="flex flex-row gap-4"
265
+ >
266
+ <RadioField
267
+ value="private"
268
+ label={t('customers.email.compose.visibilityPrivate', 'Private to me')}
269
+ />
270
+ <RadioField
271
+ value="shared"
272
+ label={t('customers.email.compose.visibilityShared', 'Visible to teammates')}
273
+ />
274
+ </RadioGroup>
275
+ </div>
276
+
277
+ {/* Send as (channel selector) */}
278
+ {channels.length > 0 && (
279
+ <div className="flex flex-col gap-1.5">
280
+ <Label htmlFor="compose-channel">
281
+ {t('customers.email.compose.sendAs', 'Send as')}
282
+ </Label>
283
+ <Select value={channelId} onValueChange={setChannelId}>
284
+ <SelectTrigger id="compose-channel">
285
+ <SelectValue placeholder={t('customers.email.compose.selectChannel', 'Select account')} />
286
+ </SelectTrigger>
287
+ <SelectContent>
288
+ {channels.map((ch) => (
289
+ <SelectItem key={ch.id} value={ch.id}>
290
+ {ch.displayName}
291
+ {ch.externalIdentifier ? ` (${ch.externalIdentifier})` : ''}
292
+ </SelectItem>
293
+ ))}
294
+ </SelectContent>
295
+ </Select>
296
+ </div>
297
+ )}
298
+
299
+ {/* Inline error */}
300
+ {error && (
301
+ <p className="text-sm text-status-error-text" role="alert">
302
+ {error}
303
+ </p>
304
+ )}
305
+ </div>
306
+
307
+ <DialogFooter>
308
+ <Button
309
+ type="button"
310
+ variant="outline"
311
+ onClick={() => onOpenChange(false)}
312
+ disabled={busy}
313
+ >
314
+ {t('customers.email.compose.cancel', 'Cancel')}
315
+ </Button>
316
+ <Button
317
+ type="button"
318
+ onClick={() => void handleSend()}
319
+ disabled={isSendDisabled}
320
+ >
321
+ {busy
322
+ ? t('customers.email.compose.sending', 'Sending...')
323
+ : t('customers.email.compose.send', 'Send')}
324
+ </Button>
325
+ </DialogFooter>
326
+ </DialogContent>
327
+ </Dialog>
328
+ )
329
+ }
@@ -805,11 +805,12 @@ export function DealForm({
805
805
  label: t('customers.people.detail.deals.fields.pipeline', 'Pipeline'),
806
806
  type: 'custom',
807
807
  layout: 'half',
808
- component: ({ value, setValue }) => (
808
+ component: ({ value, setValue, setFormValue }) => (
809
809
  <Select
810
810
  value={typeof value === 'string' && value ? value : undefined}
811
811
  onValueChange={(next) => {
812
812
  setValue(next ?? '')
813
+ setFormValue?.('pipelineStageId', '')
813
814
  loadStagesForPipeline(next ?? '').catch(() => {})
814
815
  }}
815
816
  disabled={disabled}
@@ -226,6 +226,14 @@ function normalizeDeal(deal: Partial<DealSummary> & { id: string; title?: string
226
226
  status: typeof deal.status === 'string' ? deal.status : deal.status ?? null,
227
227
  pipelineStage:
228
228
  typeof deal.pipelineStage === 'string' ? deal.pipelineStage : deal.pipelineStage ?? null,
229
+ pipelineId:
230
+ typeof deal.pipelineId === 'string' && deal.pipelineId.trim().length
231
+ ? deal.pipelineId.trim()
232
+ : deal.pipelineId ?? null,
233
+ pipelineStageId:
234
+ typeof deal.pipelineStageId === 'string' && deal.pipelineStageId.trim().length
235
+ ? deal.pipelineStageId.trim()
236
+ : deal.pipelineStageId ?? null,
229
237
  valueAmount: toNumber(deal.valueAmount ?? null),
230
238
  valueCurrency:
231
239
  typeof deal.valueCurrency === 'string' && deal.valueCurrency.trim().length
@@ -413,6 +421,18 @@ export function DealsSection({
413
421
  : typeof record.pipeline_stage === 'string' && record.pipeline_stage.trim().length
414
422
  ? record.pipeline_stage.trim()
415
423
  : null
424
+ const pipelineId =
425
+ typeof record.pipelineId === 'string' && record.pipelineId.trim().length
426
+ ? record.pipelineId.trim()
427
+ : typeof record.pipeline_id === 'string' && record.pipeline_id.trim().length
428
+ ? record.pipeline_id.trim()
429
+ : null
430
+ const pipelineStageId =
431
+ typeof record.pipelineStageId === 'string' && record.pipelineStageId.trim().length
432
+ ? record.pipelineStageId.trim()
433
+ : typeof record.pipeline_stage_id === 'string' && record.pipeline_stage_id.trim().length
434
+ ? record.pipeline_stage_id.trim()
435
+ : null
416
436
  const valueAmount = toNumber(record.valueAmount ?? record.value_amount)
417
437
  const valueCurrencyRaw = record.valueCurrency ?? record.value_currency ?? null
418
438
  const valueCurrency =
@@ -494,6 +514,8 @@ export function DealsSection({
494
514
  title,
495
515
  status,
496
516
  pipelineStage,
517
+ pipelineId,
518
+ pipelineStageId,
497
519
  valueAmount,
498
520
  valueCurrency,
499
521
  probability,
@@ -727,6 +749,8 @@ export function DealsSection({
727
749
  title: base.title,
728
750
  status: base.status ?? undefined,
729
751
  pipelineStage: base.pipelineStage ?? undefined,
752
+ pipelineId: base.pipelineId ?? undefined,
753
+ pipelineStageId: base.pipelineStageId ?? undefined,
730
754
  valueAmount: typeof base.valueAmount === 'number' ? base.valueAmount : undefined,
731
755
  valueCurrency: base.valueCurrency ?? undefined,
732
756
  probability: typeof base.probability === 'number' ? base.probability : undefined,
@@ -761,6 +785,8 @@ export function DealsSection({
761
785
  title: base.title,
762
786
  status: base.status ?? null,
763
787
  pipelineStage: base.pipelineStage ?? null,
788
+ pipelineId: base.pipelineId ?? null,
789
+ pipelineStageId: base.pipelineStageId ?? null,
764
790
  valueAmount: base.valueAmount ?? null,
765
791
  valueCurrency: base.valueCurrency ?? null,
766
792
  probability: base.probability ?? null,