@open-mercato/core 0.6.8-develop.6984.1.f0cf23f0f6 → 0.6.8-develop.6985.1.fb93574faa

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 (597) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/dist/generated/entities/notification/index.js +6 -0
  3. package/dist/generated/entities/notification/index.js.map +2 -2
  4. package/dist/generated/entities/notification_preference/index.js +19 -0
  5. package/dist/generated/entities/notification_preference/index.js.map +7 -0
  6. package/dist/generated/entities/notification_type/index.js +21 -0
  7. package/dist/generated/entities/notification_type/index.js.map +7 -0
  8. package/dist/generated/entities/notification_type_override/index.js +17 -0
  9. package/dist/generated/entities/notification_type_override/index.js.map +7 -0
  10. package/dist/generated/entities/push_notification_delivery/index.js +41 -0
  11. package/dist/generated/entities/push_notification_delivery/index.js.map +7 -0
  12. package/dist/generated/entities/user_device/index.js +35 -0
  13. package/dist/generated/entities/user_device/index.js.map +7 -0
  14. package/dist/generated/entities.ids.generated.js +12 -1
  15. package/dist/generated/entities.ids.generated.js.map +2 -2
  16. package/dist/generated/entity-fields-registry.js +72 -0
  17. package/dist/generated/entity-fields-registry.js.map +2 -2
  18. package/dist/helpers/integration/api.js +2 -1
  19. package/dist/helpers/integration/api.js.map +2 -2
  20. package/dist/helpers/integration/appRoot.js +9 -0
  21. package/dist/helpers/integration/appRoot.js.map +7 -0
  22. package/dist/helpers/integration/dbFixtures.js +1 -4
  23. package/dist/helpers/integration/dbFixtures.js.map +2 -2
  24. package/dist/helpers/integration/pushFake.js +126 -0
  25. package/dist/helpers/integration/pushFake.js.map +7 -0
  26. package/dist/modules/auth/notifications.js +16 -0
  27. package/dist/modules/auth/notifications.js.map +2 -2
  28. package/dist/modules/business_rules/notifications.js +2 -0
  29. package/dist/modules/business_rules/notifications.js.map +2 -2
  30. package/dist/modules/catalog/notifications.js +2 -0
  31. package/dist/modules/catalog/notifications.js.map +2 -2
  32. package/dist/modules/communication_channels/acl.js +9 -0
  33. package/dist/modules/communication_channels/acl.js.map +2 -2
  34. package/dist/modules/communication_channels/api/delete/admin/channels/[id]/route.js +133 -0
  35. package/dist/modules/communication_channels/api/delete/admin/channels/[id]/route.js.map +7 -0
  36. package/dist/modules/communication_channels/api/get/channels/[id]/health/route.js +6 -2
  37. package/dist/modules/communication_channels/api/get/channels/[id]/health/route.js.map +2 -2
  38. package/dist/modules/communication_channels/api/get/channels/[id]/route.js +6 -2
  39. package/dist/modules/communication_channels/api/get/channels/[id]/route.js.map +2 -2
  40. package/dist/modules/communication_channels/api/get/channels/route.js +2 -1
  41. package/dist/modules/communication_channels/api/get/channels/route.js.map +2 -2
  42. package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js +10 -5
  43. package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js.map +2 -2
  44. package/dist/modules/communication_channels/api/post/channels/connect/credentials/route.js +29 -1
  45. package/dist/modules/communication_channels/api/post/channels/connect/credentials/route.js.map +2 -2
  46. package/dist/modules/communication_channels/api/post/channels/connect/tenant-credentials/route.js +157 -0
  47. package/dist/modules/communication_channels/api/post/channels/connect/tenant-credentials/route.js.map +7 -0
  48. package/dist/modules/communication_channels/backend/communication_channels/channels/page.js +8 -1
  49. package/dist/modules/communication_channels/backend/communication_channels/channels/page.js.map +2 -2
  50. package/dist/modules/communication_channels/commands/admin-delete-channel.js +141 -0
  51. package/dist/modules/communication_channels/commands/admin-delete-channel.js.map +7 -0
  52. package/dist/modules/communication_channels/commands/connect-credential-channel.js +25 -8
  53. package/dist/modules/communication_channels/commands/connect-credential-channel.js.map +2 -2
  54. package/dist/modules/communication_channels/commands/deliver-outbound-message.js +2 -2
  55. package/dist/modules/communication_channels/commands/deliver-outbound-message.js.map +2 -2
  56. package/dist/modules/communication_channels/commands/push-register.js +1 -1
  57. package/dist/modules/communication_channels/commands/push-register.js.map +2 -2
  58. package/dist/modules/communication_channels/commands/push-unregister.js +4 -3
  59. package/dist/modules/communication_channels/commands/push-unregister.js.map +2 -2
  60. package/dist/modules/communication_channels/data/entities.js +4 -0
  61. package/dist/modules/communication_channels/data/entities.js.map +2 -2
  62. package/dist/modules/communication_channels/data/validators.js +2 -1
  63. package/dist/modules/communication_channels/data/validators.js.map +2 -2
  64. package/dist/modules/communication_channels/lib/access-control.js +11 -1
  65. package/dist/modules/communication_channels/lib/access-control.js.map +2 -2
  66. package/dist/modules/communication_channels/lib/connect-channel.js +20 -12
  67. package/dist/modules/communication_channels/lib/connect-channel.js.map +2 -2
  68. package/dist/modules/communication_channels/lib/push-adapter.js +68 -0
  69. package/dist/modules/communication_channels/lib/push-adapter.js.map +7 -0
  70. package/dist/modules/communication_channels/lib/push-capabilities.js +31 -0
  71. package/dist/modules/communication_channels/lib/push-capabilities.js.map +7 -0
  72. package/dist/modules/communication_channels/lib/push-connect-error.js +20 -0
  73. package/dist/modules/communication_channels/lib/push-connect-error.js.map +7 -0
  74. package/dist/modules/communication_channels/lib/push-credential-errors.js +41 -0
  75. package/dist/modules/communication_channels/lib/push-credential-errors.js.map +7 -0
  76. package/dist/modules/communication_channels/lib/push-envelope.js +46 -0
  77. package/dist/modules/communication_channels/lib/push-envelope.js.map +7 -0
  78. package/dist/modules/communication_channels/lib/refcounted-client-cache.js +64 -0
  79. package/dist/modules/communication_channels/lib/refcounted-client-cache.js.map +7 -0
  80. package/dist/modules/communication_channels/migrations/Migration20260703123630_communication_channels.js +13 -0
  81. package/dist/modules/communication_channels/migrations/Migration20260703123630_communication_channels.js.map +7 -0
  82. package/dist/modules/communication_channels/notifications.js +4 -0
  83. package/dist/modules/communication_channels/notifications.js.map +2 -2
  84. package/dist/modules/communication_channels/setup.js +2 -0
  85. package/dist/modules/communication_channels/setup.js.map +2 -2
  86. package/dist/modules/configs/lib/upgrade-actions.js +21 -0
  87. package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
  88. package/dist/modules/customer_accounts/notifications.js +12 -0
  89. package/dist/modules/customer_accounts/notifications.js.map +2 -2
  90. package/dist/modules/customers/notifications.js +4 -0
  91. package/dist/modules/customers/notifications.js.map +2 -2
  92. package/dist/modules/devices/acl.js +11 -0
  93. package/dist/modules/devices/acl.js.map +7 -0
  94. package/dist/modules/devices/api/[id]/route.js +167 -0
  95. package/dist/modules/devices/api/[id]/route.js.map +7 -0
  96. package/dist/modules/devices/api/admin/devices/[id]/route.js +219 -0
  97. package/dist/modules/devices/api/admin/devices/[id]/route.js.map +7 -0
  98. package/dist/modules/devices/api/admin/devices/route.js +140 -0
  99. package/dist/modules/devices/api/admin/devices/route.js.map +7 -0
  100. package/dist/modules/devices/api/auth.js +9 -0
  101. package/dist/modules/devices/api/auth.js.map +7 -0
  102. package/dist/modules/devices/api/deviceList.js +53 -0
  103. package/dist/modules/devices/api/deviceList.js.map +7 -0
  104. package/dist/modules/devices/api/deviceOps.js +118 -0
  105. package/dist/modules/devices/api/deviceOps.js.map +7 -0
  106. package/dist/modules/devices/api/openapi.js +19 -0
  107. package/dist/modules/devices/api/openapi.js.map +7 -0
  108. package/dist/modules/devices/api/route.js +143 -0
  109. package/dist/modules/devices/api/route.js.map +7 -0
  110. package/dist/modules/devices/backend/devices/[id]/page.js +135 -0
  111. package/dist/modules/devices/backend/devices/[id]/page.js.map +7 -0
  112. package/dist/modules/devices/backend/devices/[id]/page.meta.js +16 -0
  113. package/dist/modules/devices/backend/devices/[id]/page.meta.js.map +7 -0
  114. package/dist/modules/devices/backend/devices/create/page.js +68 -0
  115. package/dist/modules/devices/backend/devices/create/page.js.map +7 -0
  116. package/dist/modules/devices/backend/devices/create/page.meta.js +16 -0
  117. package/dist/modules/devices/backend/devices/create/page.meta.js.map +7 -0
  118. package/dist/modules/devices/backend/devices/page.js +235 -0
  119. package/dist/modules/devices/backend/devices/page.js.map +7 -0
  120. package/dist/modules/devices/backend/devices/page.meta.js +23 -0
  121. package/dist/modules/devices/backend/devices/page.meta.js.map +7 -0
  122. package/dist/modules/devices/commands/deactivate.js +107 -0
  123. package/dist/modules/devices/commands/deactivate.js.map +7 -0
  124. package/dist/modules/devices/commands/index.js +4 -0
  125. package/dist/modules/devices/commands/index.js.map +7 -0
  126. package/dist/modules/devices/commands/register.js +183 -0
  127. package/dist/modules/devices/commands/register.js.map +7 -0
  128. package/dist/modules/devices/commands/shared.js +74 -0
  129. package/dist/modules/devices/commands/shared.js.map +7 -0
  130. package/dist/modules/devices/commands/update.js +126 -0
  131. package/dist/modules/devices/commands/update.js.map +7 -0
  132. package/dist/modules/devices/data/entities.js +83 -0
  133. package/dist/modules/devices/data/entities.js.map +7 -0
  134. package/dist/modules/devices/data/validators.js +49 -0
  135. package/dist/modules/devices/data/validators.js.map +7 -0
  136. package/dist/modules/devices/di.js +11 -0
  137. package/dist/modules/devices/di.js.map +7 -0
  138. package/dist/modules/devices/encryption.js +12 -0
  139. package/dist/modules/devices/encryption.js.map +7 -0
  140. package/dist/modules/devices/events.js +19 -0
  141. package/dist/modules/devices/events.js.map +7 -0
  142. package/dist/modules/devices/index.js +17 -0
  143. package/dist/modules/devices/index.js.map +7 -0
  144. package/dist/modules/devices/lib/operationMetadata.js +20 -0
  145. package/dist/modules/devices/lib/operationMetadata.js.map +7 -0
  146. package/dist/modules/devices/migrations/Migration20260602120000.js +15 -0
  147. package/dist/modules/devices/migrations/Migration20260602120000.js.map +7 -0
  148. package/dist/modules/devices/migrations/Migration20260630120000.js +15 -0
  149. package/dist/modules/devices/migrations/Migration20260630120000.js.map +7 -0
  150. package/dist/modules/devices/migrations/Migration20260701120000.js +13 -0
  151. package/dist/modules/devices/migrations/Migration20260701120000.js.map +7 -0
  152. package/dist/modules/devices/migrations/Migration20260721120000.js +15 -0
  153. package/dist/modules/devices/migrations/Migration20260721120000.js.map +7 -0
  154. package/dist/modules/devices/setup.js +13 -0
  155. package/dist/modules/devices/setup.js.map +7 -0
  156. package/dist/modules/entities/cli.js +8 -3
  157. package/dist/modules/entities/cli.js.map +2 -2
  158. package/dist/modules/entities/migrations/Migration20260722120000.js +28 -0
  159. package/dist/modules/entities/migrations/Migration20260722120000.js.map +7 -0
  160. package/dist/modules/inbox_ops/notifications.js +2 -0
  161. package/dist/modules/inbox_ops/notifications.js.map +2 -2
  162. package/dist/modules/messages/notifications.js +2 -0
  163. package/dist/modules/messages/notifications.js.map +2 -2
  164. package/dist/modules/notifications/acl.js +3 -1
  165. package/dist/modules/notifications/acl.js.map +2 -2
  166. package/dist/modules/notifications/api/admin/preferences/route.js +167 -0
  167. package/dist/modules/notifications/api/admin/preferences/route.js.map +7 -0
  168. package/dist/modules/notifications/api/channels/route.js +54 -0
  169. package/dist/modules/notifications/api/channels/route.js.map +7 -0
  170. package/dist/modules/notifications/api/preferences/route.js +126 -0
  171. package/dist/modules/notifications/api/preferences/route.js.map +7 -0
  172. package/dist/modules/notifications/api/route.js +8 -1
  173. package/dist/modules/notifications/api/route.js.map +2 -2
  174. package/dist/modules/notifications/api/types/[id]/channels/[channel]/route.js +187 -0
  175. package/dist/modules/notifications/api/types/[id]/channels/[channel]/route.js.map +7 -0
  176. package/dist/modules/notifications/api/types/route.js +225 -0
  177. package/dist/modules/notifications/api/types/route.js.map +7 -0
  178. package/dist/modules/notifications/api/unread-count/route.js +5 -1
  179. package/dist/modules/notifications/api/unread-count/route.js.map +2 -2
  180. package/dist/modules/notifications/backend/notifications/user-preferences/page.js +10 -0
  181. package/dist/modules/notifications/backend/notifications/user-preferences/page.js.map +7 -0
  182. package/dist/modules/notifications/backend/notifications/user-preferences/page.meta.js +28 -0
  183. package/dist/modules/notifications/backend/notifications/user-preferences/page.meta.js.map +7 -0
  184. package/dist/modules/notifications/backend/profile/notification-preferences/page.js +10 -0
  185. package/dist/modules/notifications/backend/profile/notification-preferences/page.js.map +7 -0
  186. package/dist/modules/notifications/backend/profile/notification-preferences/page.meta.js +33 -0
  187. package/dist/modules/notifications/backend/profile/notification-preferences/page.meta.js.map +7 -0
  188. package/dist/modules/notifications/data/entities.js +128 -1
  189. package/dist/modules/notifications/data/entities.js.map +2 -2
  190. package/dist/modules/notifications/data/validators.js +95 -2
  191. package/dist/modules/notifications/data/validators.js.map +2 -2
  192. package/dist/modules/notifications/di.js +7 -0
  193. package/dist/modules/notifications/di.js.map +2 -2
  194. package/dist/modules/notifications/events.js +17 -0
  195. package/dist/modules/notifications/events.js.map +2 -2
  196. package/dist/modules/notifications/frontend/NotificationPreferenceMatrix.js +190 -0
  197. package/dist/modules/notifications/frontend/NotificationPreferenceMatrix.js.map +7 -0
  198. package/dist/modules/notifications/frontend/NotificationPreferencesPageClient.js +124 -0
  199. package/dist/modules/notifications/frontend/NotificationPreferencesPageClient.js.map +7 -0
  200. package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js +166 -1
  201. package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js.map +2 -2
  202. package/dist/modules/notifications/frontend/NotificationUserPreferencesAdminPageClient.js +172 -0
  203. package/dist/modules/notifications/frontend/NotificationUserPreferencesAdminPageClient.js.map +7 -0
  204. package/dist/modules/notifications/generators.js +63 -0
  205. package/dist/modules/notifications/generators.js.map +7 -0
  206. package/dist/modules/notifications/lib/delivery-strategies-registry.js +19 -0
  207. package/dist/modules/notifications/lib/delivery-strategies-registry.js.map +7 -0
  208. package/dist/modules/notifications/lib/deliveryStrategies.js.map +2 -2
  209. package/dist/modules/notifications/lib/derive-category.js +8 -0
  210. package/dist/modules/notifications/lib/derive-category.js.map +7 -0
  211. package/dist/modules/notifications/lib/notification-channel-registry.js +35 -0
  212. package/dist/modules/notifications/lib/notification-channel-registry.js.map +7 -0
  213. package/dist/modules/notifications/lib/notification-type-registry.js +87 -0
  214. package/dist/modules/notifications/lib/notification-type-registry.js.map +7 -0
  215. package/dist/modules/notifications/lib/notificationCopy.js +14 -0
  216. package/dist/modules/notifications/lib/notificationCopy.js.map +7 -0
  217. package/dist/modules/notifications/lib/notificationFactory.js +4 -1
  218. package/dist/modules/notifications/lib/notificationFactory.js.map +2 -2
  219. package/dist/modules/notifications/lib/notificationMapper.js +2 -0
  220. package/dist/modules/notifications/lib/notificationMapper.js.map +2 -2
  221. package/dist/modules/notifications/lib/notificationPreferenceService.js +83 -0
  222. package/dist/modules/notifications/lib/notificationPreferenceService.js.map +7 -0
  223. package/dist/modules/notifications/lib/notificationService.js +83 -28
  224. package/dist/modules/notifications/lib/notificationService.js.map +2 -2
  225. package/dist/modules/notifications/lib/notificationVisibility.js +24 -0
  226. package/dist/modules/notifications/lib/notificationVisibility.js.map +7 -0
  227. package/dist/modules/notifications/lib/routeHelpers.js +11 -1
  228. package/dist/modules/notifications/lib/routeHelpers.js.map +2 -2
  229. package/dist/modules/notifications/lib/shouldDeliver.js +46 -0
  230. package/dist/modules/notifications/lib/shouldDeliver.js.map +7 -0
  231. package/dist/modules/notifications/lib/strategies/email-delivery-strategy.js +54 -0
  232. package/dist/modules/notifications/lib/strategies/email-delivery-strategy.js.map +7 -0
  233. package/dist/modules/notifications/lib/strategies/in-app-delivery-strategy.js +12 -0
  234. package/dist/modules/notifications/lib/strategies/in-app-delivery-strategy.js.map +7 -0
  235. package/dist/modules/notifications/lib/typeCatalogue.js +71 -0
  236. package/dist/modules/notifications/lib/typeCatalogue.js.map +7 -0
  237. package/dist/modules/notifications/lib/typeChannelSettings.js +12 -0
  238. package/dist/modules/notifications/lib/typeChannelSettings.js.map +7 -0
  239. package/dist/modules/notifications/lib/typeOverrides.js +19 -0
  240. package/dist/modules/notifications/lib/typeOverrides.js.map +7 -0
  241. package/dist/modules/notifications/migrations/Migration20260625122947_notifications.js +14 -0
  242. package/dist/modules/notifications/migrations/Migration20260625122947_notifications.js.map +7 -0
  243. package/dist/modules/notifications/migrations/Migration20260626120500_notifications_push_payload.js +15 -0
  244. package/dist/modules/notifications/migrations/Migration20260626120500_notifications_push_payload.js.map +7 -0
  245. package/dist/modules/notifications/migrations/Migration20260626130000_notifications_non_opt_out.js +13 -0
  246. package/dist/modules/notifications/migrations/Migration20260626130000_notifications_non_opt_out.js.map +7 -0
  247. package/dist/modules/notifications/migrations/Migration20260626140000_notifications_type_category_silent.js +15 -0
  248. package/dist/modules/notifications/migrations/Migration20260626140000_notifications_type_category_silent.js.map +7 -0
  249. package/dist/modules/notifications/migrations/Migration20260706120000_notifications_channels.js +13 -0
  250. package/dist/modules/notifications/migrations/Migration20260706120000_notifications_channels.js.map +7 -0
  251. package/dist/modules/notifications/migrations/Migration20260716123121_notifications.js +14 -0
  252. package/dist/modules/notifications/migrations/Migration20260716123121_notifications.js.map +7 -0
  253. package/dist/modules/notifications/notification-channels.js +26 -0
  254. package/dist/modules/notifications/notification-channels.js.map +7 -0
  255. package/dist/modules/notifications/notifications.delivery-strategies.js +12 -0
  256. package/dist/modules/notifications/notifications.delivery-strategies.js.map +7 -0
  257. package/dist/modules/notifications/setup.js +16 -1
  258. package/dist/modules/notifications/setup.js.map +2 -2
  259. package/dist/modules/notifications/subscribers/deliver-notification.js +66 -57
  260. package/dist/modules/notifications/subscribers/deliver-notification.js.map +2 -2
  261. package/dist/modules/notifications/subscribers/sync-notification-types.js +16 -0
  262. package/dist/modules/notifications/subscribers/sync-notification-types.js.map +7 -0
  263. package/dist/modules/notifications/widgets/injection/profile-preferences-menu/widget.js +23 -0
  264. package/dist/modules/notifications/widgets/injection/profile-preferences-menu/widget.js.map +7 -0
  265. package/dist/modules/notifications/widgets/injection-table.js +14 -0
  266. package/dist/modules/notifications/widgets/injection-table.js.map +7 -0
  267. package/dist/modules/push_notifications/acl.js +13 -0
  268. package/dist/modules/push_notifications/acl.js.map +7 -0
  269. package/dist/modules/push_notifications/api/custom-send/route.js +141 -0
  270. package/dist/modules/push_notifications/api/custom-send/route.js.map +7 -0
  271. package/dist/modules/push_notifications/api/deliveries/[id]/route.js +110 -0
  272. package/dist/modules/push_notifications/api/deliveries/[id]/route.js.map +7 -0
  273. package/dist/modules/push_notifications/api/deliveries/route.js +56 -0
  274. package/dist/modules/push_notifications/api/deliveries/route.js.map +7 -0
  275. package/dist/modules/push_notifications/api/openapi.js +19 -0
  276. package/dist/modules/push_notifications/api/openapi.js.map +7 -0
  277. package/dist/modules/push_notifications/backend/push_notifications/[id]/page.js +103 -0
  278. package/dist/modules/push_notifications/backend/push_notifications/[id]/page.js.map +7 -0
  279. package/dist/modules/push_notifications/backend/push_notifications/[id]/page.meta.js +13 -0
  280. package/dist/modules/push_notifications/backend/push_notifications/[id]/page.meta.js.map +7 -0
  281. package/dist/modules/push_notifications/backend/push_notifications/page.js +213 -0
  282. package/dist/modules/push_notifications/backend/push_notifications/page.js.map +7 -0
  283. package/dist/modules/push_notifications/backend/push_notifications/page.meta.js +23 -0
  284. package/dist/modules/push_notifications/backend/push_notifications/page.meta.js.map +7 -0
  285. package/dist/modules/push_notifications/backend/push_notifications/send/page.js +245 -0
  286. package/dist/modules/push_notifications/backend/push_notifications/send/page.js.map +7 -0
  287. package/dist/modules/push_notifications/backend/push_notifications/send/page.meta.js +26 -0
  288. package/dist/modules/push_notifications/backend/push_notifications/send/page.meta.js.map +7 -0
  289. package/dist/modules/push_notifications/data/entities.js +92 -0
  290. package/dist/modules/push_notifications/data/entities.js.map +7 -0
  291. package/dist/modules/push_notifications/data/extensions.js +23 -0
  292. package/dist/modules/push_notifications/data/extensions.js.map +7 -0
  293. package/dist/modules/push_notifications/data/validators.js +89 -0
  294. package/dist/modules/push_notifications/data/validators.js.map +7 -0
  295. package/dist/modules/push_notifications/di.js +17 -0
  296. package/dist/modules/push_notifications/di.js.map +7 -0
  297. package/dist/modules/push_notifications/events.js +24 -0
  298. package/dist/modules/push_notifications/events.js.map +7 -0
  299. package/dist/modules/push_notifications/index.js +16 -0
  300. package/dist/modules/push_notifications/index.js.map +7 -0
  301. package/dist/modules/push_notifications/lib/fake-provider-recorder.js +80 -0
  302. package/dist/modules/push_notifications/lib/fake-provider-recorder.js.map +7 -0
  303. package/dist/modules/push_notifications/lib/push-delivery-strategy.js +54 -0
  304. package/dist/modules/push_notifications/lib/push-delivery-strategy.js.map +7 -0
  305. package/dist/modules/push_notifications/lib/push-delivery.js +297 -0
  306. package/dist/modules/push_notifications/lib/push-delivery.js.map +7 -0
  307. package/dist/modules/push_notifications/lib/push-fanout.js +138 -0
  308. package/dist/modules/push_notifications/lib/push-fanout.js.map +7 -0
  309. package/dist/modules/push_notifications/lib/push-health.js +32 -0
  310. package/dist/modules/push_notifications/lib/push-health.js.map +7 -0
  311. package/dist/modules/push_notifications/lib/push-reaper.js +87 -0
  312. package/dist/modules/push_notifications/lib/push-reaper.js.map +7 -0
  313. package/dist/modules/push_notifications/lib/push-receipt-reaper.js +136 -0
  314. package/dist/modules/push_notifications/lib/push-receipt-reaper.js.map +7 -0
  315. package/dist/modules/push_notifications/lib/push-stub-adapter.js +63 -0
  316. package/dist/modules/push_notifications/lib/push-stub-adapter.js.map +7 -0
  317. package/dist/modules/push_notifications/lib/queue.js +53 -0
  318. package/dist/modules/push_notifications/lib/queue.js.map +7 -0
  319. package/dist/modules/push_notifications/lib/reclaim-window.js +13 -0
  320. package/dist/modules/push_notifications/lib/reclaim-window.js.map +7 -0
  321. package/dist/modules/push_notifications/lib/send-custom-push.js +48 -0
  322. package/dist/modules/push_notifications/lib/send-custom-push.js.map +7 -0
  323. package/dist/modules/push_notifications/migrations/Migration20260625150049_push_notifications.js +16 -0
  324. package/dist/modules/push_notifications/migrations/Migration20260625150049_push_notifications.js.map +7 -0
  325. package/dist/modules/push_notifications/migrations/Migration20260626120000_push_notifications_silent.js +13 -0
  326. package/dist/modules/push_notifications/migrations/Migration20260626120000_push_notifications_silent.js.map +7 -0
  327. package/dist/modules/push_notifications/notifications.delivery-strategies.js +8 -0
  328. package/dist/modules/push_notifications/notifications.delivery-strategies.js.map +7 -0
  329. package/dist/modules/push_notifications/notifications.js +40 -0
  330. package/dist/modules/push_notifications/notifications.js.map +7 -0
  331. package/dist/modules/push_notifications/setup.js +52 -0
  332. package/dist/modules/push_notifications/setup.js.map +7 -0
  333. package/dist/modules/push_notifications/workers/reclaim-stuck.worker.js +57 -0
  334. package/dist/modules/push_notifications/workers/reclaim-stuck.worker.js.map +7 -0
  335. package/dist/modules/push_notifications/workers/send-push.worker.js +27 -0
  336. package/dist/modules/push_notifications/workers/send-push.worker.js.map +7 -0
  337. package/dist/modules/sales/notifications.js +8 -0
  338. package/dist/modules/sales/notifications.js.map +2 -2
  339. package/dist/modules/staff/notifications.js +6 -0
  340. package/dist/modules/staff/notifications.js.map +2 -2
  341. package/dist/modules/workflows/notifications.js +2 -0
  342. package/dist/modules/workflows/notifications.js.map +2 -2
  343. package/generated/entities/notification/index.ts +3 -0
  344. package/generated/entities/notification_preference/index.ts +8 -0
  345. package/generated/entities/notification_type/index.ts +9 -0
  346. package/generated/entities/notification_type_override/index.ts +7 -0
  347. package/generated/entities/push_notification_delivery/index.ts +19 -0
  348. package/generated/entities/user_device/index.ts +16 -0
  349. package/generated/entities.ids.generated.ts +12 -1
  350. package/generated/entity-fields-registry.ts +72 -0
  351. package/package.json +7 -7
  352. package/src/helpers/integration/api.ts +2 -1
  353. package/src/helpers/integration/appRoot.ts +13 -0
  354. package/src/helpers/integration/dbFixtures.ts +1 -5
  355. package/src/helpers/integration/pushFake.ts +219 -0
  356. package/src/modules/auth/i18n/de.json +1 -0
  357. package/src/modules/auth/i18n/en.json +1 -0
  358. package/src/modules/auth/i18n/es.json +1 -0
  359. package/src/modules/auth/i18n/ko.json +1 -0
  360. package/src/modules/auth/i18n/pl.json +1 -0
  361. package/src/modules/auth/notifications.ts +16 -0
  362. package/src/modules/business_rules/i18n/de.json +2 -1
  363. package/src/modules/business_rules/i18n/en.json +2 -1
  364. package/src/modules/business_rules/i18n/es.json +2 -1
  365. package/src/modules/business_rules/i18n/ko.json +2 -1
  366. package/src/modules/business_rules/i18n/pl.json +2 -1
  367. package/src/modules/business_rules/notifications.ts +2 -0
  368. package/src/modules/catalog/i18n/de.json +2 -1
  369. package/src/modules/catalog/i18n/en.json +2 -1
  370. package/src/modules/catalog/i18n/es.json +2 -1
  371. package/src/modules/catalog/i18n/ko.json +2 -1
  372. package/src/modules/catalog/i18n/pl.json +2 -1
  373. package/src/modules/catalog/notifications.ts +2 -0
  374. package/src/modules/communication_channels/acl.ts +9 -0
  375. package/src/modules/communication_channels/api/delete/admin/channels/[id]/route.ts +168 -0
  376. package/src/modules/communication_channels/api/get/channels/[id]/health/route.ts +6 -2
  377. package/src/modules/communication_channels/api/get/channels/[id]/route.ts +6 -2
  378. package/src/modules/communication_channels/api/get/channels/route.ts +2 -1
  379. package/src/modules/communication_channels/api/post/channels/[id]/test-send/route.ts +16 -5
  380. package/src/modules/communication_channels/api/post/channels/connect/credentials/route.ts +37 -1
  381. package/src/modules/communication_channels/api/post/channels/connect/tenant-credentials/route.ts +175 -0
  382. package/src/modules/communication_channels/backend/communication_channels/channels/page.tsx +11 -1
  383. package/src/modules/communication_channels/commands/admin-delete-channel.ts +203 -0
  384. package/src/modules/communication_channels/commands/connect-credential-channel.ts +63 -15
  385. package/src/modules/communication_channels/commands/deliver-outbound-message.ts +10 -2
  386. package/src/modules/communication_channels/commands/push-register.ts +7 -1
  387. package/src/modules/communication_channels/commands/push-unregister.ts +14 -3
  388. package/src/modules/communication_channels/data/entities.ts +10 -0
  389. package/src/modules/communication_channels/data/validators.ts +1 -0
  390. package/src/modules/communication_channels/i18n/de.json +35 -1
  391. package/src/modules/communication_channels/i18n/en.json +35 -1
  392. package/src/modules/communication_channels/i18n/es.json +35 -1
  393. package/src/modules/communication_channels/i18n/ko.json +35 -1
  394. package/src/modules/communication_channels/i18n/pl.json +35 -1
  395. package/src/modules/communication_channels/lib/access-control.ts +42 -0
  396. package/src/modules/communication_channels/lib/adapter.ts +25 -0
  397. package/src/modules/communication_channels/lib/connect-channel.ts +61 -26
  398. package/src/modules/communication_channels/lib/push-adapter.ts +139 -0
  399. package/src/modules/communication_channels/lib/push-capabilities.ts +42 -0
  400. package/src/modules/communication_channels/lib/push-connect-error.ts +52 -0
  401. package/src/modules/communication_channels/lib/push-credential-errors.ts +58 -0
  402. package/src/modules/communication_channels/lib/push-envelope.ts +104 -0
  403. package/src/modules/communication_channels/lib/refcounted-client-cache.ts +123 -0
  404. package/src/modules/communication_channels/migrations/.snapshot-open-mercato.json +9 -0
  405. package/src/modules/communication_channels/migrations/Migration20260703123630_communication_channels.ts +20 -0
  406. package/src/modules/communication_channels/notifications.ts +4 -0
  407. package/src/modules/communication_channels/setup.ts +2 -0
  408. package/src/modules/configs/i18n/de.json +5 -1
  409. package/src/modules/configs/i18n/en.json +5 -1
  410. package/src/modules/configs/i18n/es.json +5 -1
  411. package/src/modules/configs/i18n/ko.json +5 -1
  412. package/src/modules/configs/i18n/pl.json +5 -1
  413. package/src/modules/configs/lib/upgrade-actions.ts +21 -0
  414. package/src/modules/customer_accounts/i18n/de.json +2 -1
  415. package/src/modules/customer_accounts/i18n/en.json +2 -1
  416. package/src/modules/customer_accounts/i18n/es.json +2 -1
  417. package/src/modules/customer_accounts/i18n/ko.json +2 -1
  418. package/src/modules/customer_accounts/i18n/pl.json +2 -1
  419. package/src/modules/customer_accounts/notifications.ts +12 -0
  420. package/src/modules/customers/i18n/de.json +2 -1
  421. package/src/modules/customers/i18n/en.json +2 -1
  422. package/src/modules/customers/i18n/es.json +2 -1
  423. package/src/modules/customers/i18n/ko.json +2 -1
  424. package/src/modules/customers/i18n/pl.json +2 -1
  425. package/src/modules/customers/notifications.ts +4 -0
  426. package/src/modules/devices/AGENTS.md +101 -0
  427. package/src/modules/devices/acl.ts +7 -0
  428. package/src/modules/devices/api/[id]/route.ts +180 -0
  429. package/src/modules/devices/api/admin/devices/[id]/route.ts +235 -0
  430. package/src/modules/devices/api/admin/devices/route.ts +160 -0
  431. package/src/modules/devices/api/auth.ts +13 -0
  432. package/src/modules/devices/api/deviceList.ts +54 -0
  433. package/src/modules/devices/api/deviceOps.ts +186 -0
  434. package/src/modules/devices/api/openapi.ts +23 -0
  435. package/src/modules/devices/api/route.ts +165 -0
  436. package/src/modules/devices/backend/devices/[id]/page.meta.ts +12 -0
  437. package/src/modules/devices/backend/devices/[id]/page.tsx +164 -0
  438. package/src/modules/devices/backend/devices/create/page.meta.ts +12 -0
  439. package/src/modules/devices/backend/devices/create/page.tsx +81 -0
  440. package/src/modules/devices/backend/devices/page.meta.ts +21 -0
  441. package/src/modules/devices/backend/devices/page.tsx +259 -0
  442. package/src/modules/devices/commands/deactivate.ts +126 -0
  443. package/src/modules/devices/commands/index.ts +3 -0
  444. package/src/modules/devices/commands/register.ts +199 -0
  445. package/src/modules/devices/commands/shared.ts +119 -0
  446. package/src/modules/devices/commands/update.ts +142 -0
  447. package/src/modules/devices/data/entities.ts +79 -0
  448. package/src/modules/devices/data/validators.ts +65 -0
  449. package/src/modules/devices/di.ts +9 -0
  450. package/src/modules/devices/encryption.ts +15 -0
  451. package/src/modules/devices/events.ts +16 -0
  452. package/src/modules/devices/i18n/de.json +45 -0
  453. package/src/modules/devices/i18n/en.json +45 -0
  454. package/src/modules/devices/i18n/es.json +45 -0
  455. package/src/modules/devices/i18n/ko.json +45 -0
  456. package/src/modules/devices/i18n/pl.json +45 -0
  457. package/src/modules/devices/index.ts +15 -0
  458. package/src/modules/devices/lib/operationMetadata.ts +35 -0
  459. package/src/modules/devices/migrations/.snapshot-open-mercato.json +200 -0
  460. package/src/modules/devices/migrations/Migration20260602120000.ts +15 -0
  461. package/src/modules/devices/migrations/Migration20260630120000.ts +20 -0
  462. package/src/modules/devices/migrations/Migration20260701120000.ts +13 -0
  463. package/src/modules/devices/migrations/Migration20260721120000.ts +18 -0
  464. package/src/modules/devices/setup.ts +11 -0
  465. package/src/modules/entities/cli.ts +16 -2
  466. package/src/modules/entities/migrations/Migration20260722120000.ts +38 -0
  467. package/src/modules/inbox_ops/i18n/de.json +2 -1
  468. package/src/modules/inbox_ops/i18n/en.json +2 -1
  469. package/src/modules/inbox_ops/i18n/es.json +2 -1
  470. package/src/modules/inbox_ops/i18n/ko.json +2 -1
  471. package/src/modules/inbox_ops/i18n/pl.json +2 -1
  472. package/src/modules/inbox_ops/notifications.ts +2 -0
  473. package/src/modules/messages/i18n/de.json +2 -1
  474. package/src/modules/messages/i18n/en.json +2 -1
  475. package/src/modules/messages/i18n/es.json +2 -1
  476. package/src/modules/messages/i18n/ko.json +2 -1
  477. package/src/modules/messages/i18n/pl.json +2 -1
  478. package/src/modules/messages/notifications.ts +2 -0
  479. package/src/modules/notifications/AGENTS.md +54 -0
  480. package/src/modules/notifications/acl.ts +2 -0
  481. package/src/modules/notifications/api/admin/preferences/route.ts +193 -0
  482. package/src/modules/notifications/api/channels/route.ts +54 -0
  483. package/src/modules/notifications/api/preferences/route.ts +131 -0
  484. package/src/modules/notifications/api/route.ts +8 -1
  485. package/src/modules/notifications/api/types/[id]/channels/[channel]/route.ts +226 -0
  486. package/src/modules/notifications/api/types/route.ts +239 -0
  487. package/src/modules/notifications/api/unread-count/route.ts +5 -1
  488. package/src/modules/notifications/backend/notifications/user-preferences/page.meta.ts +26 -0
  489. package/src/modules/notifications/backend/notifications/user-preferences/page.tsx +12 -0
  490. package/src/modules/notifications/backend/profile/notification-preferences/page.meta.ts +31 -0
  491. package/src/modules/notifications/backend/profile/notification-preferences/page.tsx +12 -0
  492. package/src/modules/notifications/data/entities.ts +144 -0
  493. package/src/modules/notifications/data/validators.ts +116 -0
  494. package/src/modules/notifications/di.ts +7 -0
  495. package/src/modules/notifications/events.ts +23 -0
  496. package/src/modules/notifications/frontend/NotificationPreferenceMatrix.tsx +287 -0
  497. package/src/modules/notifications/frontend/NotificationPreferencesPageClient.tsx +155 -0
  498. package/src/modules/notifications/frontend/NotificationSettingsPageClient.tsx +273 -2
  499. package/src/modules/notifications/frontend/NotificationUserPreferencesAdminPageClient.tsx +214 -0
  500. package/src/modules/notifications/generators.ts +82 -0
  501. package/src/modules/notifications/i18n/de.json +43 -0
  502. package/src/modules/notifications/i18n/en.json +43 -0
  503. package/src/modules/notifications/i18n/es.json +43 -0
  504. package/src/modules/notifications/i18n/ko.json +43 -0
  505. package/src/modules/notifications/i18n/pl.json +44 -1
  506. package/src/modules/notifications/lib/delivery-strategies-registry.ts +30 -0
  507. package/src/modules/notifications/lib/deliveryStrategies.ts +40 -4
  508. package/src/modules/notifications/lib/derive-category.ts +15 -0
  509. package/src/modules/notifications/lib/notification-channel-registry.ts +59 -0
  510. package/src/modules/notifications/lib/notification-type-registry.ts +182 -0
  511. package/src/modules/notifications/lib/notificationCopy.ts +34 -0
  512. package/src/modules/notifications/lib/notificationFactory.ts +5 -1
  513. package/src/modules/notifications/lib/notificationMapper.ts +2 -0
  514. package/src/modules/notifications/lib/notificationPreferenceService.ts +138 -0
  515. package/src/modules/notifications/lib/notificationService.ts +129 -25
  516. package/src/modules/notifications/lib/notificationVisibility.ts +48 -0
  517. package/src/modules/notifications/lib/routeHelpers.ts +14 -1
  518. package/src/modules/notifications/lib/shouldDeliver.ts +112 -0
  519. package/src/modules/notifications/lib/strategies/email-delivery-strategy.ts +63 -0
  520. package/src/modules/notifications/lib/strategies/in-app-delivery-strategy.ts +21 -0
  521. package/src/modules/notifications/lib/typeCatalogue.ts +141 -0
  522. package/src/modules/notifications/lib/typeChannelSettings.ts +29 -0
  523. package/src/modules/notifications/lib/typeOverrides.ts +46 -0
  524. package/src/modules/notifications/migrations/.snapshot-open-mercato.json +874 -100
  525. package/src/modules/notifications/migrations/Migration20260625122947_notifications.ts +14 -0
  526. package/src/modules/notifications/migrations/Migration20260626120500_notifications_push_payload.ts +15 -0
  527. package/src/modules/notifications/migrations/Migration20260626130000_notifications_non_opt_out.ts +13 -0
  528. package/src/modules/notifications/migrations/Migration20260626140000_notifications_type_category_silent.ts +15 -0
  529. package/src/modules/notifications/migrations/Migration20260706120000_notifications_channels.ts +13 -0
  530. package/src/modules/notifications/migrations/Migration20260716123121_notifications.ts +14 -0
  531. package/src/modules/notifications/notification-channels.ts +30 -0
  532. package/src/modules/notifications/notifications.delivery-strategies.ts +15 -0
  533. package/src/modules/notifications/setup.ts +23 -1
  534. package/src/modules/notifications/subscribers/deliver-notification.ts +105 -71
  535. package/src/modules/notifications/subscribers/sync-notification-types.ts +18 -0
  536. package/src/modules/notifications/widgets/injection/profile-preferences-menu/widget.ts +35 -0
  537. package/src/modules/notifications/widgets/injection-table.ts +18 -0
  538. package/src/modules/push_notifications/AGENTS.md +92 -0
  539. package/src/modules/push_notifications/acl.ts +9 -0
  540. package/src/modules/push_notifications/api/custom-send/route.ts +175 -0
  541. package/src/modules/push_notifications/api/deliveries/[id]/route.ts +122 -0
  542. package/src/modules/push_notifications/api/deliveries/route.ts +58 -0
  543. package/src/modules/push_notifications/api/openapi.ts +22 -0
  544. package/src/modules/push_notifications/backend/push_notifications/[id]/page.meta.ts +9 -0
  545. package/src/modules/push_notifications/backend/push_notifications/[id]/page.tsx +149 -0
  546. package/src/modules/push_notifications/backend/push_notifications/page.meta.ts +21 -0
  547. package/src/modules/push_notifications/backend/push_notifications/page.tsx +239 -0
  548. package/src/modules/push_notifications/backend/push_notifications/send/page.meta.ts +24 -0
  549. package/src/modules/push_notifications/backend/push_notifications/send/page.tsx +327 -0
  550. package/src/modules/push_notifications/data/entities.ts +111 -0
  551. package/src/modules/push_notifications/data/extensions.ts +29 -0
  552. package/src/modules/push_notifications/data/validators.ts +102 -0
  553. package/src/modules/push_notifications/di.ts +20 -0
  554. package/src/modules/push_notifications/events.ts +21 -0
  555. package/src/modules/push_notifications/i18n/de.json +79 -0
  556. package/src/modules/push_notifications/i18n/en.json +79 -0
  557. package/src/modules/push_notifications/i18n/es.json +79 -0
  558. package/src/modules/push_notifications/i18n/ko.json +79 -0
  559. package/src/modules/push_notifications/i18n/pl.json +79 -0
  560. package/src/modules/push_notifications/index.ts +15 -0
  561. package/src/modules/push_notifications/lib/fake-provider-recorder.ts +154 -0
  562. package/src/modules/push_notifications/lib/push-delivery-strategy.ts +90 -0
  563. package/src/modules/push_notifications/lib/push-delivery.ts +455 -0
  564. package/src/modules/push_notifications/lib/push-fanout.ts +237 -0
  565. package/src/modules/push_notifications/lib/push-health.ts +47 -0
  566. package/src/modules/push_notifications/lib/push-reaper.ts +140 -0
  567. package/src/modules/push_notifications/lib/push-receipt-reaper.ts +210 -0
  568. package/src/modules/push_notifications/lib/push-stub-adapter.ts +80 -0
  569. package/src/modules/push_notifications/lib/queue.ts +74 -0
  570. package/src/modules/push_notifications/lib/reclaim-window.ts +16 -0
  571. package/src/modules/push_notifications/lib/send-custom-push.ts +100 -0
  572. package/src/modules/push_notifications/migrations/.snapshot-open-mercato.json +386 -0
  573. package/src/modules/push_notifications/migrations/Migration20260625150049_push_notifications.ts +16 -0
  574. package/src/modules/push_notifications/migrations/Migration20260626120000_push_notifications_silent.ts +13 -0
  575. package/src/modules/push_notifications/notifications.delivery-strategies.ts +8 -0
  576. package/src/modules/push_notifications/notifications.ts +50 -0
  577. package/src/modules/push_notifications/setup.ts +92 -0
  578. package/src/modules/push_notifications/workers/reclaim-stuck.worker.ts +78 -0
  579. package/src/modules/push_notifications/workers/send-push.worker.ts +34 -0
  580. package/src/modules/sales/i18n/de.json +1 -0
  581. package/src/modules/sales/i18n/en.json +1 -0
  582. package/src/modules/sales/i18n/es.json +1 -0
  583. package/src/modules/sales/i18n/ko.json +1 -0
  584. package/src/modules/sales/i18n/pl.json +1 -0
  585. package/src/modules/sales/notifications.ts +8 -0
  586. package/src/modules/staff/i18n/de.json +1 -0
  587. package/src/modules/staff/i18n/en.json +1 -0
  588. package/src/modules/staff/i18n/es.json +1 -0
  589. package/src/modules/staff/i18n/ko.json +1 -0
  590. package/src/modules/staff/i18n/pl.json +1 -0
  591. package/src/modules/staff/notifications.ts +6 -0
  592. package/src/modules/workflows/i18n/de.json +1 -0
  593. package/src/modules/workflows/i18n/en.json +1 -0
  594. package/src/modules/workflows/i18n/es.json +1 -0
  595. package/src/modules/workflows/i18n/ko.json +1 -0
  596. package/src/modules/workflows/i18n/pl.json +1 -0
  597. package/src/modules/workflows/notifications.ts +2 -0
@@ -1,6 +1,8 @@
1
1
  const notificationTypes = [
2
2
  {
3
3
  type: "communication_channels.message.received",
4
+ // Ships without push — operators re-enable it per type from the Notification Delivery settings.
5
+ channels: ["in_app", "email"],
4
6
  module: "communication_channels",
5
7
  titleKey: "communication_channels.notifications.message_received.title",
6
8
  bodyKey: "communication_channels.notifications.message_received.body",
@@ -29,6 +31,8 @@ const notificationTypes = [
29
31
  * integration spec's reconnect flow.
30
32
  */
31
33
  type: "communication_channels.channel.requires_reauth",
34
+ // Ships without push — operators re-enable it per type from the Notification Delivery settings.
35
+ channels: ["in_app", "email"],
32
36
  module: "communication_channels",
33
37
  titleKey: "communication_channels.notifications.channel_requires_reauth.title",
34
38
  bodyKey: "communication_channels.notifications.channel_requires_reauth.body",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/modules/communication_channels/notifications.ts"],
4
- "sourcesContent": ["import type { NotificationTypeDefinition } from '@open-mercato/shared/modules/notifications/types'\n\nexport const notificationTypes: NotificationTypeDefinition[] = [\n {\n type: 'communication_channels.message.received',\n module: 'communication_channels',\n titleKey: 'communication_channels.notifications.message_received.title',\n bodyKey: 'communication_channels.notifications.message_received.body',\n icon: 'message-circle',\n severity: 'info',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/messages/{sourceEntityId}',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/messages/{sourceEntityId}',\n expiresAfterHours: 168, // 7 days\n },\n {\n /**\n * Channel-agnostic notification raised when an adapter loses authorization\n * (OAuth refresh token revoked, IMAP/SMTP password rotated, WhatsApp token expired).\n * Persisted by the `channel-requires-reauth-notification` subscriber in\n * response to the `communication_channels.channel.requires_reauth` event\n * (emitted by the poll worker and outbound delivery). Consumed by the email\n * integration spec's reconnect flow.\n */\n type: 'communication_channels.channel.requires_reauth',\n module: 'communication_channels',\n titleKey: 'communication_channels.notifications.channel_requires_reauth.title',\n bodyKey: 'communication_channels.notifications.channel_requires_reauth.body',\n icon: 'alert-triangle',\n severity: 'warning',\n actions: [\n {\n id: 'reconnect',\n labelKey: 'communication_channels.notifications.channel_requires_reauth.reconnect',\n variant: 'outline',\n href: '/backend/profile/communication-channels?reconnect={sourceEntityId}',\n icon: 'refresh-cw',\n },\n ],\n linkHref: '/backend/profile/communication-channels?reconnect={sourceEntityId}',\n expiresAfterHours: 720, // 30 days \u2014 auth issues should be addressed promptly\n },\n]\n\nexport default notificationTypes\n"],
5
- "mappings": "AAEO,MAAM,oBAAkD;AAAA,EAC7D;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA;AAAA,EACrB;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA;AAAA,EACrB;AACF;AAEA,IAAO,wBAAQ;",
4
+ "sourcesContent": ["import type { NotificationTypeDefinition } from '@open-mercato/shared/modules/notifications/types'\n\nexport const notificationTypes: NotificationTypeDefinition[] = [\n {\n type: 'communication_channels.message.received',\n // Ships without push \u2014 operators re-enable it per type from the Notification Delivery settings.\n channels: ['in_app', 'email'],\n module: 'communication_channels',\n titleKey: 'communication_channels.notifications.message_received.title',\n bodyKey: 'communication_channels.notifications.message_received.body',\n icon: 'message-circle',\n severity: 'info',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/messages/{sourceEntityId}',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/messages/{sourceEntityId}',\n expiresAfterHours: 168, // 7 days\n },\n {\n /**\n * Channel-agnostic notification raised when an adapter loses authorization\n * (OAuth refresh token revoked, IMAP/SMTP password rotated, WhatsApp token expired).\n * Persisted by the `channel-requires-reauth-notification` subscriber in\n * response to the `communication_channels.channel.requires_reauth` event\n * (emitted by the poll worker and outbound delivery). Consumed by the email\n * integration spec's reconnect flow.\n */\n type: 'communication_channels.channel.requires_reauth',\n // Ships without push \u2014 operators re-enable it per type from the Notification Delivery settings.\n channels: ['in_app', 'email'],\n module: 'communication_channels',\n titleKey: 'communication_channels.notifications.channel_requires_reauth.title',\n bodyKey: 'communication_channels.notifications.channel_requires_reauth.body',\n icon: 'alert-triangle',\n severity: 'warning',\n actions: [\n {\n id: 'reconnect',\n labelKey: 'communication_channels.notifications.channel_requires_reauth.reconnect',\n variant: 'outline',\n href: '/backend/profile/communication-channels?reconnect={sourceEntityId}',\n icon: 'refresh-cw',\n },\n ],\n linkHref: '/backend/profile/communication-channels?reconnect={sourceEntityId}',\n expiresAfterHours: 720, // 30 days \u2014 auth issues should be addressed promptly\n },\n]\n\nexport default notificationTypes\n"],
5
+ "mappings": "AAEO,MAAM,oBAAkD;AAAA,EAC7D;AAAA,IACE,MAAM;AAAA;AAAA,IAEN,UAAU,CAAC,UAAU,OAAO;AAAA,IAC5B,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA;AAAA,EACrB;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASE,MAAM;AAAA;AAAA,IAEN,UAAU,CAAC,UAAU,OAAO;AAAA,IAC5B,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA;AAAA,EACrB;AACF;AAEA,IAAO,wBAAQ;",
6
6
  "names": []
7
7
  }
@@ -21,6 +21,7 @@ const setup = {
21
21
  "communication_channels.react",
22
22
  "communication_channels.assign",
23
23
  "communication_channels.connect_user_channel",
24
+ "communication_channels.connect_tenant_channel",
24
25
  "communication_channels.admin",
25
26
  "communication_channels.channel.import_history",
26
27
  "communication_channels.channel.push.manage"
@@ -31,6 +32,7 @@ const setup = {
31
32
  "communication_channels.react",
32
33
  "communication_channels.assign",
33
34
  "communication_channels.connect_user_channel",
35
+ "communication_channels.connect_tenant_channel",
34
36
  "communication_channels.admin",
35
37
  "communication_channels.channel.import_history",
36
38
  "communication_channels.channel.push.manage"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/modules/communication_channels/setup.ts"],
4
- "sourcesContent": ["import { createHash } from 'node:crypto'\nimport type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'\nimport { COMMUNICATION_CHANNELS_QUEUES } from './lib/queue'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('communication_channels')\n\ntype SchedulerServiceLike = {\n register: (registration: {\n id: string\n name: string\n scopeType: 'system' | 'organization' | 'tenant'\n organizationId?: string\n tenantId?: string\n scheduleType: 'cron' | 'interval'\n scheduleValue: string\n timezone?: string\n targetType: 'queue' | 'command'\n targetQueue?: string\n targetPayload?: unknown\n sourceType?: 'user' | 'module'\n sourceModule?: string\n isEnabled?: boolean\n description?: string\n }) => Promise<void>\n}\n\n/**\n * Tick interval in seconds. Default 60s per email integration spec\n * \u00A7 Hub Deltas \u2192 Delta 6 (scheduler mechanism).\n */\nconst POLL_TICK_INTERVAL_SECONDS = Math.max(\n 10,\n Number.parseInt(process.env.OM_HUB_POLL_SCHEDULER_TICK_SECONDS ?? '60', 10) || 60,\n)\n\n/**\n * `scheduled_jobs.id` is a uuid column, so a module-owned schedule's stable\n * registration key must be hashed into a uuid rather than used verbatim \u2014 this\n * keeps `schedulerService.register()` an idempotent upsert across re-runs of\n * seedDefaults instead of trying to insert a raw string into the uuid PK.\n */\nfunction stableScheduleUuid(stableKey: string): string {\n const hex = createHash('sha256').update(stableKey).digest('hex')\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`\n}\n\nfunction stablePollTickScheduleId(organizationId: string): string {\n return stableScheduleUuid(`communication_channels:poll-tick:${organizationId}`)\n}\n\nexport const setup: ModuleSetupConfig = {\n defaultRoleFeatures: {\n superadmin: [\n 'communication_channels.view',\n 'communication_channels.manage',\n 'communication_channels.react',\n 'communication_channels.assign',\n 'communication_channels.connect_user_channel',\n 'communication_channels.admin',\n 'communication_channels.channel.import_history',\n 'communication_channels.channel.push.manage',\n ],\n admin: [\n 'communication_channels.view',\n 'communication_channels.manage',\n 'communication_channels.react',\n 'communication_channels.assign',\n 'communication_channels.connect_user_channel',\n 'communication_channels.admin',\n 'communication_channels.channel.import_history',\n 'communication_channels.channel.push.manage',\n ],\n manager: [\n 'communication_channels.view',\n 'communication_channels.manage',\n 'communication_channels.react',\n 'communication_channels.assign',\n 'communication_channels.connect_user_channel',\n ],\n employee: [\n 'communication_channels.view',\n 'communication_channels.react',\n 'communication_channels.connect_user_channel',\n ],\n },\n\n async seedDefaults({ container, organizationId, tenantId }) {\n /**\n * Register the per-channel polling tick with `@open-mercato/scheduler`.\n *\n * Per email integration spec \u00A7 Hub Deltas \u2192 Delta 6: every\n * `POLL_TICK_INTERVAL_SECONDS` (default 60s), enqueue a single\n * `communication-channels-poll-tick` job that enumerates due channels and\n * fans out to the `communication-channels-poll` queue.\n *\n * The registration is per-organization (one tick row per org/tenant pair)\n * so multi-tenant deploys schedule independently. Skipped silently when the\n * scheduler module isn't enabled \u2014 keeps the hub usable in scheduler-less\n * test harnesses.\n */\n const cradle = container as { hasRegistration?: (name: string) => boolean }\n if (typeof cradle.hasRegistration !== 'function' || !cradle.hasRegistration('schedulerService')) {\n return\n }\n const schedulerService = container.resolve('schedulerService') as SchedulerServiceLike\n // Best-effort: a scheduler failure must not abort tenant initialization for\n // every other module (mirrors the ai_assistant setup pattern). The schedule\n // ids are deterministic uuids so re-runs upsert idempotently.\n try {\n await schedulerService.register({\n id: stablePollTickScheduleId(organizationId),\n name: 'Communication channels poll tick',\n description:\n `Enumerates active polling channels every ${POLL_TICK_INTERVAL_SECONDS}s and enqueues per-channel poll jobs.`,\n scopeType: 'organization',\n organizationId,\n tenantId,\n scheduleType: 'interval',\n scheduleValue: `${POLL_TICK_INTERVAL_SECONDS}s`,\n timezone: 'UTC',\n targetType: 'queue',\n targetQueue: COMMUNICATION_CHANNELS_QUEUES.pollTick,\n targetPayload: {\n scope: { tenantId, organizationId },\n },\n sourceType: 'module',\n sourceModule: 'communication_channels',\n isEnabled: true,\n })\n\n // Spec C \u00A7 Phase C4 \u2014 Gmail watch renewal cron, per-org so multi-tenant\n // deploys schedule independently.\n await schedulerService.register({\n id: stableScheduleUuid(`communication_channels:gmail-renew-watch:${organizationId}`),\n name: 'Gmail watch renewal',\n description:\n 'Daily 04:00 UTC. Re-issues gmail.users.watch for channels within OM_PUSH_RENEWAL_GMAIL_LEAD_HOURS of expiry.',\n scopeType: 'organization',\n organizationId,\n tenantId,\n scheduleType: 'cron',\n scheduleValue: '0 4 * * *',\n timezone: 'UTC',\n targetType: 'queue',\n targetQueue: COMMUNICATION_CHANNELS_QUEUES.gmailRenewWatch,\n targetPayload: { scope: { tenantId, organizationId } },\n sourceType: 'module',\n sourceModule: 'communication_channels',\n isEnabled: true,\n })\n } catch (error) {\n logger.warn('Failed to register module schedules', { err: error })\n }\n },\n}\n\nexport default setup\n"],
5
- "mappings": "AAAA,SAAS,kBAAkB;AAE3B,SAAS,qCAAqC;AAC9C,SAAS,oBAAoB;AAE7B,MAAM,SAAS,aAAa,wBAAwB;AA0BpD,MAAM,6BAA6B,KAAK;AAAA,EACtC;AAAA,EACA,OAAO,SAAS,QAAQ,IAAI,sCAAsC,MAAM,EAAE,KAAK;AACjF;AAQA,SAAS,mBAAmB,WAA2B;AACrD,QAAM,MAAM,WAAW,QAAQ,EAAE,OAAO,SAAS,EAAE,OAAO,KAAK;AAC/D,SAAO,GAAG,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC;AAC9G;AAEA,SAAS,yBAAyB,gBAAgC;AAChE,SAAO,mBAAmB,oCAAoC,cAAc,EAAE;AAChF;AAEO,MAAM,QAA2B;AAAA,EACtC,qBAAqB;AAAA,IACnB,YAAY;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,aAAa,EAAE,WAAW,gBAAgB,SAAS,GAAG;AAc1D,UAAM,SAAS;AACf,QAAI,OAAO,OAAO,oBAAoB,cAAc,CAAC,OAAO,gBAAgB,kBAAkB,GAAG;AAC/F;AAAA,IACF;AACA,UAAM,mBAAmB,UAAU,QAAQ,kBAAkB;AAI7D,QAAI;AACF,YAAM,iBAAiB,SAAS;AAAA,QAC9B,IAAI,yBAAyB,cAAc;AAAA,QAC3C,MAAM;AAAA,QACN,aACE,4CAA4C,0BAA0B;AAAA,QACxE,WAAW;AAAA,QACX;AAAA,QACA;AAAA,QACA,cAAc;AAAA,QACd,eAAe,GAAG,0BAA0B;AAAA,QAC5C,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,aAAa,8BAA8B;AAAA,QAC3C,eAAe;AAAA,UACb,OAAO,EAAE,UAAU,eAAe;AAAA,QACpC;AAAA,QACA,YAAY;AAAA,QACZ,cAAc;AAAA,QACd,WAAW;AAAA,MACb,CAAC;AAID,YAAM,iBAAiB,SAAS;AAAA,QAC9B,IAAI,mBAAmB,4CAA4C,cAAc,EAAE;AAAA,QACnF,MAAM;AAAA,QACN,aACE;AAAA,QACF,WAAW;AAAA,QACX;AAAA,QACA;AAAA,QACA,cAAc;AAAA,QACd,eAAe;AAAA,QACf,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,aAAa,8BAA8B;AAAA,QAC3C,eAAe,EAAE,OAAO,EAAE,UAAU,eAAe,EAAE;AAAA,QACrD,YAAY;AAAA,QACZ,cAAc;AAAA,QACd,WAAW;AAAA,MACb,CAAC;AAAA,IACH,SAAS,OAAO;AACd,aAAO,KAAK,uCAAuC,EAAE,KAAK,MAAM,CAAC;AAAA,IACnE;AAAA,EACF;AACF;AAEA,IAAO,gBAAQ;",
4
+ "sourcesContent": ["import { createHash } from 'node:crypto'\nimport type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'\nimport { COMMUNICATION_CHANNELS_QUEUES } from './lib/queue'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('communication_channels')\n\ntype SchedulerServiceLike = {\n register: (registration: {\n id: string\n name: string\n scopeType: 'system' | 'organization' | 'tenant'\n organizationId?: string\n tenantId?: string\n scheduleType: 'cron' | 'interval'\n scheduleValue: string\n timezone?: string\n targetType: 'queue' | 'command'\n targetQueue?: string\n targetPayload?: unknown\n sourceType?: 'user' | 'module'\n sourceModule?: string\n isEnabled?: boolean\n description?: string\n }) => Promise<void>\n}\n\n/**\n * Tick interval in seconds. Default 60s per email integration spec\n * \u00A7 Hub Deltas \u2192 Delta 6 (scheduler mechanism).\n */\nconst POLL_TICK_INTERVAL_SECONDS = Math.max(\n 10,\n Number.parseInt(process.env.OM_HUB_POLL_SCHEDULER_TICK_SECONDS ?? '60', 10) || 60,\n)\n\n/**\n * `scheduled_jobs.id` is a uuid column, so a module-owned schedule's stable\n * registration key must be hashed into a uuid rather than used verbatim \u2014 this\n * keeps `schedulerService.register()` an idempotent upsert across re-runs of\n * seedDefaults instead of trying to insert a raw string into the uuid PK.\n */\nfunction stableScheduleUuid(stableKey: string): string {\n const hex = createHash('sha256').update(stableKey).digest('hex')\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`\n}\n\nfunction stablePollTickScheduleId(organizationId: string): string {\n return stableScheduleUuid(`communication_channels:poll-tick:${organizationId}`)\n}\n\nexport const setup: ModuleSetupConfig = {\n defaultRoleFeatures: {\n superadmin: [\n 'communication_channels.view',\n 'communication_channels.manage',\n 'communication_channels.react',\n 'communication_channels.assign',\n 'communication_channels.connect_user_channel',\n 'communication_channels.connect_tenant_channel',\n 'communication_channels.admin',\n 'communication_channels.channel.import_history',\n 'communication_channels.channel.push.manage',\n ],\n admin: [\n 'communication_channels.view',\n 'communication_channels.manage',\n 'communication_channels.react',\n 'communication_channels.assign',\n 'communication_channels.connect_user_channel',\n 'communication_channels.connect_tenant_channel',\n 'communication_channels.admin',\n 'communication_channels.channel.import_history',\n 'communication_channels.channel.push.manage',\n ],\n manager: [\n 'communication_channels.view',\n 'communication_channels.manage',\n 'communication_channels.react',\n 'communication_channels.assign',\n 'communication_channels.connect_user_channel',\n ],\n employee: [\n 'communication_channels.view',\n 'communication_channels.react',\n 'communication_channels.connect_user_channel',\n ],\n },\n\n async seedDefaults({ container, organizationId, tenantId }) {\n /**\n * Register the per-channel polling tick with `@open-mercato/scheduler`.\n *\n * Per email integration spec \u00A7 Hub Deltas \u2192 Delta 6: every\n * `POLL_TICK_INTERVAL_SECONDS` (default 60s), enqueue a single\n * `communication-channels-poll-tick` job that enumerates due channels and\n * fans out to the `communication-channels-poll` queue.\n *\n * The registration is per-organization (one tick row per org/tenant pair)\n * so multi-tenant deploys schedule independently. Skipped silently when the\n * scheduler module isn't enabled \u2014 keeps the hub usable in scheduler-less\n * test harnesses.\n */\n const cradle = container as { hasRegistration?: (name: string) => boolean }\n if (typeof cradle.hasRegistration !== 'function' || !cradle.hasRegistration('schedulerService')) {\n return\n }\n const schedulerService = container.resolve('schedulerService') as SchedulerServiceLike\n // Best-effort: a scheduler failure must not abort tenant initialization for\n // every other module (mirrors the ai_assistant setup pattern). The schedule\n // ids are deterministic uuids so re-runs upsert idempotently.\n try {\n await schedulerService.register({\n id: stablePollTickScheduleId(organizationId),\n name: 'Communication channels poll tick',\n description:\n `Enumerates active polling channels every ${POLL_TICK_INTERVAL_SECONDS}s and enqueues per-channel poll jobs.`,\n scopeType: 'organization',\n organizationId,\n tenantId,\n scheduleType: 'interval',\n scheduleValue: `${POLL_TICK_INTERVAL_SECONDS}s`,\n timezone: 'UTC',\n targetType: 'queue',\n targetQueue: COMMUNICATION_CHANNELS_QUEUES.pollTick,\n targetPayload: {\n scope: { tenantId, organizationId },\n },\n sourceType: 'module',\n sourceModule: 'communication_channels',\n isEnabled: true,\n })\n\n // Spec C \u00A7 Phase C4 \u2014 Gmail watch renewal cron, per-org so multi-tenant\n // deploys schedule independently.\n await schedulerService.register({\n id: stableScheduleUuid(`communication_channels:gmail-renew-watch:${organizationId}`),\n name: 'Gmail watch renewal',\n description:\n 'Daily 04:00 UTC. Re-issues gmail.users.watch for channels within OM_PUSH_RENEWAL_GMAIL_LEAD_HOURS of expiry.',\n scopeType: 'organization',\n organizationId,\n tenantId,\n scheduleType: 'cron',\n scheduleValue: '0 4 * * *',\n timezone: 'UTC',\n targetType: 'queue',\n targetQueue: COMMUNICATION_CHANNELS_QUEUES.gmailRenewWatch,\n targetPayload: { scope: { tenantId, organizationId } },\n sourceType: 'module',\n sourceModule: 'communication_channels',\n isEnabled: true,\n })\n } catch (error) {\n logger.warn('Failed to register module schedules', { err: error })\n }\n },\n}\n\nexport default setup\n"],
5
+ "mappings": "AAAA,SAAS,kBAAkB;AAE3B,SAAS,qCAAqC;AAC9C,SAAS,oBAAoB;AAE7B,MAAM,SAAS,aAAa,wBAAwB;AA0BpD,MAAM,6BAA6B,KAAK;AAAA,EACtC;AAAA,EACA,OAAO,SAAS,QAAQ,IAAI,sCAAsC,MAAM,EAAE,KAAK;AACjF;AAQA,SAAS,mBAAmB,WAA2B;AACrD,QAAM,MAAM,WAAW,QAAQ,EAAE,OAAO,SAAS,EAAE,OAAO,KAAK;AAC/D,SAAO,GAAG,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC;AAC9G;AAEA,SAAS,yBAAyB,gBAAgC;AAChE,SAAO,mBAAmB,oCAAoC,cAAc,EAAE;AAChF;AAEO,MAAM,QAA2B;AAAA,EACtC,qBAAqB;AAAA,IACnB,YAAY;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,SAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,UAAU;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,aAAa,EAAE,WAAW,gBAAgB,SAAS,GAAG;AAc1D,UAAM,SAAS;AACf,QAAI,OAAO,OAAO,oBAAoB,cAAc,CAAC,OAAO,gBAAgB,kBAAkB,GAAG;AAC/F;AAAA,IACF;AACA,UAAM,mBAAmB,UAAU,QAAQ,kBAAkB;AAI7D,QAAI;AACF,YAAM,iBAAiB,SAAS;AAAA,QAC9B,IAAI,yBAAyB,cAAc;AAAA,QAC3C,MAAM;AAAA,QACN,aACE,4CAA4C,0BAA0B;AAAA,QACxE,WAAW;AAAA,QACX;AAAA,QACA;AAAA,QACA,cAAc;AAAA,QACd,eAAe,GAAG,0BAA0B;AAAA,QAC5C,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,aAAa,8BAA8B;AAAA,QAC3C,eAAe;AAAA,UACb,OAAO,EAAE,UAAU,eAAe;AAAA,QACpC;AAAA,QACA,YAAY;AAAA,QACZ,cAAc;AAAA,QACd,WAAW;AAAA,MACb,CAAC;AAID,YAAM,iBAAiB,SAAS;AAAA,QAC9B,IAAI,mBAAmB,4CAA4C,cAAc,EAAE;AAAA,QACnF,MAAM;AAAA,QACN,aACE;AAAA,QACF,WAAW;AAAA,QACX;AAAA,QACA;AAAA,QACA,cAAc;AAAA,QACd,eAAe;AAAA,QACf,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,aAAa,8BAA8B;AAAA,QAC3C,eAAe,EAAE,OAAO,EAAE,UAAU,eAAe,EAAE;AAAA,QACrD,YAAY;AAAA,QACZ,cAAc;AAAA,QACd,WAAW;AAAA,MACb,CAAC;AAAA,IACH,SAAS,OAAO;AACd,aAAO,KAAK,uCAAuC,EAAE,KAAK,MAAM,CAAC;AAAA,IACnE;AAAA,EACF;AACF;AAEA,IAAO,gBAAQ;",
6
6
  "names": []
7
7
  }
@@ -33,6 +33,27 @@ const upgradeActions = [
33
33
  });
34
34
  }
35
35
  },
36
+ {
37
+ id: "devices.seed-push-token-encryption-map",
38
+ version: "0.6.6",
39
+ messageKey: "configs.upgrades.devicesPushTokenEncryption.message",
40
+ ctaKey: "configs.upgrades.devicesPushTokenEncryption.cta",
41
+ successKey: "configs.upgrades.devicesPushTokenEncryption.success",
42
+ loadingKey: "configs.upgrades.devicesPushTokenEncryption.loading",
43
+ // Encryption maps are seeded once at tenant creation (`entities seed-encryption`), so a tenant
44
+ // that predates the devices push-token feature has no `devices:user_device` map row. Without it
45
+ // `encryptEntityPayload` no-ops and `push_token` is written as PLAINTEXT (the map is a declaration
46
+ // of which fields to encrypt; the tenant DEK still drives the actual crypto, so seeding it is safe
47
+ // even when encryption is currently disabled — it only takes effect once encryption is on).
48
+ // Lazy-imported so configs stays decoupled from devices/entities (mirrors the customers action).
49
+ run: async ({ em, tenantId, organizationId }) => {
50
+ const [{ default: devicesEncryptionMaps }, { upsertEncryptionMapSpecs }] = await Promise.all([
51
+ import("@open-mercato/core/modules/devices/encryption"),
52
+ import("@open-mercato/core/modules/entities/cli")
53
+ ]);
54
+ await upsertEncryptionMapSpecs(em, tenantId, organizationId ?? null, devicesEncryptionMaps);
55
+ }
56
+ },
36
57
  {
37
58
  id: "customers.seed-interaction-statuses",
38
59
  version: "0.6.5",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/configs/lib/upgrade-actions.ts"],
4
- "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport * as semver from 'semver'\nimport type { AppContainer } from '@open-mercato/shared/lib/di/container'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport type { QueryEngine } from '@open-mercato/shared/lib/query/types'\nimport { reconcileAttachmentOrganizations } from '@open-mercato/core/modules/attachments/lib/reconcileOrganization'\n\nconst logger = createLogger('configs').child({ component: 'upgrade-actions' })\n\nexport type UpgradeActionContext = {\n tenantId: string\n organizationId: string\n container: AppContainer\n em: EntityManager\n}\n\nexport type UpgradeActionDefinition = {\n id: string\n version: string\n messageKey: string\n ctaKey: string\n successKey: string\n loadingKey?: string\n run: (ctx: UpgradeActionContext) => Promise<void>\n}\n\n/**\n * Compare two semantic version strings.\n * Uses the semver library for robust version comparison.\n * Returns negative if a < b, positive if a > b, 0 if equal.\n * Throws an error if either version string is invalid.\n */\nexport function compareVersions(a: string, b: string): number {\n const cleanA = semver.valid(semver.coerce(a))\n const cleanB = semver.valid(semver.coerce(b))\n if (!cleanA) {\n throw new Error(`Invalid version string: \"${a}\". Expected a valid semver format (e.g., \"1.2.3\").`)\n }\n if (!cleanB) {\n throw new Error(`Invalid version string: \"${b}\". Expected a valid semver format (e.g., \"1.2.3\").`)\n }\n return semver.compare(cleanA, cleanB)\n}\n\nexport const upgradeActions: UpgradeActionDefinition[] = [\n {\n id: 'attachments.reconcile-organization',\n version: '0.6.6',\n messageKey: 'configs.upgrades.attachmentsOrgReconcile.message',\n ctaKey: 'configs.upgrades.attachmentsOrgReconcile.cta',\n successKey: 'configs.upgrades.attachmentsOrgReconcile.success',\n loadingKey: 'configs.upgrades.attachmentsOrgReconcile.loading',\n async run({ container, em, tenantId }) {\n const queryEngine = container.resolve('queryEngine') as QueryEngine\n const report = await reconcileAttachmentOrganizations({ em, queryEngine, tenantId })\n logger.info('attachments organization reconcile completed', {\n tenantId,\n scanned: report.scanned,\n updated: report.updated,\n unresolved: report.unresolved,\n skippedVirtual: report.skippedVirtual,\n })\n },\n },\n {\n id: 'customers.seed-interaction-statuses',\n version: '0.6.5',\n messageKey: 'customers.config.upgradeActions.interactionStatuses.message',\n ctaKey: 'customers.config.upgradeActions.interactionStatuses.cta',\n successKey: 'customers.config.upgradeActions.interactionStatuses.success',\n loadingKey: 'customers.config.upgradeActions.interactionStatuses.loading',\n // Existing tenants predate the `interaction_status` dictionary, so their status\n // dropdown is empty until seeded. New tenants get it via customers `seedDefaults`.\n // Lazy-imported so configs stays decoupled from customers (the catalog of actions\n // lives here, but customers code only loads when the action actually runs).\n run: async ({ em, tenantId, organizationId }) => {\n const [{ INTERACTION_STATUS_DEFAULTS }, { ensureDictionaryEntry }] = await Promise.all([\n import('@open-mercato/core/modules/customers/cli'),\n import('@open-mercato/core/modules/customers/commands/shared'),\n ])\n for (const entry of INTERACTION_STATUS_DEFAULTS) {\n await ensureDictionaryEntry(em, {\n tenantId,\n organizationId,\n kind: 'interaction_status',\n value: entry.value,\n label: entry.label,\n color: entry.color,\n icon: entry.icon,\n })\n }\n },\n },\n {\n id: 'payment_gateways.register-session-initialization-prune',\n version: '0.6.6',\n messageKey: 'payment_gateways.upgradeActions.sessionInitializationPrune.message',\n ctaKey: 'payment_gateways.upgradeActions.sessionInitializationPrune.cta',\n successKey: 'payment_gateways.upgradeActions.sessionInitializationPrune.success',\n loadingKey: 'payment_gateways.upgradeActions.sessionInitializationPrune.loading',\n run: async ({ container, tenantId, organizationId }) => {\n const { registerSessionInitializationPruneSchedule } = await import(\n '@open-mercato/core/modules/payment_gateways/setup'\n )\n await registerSessionInitializationPruneSchedule(container, { tenantId, organizationId })\n },\n },\n]\n\nexport function actionsUpToVersion(version: string): UpgradeActionDefinition[] {\n return upgradeActions // NOSONAR \u2014 upgradeActions is populated at boot time by modules\n .filter((action) => compareVersions(action.version, version) <= 0)\n .sort((a, b) => compareVersions(a.version, b.version) || a.id.localeCompare(b.id))\n}\n\nexport function findUpgradeAction(actionId: string, maxVersion: string): UpgradeActionDefinition | undefined {\n const matches = actionsUpToVersion(maxVersion).filter((action) => action.id === actionId)\n if (!matches.length) return undefined\n return matches[matches.length - 1]\n}\n"],
5
- "mappings": "AACA,YAAY,YAAY;AAExB,SAAS,oBAAoB;AAE7B,SAAS,wCAAwC;AAEjD,MAAM,SAAS,aAAa,SAAS,EAAE,MAAM,EAAE,WAAW,kBAAkB,CAAC;AAyBtE,SAAS,gBAAgB,GAAW,GAAmB;AAC5D,QAAM,SAAS,OAAO,MAAM,OAAO,OAAO,CAAC,CAAC;AAC5C,QAAM,SAAS,OAAO,MAAM,OAAO,OAAO,CAAC,CAAC;AAC5C,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,4BAA4B,CAAC,oDAAoD;AAAA,EACnG;AACA,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,4BAA4B,CAAC,oDAAoD;AAAA,EACnG;AACA,SAAO,OAAO,QAAQ,QAAQ,MAAM;AACtC;AAEO,MAAM,iBAA4C;AAAA,EACvD;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,MAAM,IAAI,EAAE,WAAW,IAAI,SAAS,GAAG;AACrC,YAAM,cAAc,UAAU,QAAQ,aAAa;AACnD,YAAM,SAAS,MAAM,iCAAiC,EAAE,IAAI,aAAa,SAAS,CAAC;AACnF,aAAO,KAAK,gDAAgD;AAAA,QAC1D;AAAA,QACA,SAAS,OAAO;AAAA,QAChB,SAAS,OAAO;AAAA,QAChB,YAAY,OAAO;AAAA,QACnB,gBAAgB,OAAO;AAAA,MACzB,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA,IAKZ,KAAK,OAAO,EAAE,IAAI,UAAU,eAAe,MAAM;AAC/C,YAAM,CAAC,EAAE,4BAA4B,GAAG,EAAE,sBAAsB,CAAC,IAAI,MAAM,QAAQ,IAAI;AAAA,QACrF,OAAO,0CAA0C;AAAA,QACjD,OAAO,sDAAsD;AAAA,MAC/D,CAAC;AACD,iBAAW,SAAS,6BAA6B;AAC/C,cAAM,sBAAsB,IAAI;AAAA,UAC9B;AAAA,UACA;AAAA,UACA,MAAM;AAAA,UACN,OAAO,MAAM;AAAA,UACb,OAAO,MAAM;AAAA,UACb,OAAO,MAAM;AAAA,UACb,MAAM,MAAM;AAAA,QACd,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,KAAK,OAAO,EAAE,WAAW,UAAU,eAAe,MAAM;AACtD,YAAM,EAAE,2CAA2C,IAAI,MAAM,OAC3D,mDACF;AACA,YAAM,2CAA2C,WAAW,EAAE,UAAU,eAAe,CAAC;AAAA,IAC1F;AAAA,EACF;AACF;AAEO,SAAS,mBAAmB,SAA4C;AAC7E,SAAO,eACJ,OAAO,CAAC,WAAW,gBAAgB,OAAO,SAAS,OAAO,KAAK,CAAC,EAChE,KAAK,CAAC,GAAG,MAAM,gBAAgB,EAAE,SAAS,EAAE,OAAO,KAAK,EAAE,GAAG,cAAc,EAAE,EAAE,CAAC;AACrF;AAEO,SAAS,kBAAkB,UAAkB,YAAyD;AAC3G,QAAM,UAAU,mBAAmB,UAAU,EAAE,OAAO,CAAC,WAAW,OAAO,OAAO,QAAQ;AACxF,MAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,SAAO,QAAQ,QAAQ,SAAS,CAAC;AACnC;",
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport * as semver from 'semver'\nimport type { AppContainer } from '@open-mercato/shared/lib/di/container'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport type { QueryEngine } from '@open-mercato/shared/lib/query/types'\nimport { reconcileAttachmentOrganizations } from '@open-mercato/core/modules/attachments/lib/reconcileOrganization'\n\nconst logger = createLogger('configs').child({ component: 'upgrade-actions' })\n\nexport type UpgradeActionContext = {\n tenantId: string\n organizationId: string\n container: AppContainer\n em: EntityManager\n}\n\nexport type UpgradeActionDefinition = {\n id: string\n version: string\n messageKey: string\n ctaKey: string\n successKey: string\n loadingKey?: string\n run: (ctx: UpgradeActionContext) => Promise<void>\n}\n\n/**\n * Compare two semantic version strings.\n * Uses the semver library for robust version comparison.\n * Returns negative if a < b, positive if a > b, 0 if equal.\n * Throws an error if either version string is invalid.\n */\nexport function compareVersions(a: string, b: string): number {\n const cleanA = semver.valid(semver.coerce(a))\n const cleanB = semver.valid(semver.coerce(b))\n if (!cleanA) {\n throw new Error(`Invalid version string: \"${a}\". Expected a valid semver format (e.g., \"1.2.3\").`)\n }\n if (!cleanB) {\n throw new Error(`Invalid version string: \"${b}\". Expected a valid semver format (e.g., \"1.2.3\").`)\n }\n return semver.compare(cleanA, cleanB)\n}\n\nexport const upgradeActions: UpgradeActionDefinition[] = [\n {\n id: 'attachments.reconcile-organization',\n version: '0.6.6',\n messageKey: 'configs.upgrades.attachmentsOrgReconcile.message',\n ctaKey: 'configs.upgrades.attachmentsOrgReconcile.cta',\n successKey: 'configs.upgrades.attachmentsOrgReconcile.success',\n loadingKey: 'configs.upgrades.attachmentsOrgReconcile.loading',\n async run({ container, em, tenantId }) {\n const queryEngine = container.resolve('queryEngine') as QueryEngine\n const report = await reconcileAttachmentOrganizations({ em, queryEngine, tenantId })\n logger.info('attachments organization reconcile completed', {\n tenantId,\n scanned: report.scanned,\n updated: report.updated,\n unresolved: report.unresolved,\n skippedVirtual: report.skippedVirtual,\n })\n },\n },\n {\n id: 'devices.seed-push-token-encryption-map',\n version: '0.6.6',\n messageKey: 'configs.upgrades.devicesPushTokenEncryption.message',\n ctaKey: 'configs.upgrades.devicesPushTokenEncryption.cta',\n successKey: 'configs.upgrades.devicesPushTokenEncryption.success',\n loadingKey: 'configs.upgrades.devicesPushTokenEncryption.loading',\n // Encryption maps are seeded once at tenant creation (`entities seed-encryption`), so a tenant\n // that predates the devices push-token feature has no `devices:user_device` map row. Without it\n // `encryptEntityPayload` no-ops and `push_token` is written as PLAINTEXT (the map is a declaration\n // of which fields to encrypt; the tenant DEK still drives the actual crypto, so seeding it is safe\n // even when encryption is currently disabled \u2014 it only takes effect once encryption is on).\n // Lazy-imported so configs stays decoupled from devices/entities (mirrors the customers action).\n run: async ({ em, tenantId, organizationId }) => {\n const [{ default: devicesEncryptionMaps }, { upsertEncryptionMapSpecs }] = await Promise.all([\n import('@open-mercato/core/modules/devices/encryption'),\n import('@open-mercato/core/modules/entities/cli'),\n ])\n await upsertEncryptionMapSpecs(em, tenantId, organizationId ?? null, devicesEncryptionMaps)\n },\n },\n {\n id: 'customers.seed-interaction-statuses',\n version: '0.6.5',\n messageKey: 'customers.config.upgradeActions.interactionStatuses.message',\n ctaKey: 'customers.config.upgradeActions.interactionStatuses.cta',\n successKey: 'customers.config.upgradeActions.interactionStatuses.success',\n loadingKey: 'customers.config.upgradeActions.interactionStatuses.loading',\n // Existing tenants predate the `interaction_status` dictionary, so their status\n // dropdown is empty until seeded. New tenants get it via customers `seedDefaults`.\n // Lazy-imported so configs stays decoupled from customers (the catalog of actions\n // lives here, but customers code only loads when the action actually runs).\n run: async ({ em, tenantId, organizationId }) => {\n const [{ INTERACTION_STATUS_DEFAULTS }, { ensureDictionaryEntry }] = await Promise.all([\n import('@open-mercato/core/modules/customers/cli'),\n import('@open-mercato/core/modules/customers/commands/shared'),\n ])\n for (const entry of INTERACTION_STATUS_DEFAULTS) {\n await ensureDictionaryEntry(em, {\n tenantId,\n organizationId,\n kind: 'interaction_status',\n value: entry.value,\n label: entry.label,\n color: entry.color,\n icon: entry.icon,\n })\n }\n },\n },\n {\n id: 'payment_gateways.register-session-initialization-prune',\n version: '0.6.6',\n messageKey: 'payment_gateways.upgradeActions.sessionInitializationPrune.message',\n ctaKey: 'payment_gateways.upgradeActions.sessionInitializationPrune.cta',\n successKey: 'payment_gateways.upgradeActions.sessionInitializationPrune.success',\n loadingKey: 'payment_gateways.upgradeActions.sessionInitializationPrune.loading',\n run: async ({ container, tenantId, organizationId }) => {\n const { registerSessionInitializationPruneSchedule } = await import(\n '@open-mercato/core/modules/payment_gateways/setup'\n )\n await registerSessionInitializationPruneSchedule(container, { tenantId, organizationId })\n },\n },\n]\n\nexport function actionsUpToVersion(version: string): UpgradeActionDefinition[] {\n return upgradeActions // NOSONAR \u2014 upgradeActions is populated at boot time by modules\n .filter((action) => compareVersions(action.version, version) <= 0)\n .sort((a, b) => compareVersions(a.version, b.version) || a.id.localeCompare(b.id))\n}\n\nexport function findUpgradeAction(actionId: string, maxVersion: string): UpgradeActionDefinition | undefined {\n const matches = actionsUpToVersion(maxVersion).filter((action) => action.id === actionId)\n if (!matches.length) return undefined\n return matches[matches.length - 1]\n}\n"],
5
+ "mappings": "AACA,YAAY,YAAY;AAExB,SAAS,oBAAoB;AAE7B,SAAS,wCAAwC;AAEjD,MAAM,SAAS,aAAa,SAAS,EAAE,MAAM,EAAE,WAAW,kBAAkB,CAAC;AAyBtE,SAAS,gBAAgB,GAAW,GAAmB;AAC5D,QAAM,SAAS,OAAO,MAAM,OAAO,OAAO,CAAC,CAAC;AAC5C,QAAM,SAAS,OAAO,MAAM,OAAO,OAAO,CAAC,CAAC;AAC5C,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,4BAA4B,CAAC,oDAAoD;AAAA,EACnG;AACA,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,4BAA4B,CAAC,oDAAoD;AAAA,EACnG;AACA,SAAO,OAAO,QAAQ,QAAQ,MAAM;AACtC;AAEO,MAAM,iBAA4C;AAAA,EACvD;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,MAAM,IAAI,EAAE,WAAW,IAAI,SAAS,GAAG;AACrC,YAAM,cAAc,UAAU,QAAQ,aAAa;AACnD,YAAM,SAAS,MAAM,iCAAiC,EAAE,IAAI,aAAa,SAAS,CAAC;AACnF,aAAO,KAAK,gDAAgD;AAAA,QAC1D;AAAA,QACA,SAAS,OAAO;AAAA,QAChB,SAAS,OAAO;AAAA,QAChB,YAAY,OAAO;AAAA,QACnB,gBAAgB,OAAO;AAAA,MACzB,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOZ,KAAK,OAAO,EAAE,IAAI,UAAU,eAAe,MAAM;AAC/C,YAAM,CAAC,EAAE,SAAS,sBAAsB,GAAG,EAAE,yBAAyB,CAAC,IAAI,MAAM,QAAQ,IAAI;AAAA,QAC3F,OAAO,+CAA+C;AAAA,QACtD,OAAO,yCAAyC;AAAA,MAClD,CAAC;AACD,YAAM,yBAAyB,IAAI,UAAU,kBAAkB,MAAM,qBAAqB;AAAA,IAC5F;AAAA,EACF;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA,IAKZ,KAAK,OAAO,EAAE,IAAI,UAAU,eAAe,MAAM;AAC/C,YAAM,CAAC,EAAE,4BAA4B,GAAG,EAAE,sBAAsB,CAAC,IAAI,MAAM,QAAQ,IAAI;AAAA,QACrF,OAAO,0CAA0C;AAAA,QACjD,OAAO,sDAAsD;AAAA,MAC/D,CAAC;AACD,iBAAW,SAAS,6BAA6B;AAC/C,cAAM,sBAAsB,IAAI;AAAA,UAC9B;AAAA,UACA;AAAA,UACA,MAAM;AAAA,UACN,OAAO,MAAM;AAAA,UACb,OAAO,MAAM;AAAA,UACb,OAAO,MAAM;AAAA,UACb,MAAM,MAAM;AAAA,QACd,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EACA;AAAA,IACE,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,KAAK,OAAO,EAAE,WAAW,UAAU,eAAe,MAAM;AACtD,YAAM,EAAE,2CAA2C,IAAI,MAAM,OAC3D,mDACF;AACA,YAAM,2CAA2C,WAAW,EAAE,UAAU,eAAe,CAAC;AAAA,IAC1F;AAAA,EACF;AACF;AAEO,SAAS,mBAAmB,SAA4C;AAC7E,SAAO,eACJ,OAAO,CAAC,WAAW,gBAAgB,OAAO,SAAS,OAAO,KAAK,CAAC,EAChE,KAAK,CAAC,GAAG,MAAM,gBAAgB,EAAE,SAAS,EAAE,OAAO,KAAK,EAAE,GAAG,cAAc,EAAE,EAAE,CAAC;AACrF;AAEO,SAAS,kBAAkB,UAAkB,YAAyD;AAC3G,QAAM,UAAU,mBAAmB,UAAU,EAAE,OAAO,CAAC,WAAW,OAAO,OAAO,QAAQ;AACxF,MAAI,CAAC,QAAQ,OAAQ,QAAO;AAC5B,SAAO,QAAQ,QAAQ,SAAS,CAAC;AACnC;",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,8 @@
1
1
  const notificationTypes = [
2
2
  {
3
3
  type: "customer_accounts.user.signup",
4
+ // Ships without push — operators re-enable it per type from the Notification Delivery settings.
5
+ channels: ["in_app", "email"],
4
6
  module: "customer_accounts",
5
7
  titleKey: "customer_accounts.notifications.user.signup.title",
6
8
  bodyKey: "customer_accounts.notifications.user.signup.body",
@@ -20,6 +22,8 @@ const notificationTypes = [
20
22
  },
21
23
  {
22
24
  type: "customer_accounts.user.locked",
25
+ // Ships without push — operators re-enable it per type from the Notification Delivery settings.
26
+ channels: ["in_app", "email"],
23
27
  module: "customer_accounts",
24
28
  titleKey: "customer_accounts.notifications.user.locked.title",
25
29
  bodyKey: "customer_accounts.notifications.user.locked.body",
@@ -39,6 +43,8 @@ const notificationTypes = [
39
43
  },
40
44
  {
41
45
  type: "customer_accounts.domain_mapping.verified",
46
+ // Ships without push — operators re-enable it per type from the Notification Delivery settings.
47
+ channels: ["in_app", "email"],
42
48
  module: "customer_accounts",
43
49
  titleKey: "customer_accounts.notifications.domain_mapping.verified.title",
44
50
  bodyKey: "customer_accounts.notifications.domain_mapping.verified.body",
@@ -58,6 +64,8 @@ const notificationTypes = [
58
64
  },
59
65
  {
60
66
  type: "customer_accounts.domain_mapping.activated",
67
+ // Ships without push — operators re-enable it per type from the Notification Delivery settings.
68
+ channels: ["in_app", "email"],
61
69
  module: "customer_accounts",
62
70
  titleKey: "customer_accounts.notifications.domain_mapping.activated.title",
63
71
  bodyKey: "customer_accounts.notifications.domain_mapping.activated.body",
@@ -77,6 +85,8 @@ const notificationTypes = [
77
85
  },
78
86
  {
79
87
  type: "customer_accounts.domain_mapping.dns_failed",
88
+ // Ships without push — operators re-enable it per type from the Notification Delivery settings.
89
+ channels: ["in_app", "email"],
80
90
  module: "customer_accounts",
81
91
  titleKey: "customer_accounts.notifications.domain_mapping.dns_failed.title",
82
92
  bodyKey: "customer_accounts.notifications.domain_mapping.dns_failed.body",
@@ -96,6 +106,8 @@ const notificationTypes = [
96
106
  },
97
107
  {
98
108
  type: "customer_accounts.domain_mapping.tls_failed",
109
+ // Ships without push — operators re-enable it per type from the Notification Delivery settings.
110
+ channels: ["in_app", "email"],
99
111
  module: "customer_accounts",
100
112
  titleKey: "customer_accounts.notifications.domain_mapping.tls_failed.title",
101
113
  bodyKey: "customer_accounts.notifications.domain_mapping.tls_failed.body",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/modules/customer_accounts/notifications.ts"],
4
- "sourcesContent": ["import type { NotificationTypeDefinition } from '@open-mercato/shared/modules/notifications/types'\n\nexport const notificationTypes: NotificationTypeDefinition[] = [\n {\n type: 'customer_accounts.user.signup',\n module: 'customer_accounts',\n titleKey: 'customer_accounts.notifications.user.signup.title',\n bodyKey: 'customer_accounts.notifications.user.signup.body',\n icon: 'user-plus',\n severity: 'info',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/customer_accounts/users/{sourceEntityId}',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/customer_accounts/users/{sourceEntityId}',\n expiresAfterHours: 168,\n },\n {\n type: 'customer_accounts.user.locked',\n module: 'customer_accounts',\n titleKey: 'customer_accounts.notifications.user.locked.title',\n bodyKey: 'customer_accounts.notifications.user.locked.body',\n icon: 'lock',\n severity: 'warning',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/customer_accounts/users/{sourceEntityId}',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/customer_accounts/users/{sourceEntityId}',\n expiresAfterHours: 168,\n },\n {\n type: 'customer_accounts.domain_mapping.verified',\n module: 'customer_accounts',\n titleKey: 'customer_accounts.notifications.domain_mapping.verified.title',\n bodyKey: 'customer_accounts.notifications.domain_mapping.verified.body',\n icon: 'check-circle',\n severity: 'success',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/customer_accounts/settings/domain',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/customer_accounts/settings/domain',\n expiresAfterHours: 168,\n },\n {\n type: 'customer_accounts.domain_mapping.activated',\n module: 'customer_accounts',\n titleKey: 'customer_accounts.notifications.domain_mapping.activated.title',\n bodyKey: 'customer_accounts.notifications.domain_mapping.activated.body',\n icon: 'globe',\n severity: 'success',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/customer_accounts/settings/domain',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/customer_accounts/settings/domain',\n expiresAfterHours: 168,\n },\n {\n type: 'customer_accounts.domain_mapping.dns_failed',\n module: 'customer_accounts',\n titleKey: 'customer_accounts.notifications.domain_mapping.dns_failed.title',\n bodyKey: 'customer_accounts.notifications.domain_mapping.dns_failed.body',\n icon: 'alert-triangle',\n severity: 'warning',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/customer_accounts/settings/domain',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/customer_accounts/settings/domain',\n expiresAfterHours: 168,\n },\n {\n type: 'customer_accounts.domain_mapping.tls_failed',\n module: 'customer_accounts',\n titleKey: 'customer_accounts.notifications.domain_mapping.tls_failed.title',\n bodyKey: 'customer_accounts.notifications.domain_mapping.tls_failed.body',\n icon: 'shield-alert',\n severity: 'warning',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/customer_accounts/settings/domain',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/customer_accounts/settings/domain',\n expiresAfterHours: 168,\n },\n]\n\nexport default notificationTypes\n"],
5
- "mappings": "AAEO,MAAM,oBAAkD;AAAA,EAC7D;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA,EACrB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA,EACrB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA,EACrB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA,EACrB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA,EACrB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA,EACrB;AACF;AAEA,IAAO,wBAAQ;",
4
+ "sourcesContent": ["import type { NotificationTypeDefinition } from '@open-mercato/shared/modules/notifications/types'\n\nexport const notificationTypes: NotificationTypeDefinition[] = [\n {\n type: 'customer_accounts.user.signup',\n // Ships without push \u2014 operators re-enable it per type from the Notification Delivery settings.\n channels: ['in_app', 'email'],\n module: 'customer_accounts',\n titleKey: 'customer_accounts.notifications.user.signup.title',\n bodyKey: 'customer_accounts.notifications.user.signup.body',\n icon: 'user-plus',\n severity: 'info',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/customer_accounts/users/{sourceEntityId}',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/customer_accounts/users/{sourceEntityId}',\n expiresAfterHours: 168,\n },\n {\n type: 'customer_accounts.user.locked',\n // Ships without push \u2014 operators re-enable it per type from the Notification Delivery settings.\n channels: ['in_app', 'email'],\n module: 'customer_accounts',\n titleKey: 'customer_accounts.notifications.user.locked.title',\n bodyKey: 'customer_accounts.notifications.user.locked.body',\n icon: 'lock',\n severity: 'warning',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/customer_accounts/users/{sourceEntityId}',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/customer_accounts/users/{sourceEntityId}',\n expiresAfterHours: 168,\n },\n {\n type: 'customer_accounts.domain_mapping.verified',\n // Ships without push \u2014 operators re-enable it per type from the Notification Delivery settings.\n channels: ['in_app', 'email'],\n module: 'customer_accounts',\n titleKey: 'customer_accounts.notifications.domain_mapping.verified.title',\n bodyKey: 'customer_accounts.notifications.domain_mapping.verified.body',\n icon: 'check-circle',\n severity: 'success',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/customer_accounts/settings/domain',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/customer_accounts/settings/domain',\n expiresAfterHours: 168,\n },\n {\n type: 'customer_accounts.domain_mapping.activated',\n // Ships without push \u2014 operators re-enable it per type from the Notification Delivery settings.\n channels: ['in_app', 'email'],\n module: 'customer_accounts',\n titleKey: 'customer_accounts.notifications.domain_mapping.activated.title',\n bodyKey: 'customer_accounts.notifications.domain_mapping.activated.body',\n icon: 'globe',\n severity: 'success',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/customer_accounts/settings/domain',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/customer_accounts/settings/domain',\n expiresAfterHours: 168,\n },\n {\n type: 'customer_accounts.domain_mapping.dns_failed',\n // Ships without push \u2014 operators re-enable it per type from the Notification Delivery settings.\n channels: ['in_app', 'email'],\n module: 'customer_accounts',\n titleKey: 'customer_accounts.notifications.domain_mapping.dns_failed.title',\n bodyKey: 'customer_accounts.notifications.domain_mapping.dns_failed.body',\n icon: 'alert-triangle',\n severity: 'warning',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/customer_accounts/settings/domain',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/customer_accounts/settings/domain',\n expiresAfterHours: 168,\n },\n {\n type: 'customer_accounts.domain_mapping.tls_failed',\n // Ships without push \u2014 operators re-enable it per type from the Notification Delivery settings.\n channels: ['in_app', 'email'],\n module: 'customer_accounts',\n titleKey: 'customer_accounts.notifications.domain_mapping.tls_failed.title',\n bodyKey: 'customer_accounts.notifications.domain_mapping.tls_failed.body',\n icon: 'shield-alert',\n severity: 'warning',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/customer_accounts/settings/domain',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/customer_accounts/settings/domain',\n expiresAfterHours: 168,\n },\n]\n\nexport default notificationTypes\n"],
5
+ "mappings": "AAEO,MAAM,oBAAkD;AAAA,EAC7D;AAAA,IACE,MAAM;AAAA;AAAA,IAEN,UAAU,CAAC,UAAU,OAAO;AAAA,IAC5B,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA,EACrB;AAAA,EACA;AAAA,IACE,MAAM;AAAA;AAAA,IAEN,UAAU,CAAC,UAAU,OAAO;AAAA,IAC5B,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA,EACrB;AAAA,EACA;AAAA,IACE,MAAM;AAAA;AAAA,IAEN,UAAU,CAAC,UAAU,OAAO;AAAA,IAC5B,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA,EACrB;AAAA,EACA;AAAA,IACE,MAAM;AAAA;AAAA,IAEN,UAAU,CAAC,UAAU,OAAO;AAAA,IAC5B,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA,EACrB;AAAA,EACA;AAAA,IACE,MAAM;AAAA;AAAA,IAEN,UAAU,CAAC,UAAU,OAAO;AAAA,IAC5B,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA,EACrB;AAAA,EACA;AAAA,IACE,MAAM;AAAA;AAAA,IAEN,UAAU,CAAC,UAAU,OAAO;AAAA,IAC5B,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA,EACrB;AACF;AAEA,IAAO,wBAAQ;",
6
6
  "names": []
7
7
  }
@@ -1,6 +1,8 @@
1
1
  const notificationTypes = [
2
2
  {
3
3
  type: "customers.deal.won",
4
+ // Ships without push — operators re-enable it per type from the Notification Delivery settings.
5
+ channels: ["in_app", "email"],
4
6
  module: "customers",
5
7
  titleKey: "customers.notifications.deal.won.title",
6
8
  bodyKey: "customers.notifications.deal.won.body",
@@ -21,6 +23,8 @@ const notificationTypes = [
21
23
  },
22
24
  {
23
25
  type: "customers.deal.lost",
26
+ // Ships without push — operators re-enable it per type from the Notification Delivery settings.
27
+ channels: ["in_app", "email"],
24
28
  module: "customers",
25
29
  titleKey: "customers.notifications.deal.lost.title",
26
30
  bodyKey: "customers.notifications.deal.lost.body",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/modules/customers/notifications.ts"],
4
- "sourcesContent": ["import type { NotificationTypeDefinition } from '@open-mercato/shared/modules/notifications/types'\n\nexport const notificationTypes: NotificationTypeDefinition[] = [\n {\n type: 'customers.deal.won',\n module: 'customers',\n titleKey: 'customers.notifications.deal.won.title',\n bodyKey: 'customers.notifications.deal.won.body',\n icon: 'trophy',\n severity: 'success',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/customers/deals/{sourceEntityId}',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/customers/deals/{sourceEntityId}',\n expiresAfterHours: 168, // 7 days\n },\n {\n type: 'customers.deal.lost',\n module: 'customers',\n titleKey: 'customers.notifications.deal.lost.title',\n bodyKey: 'customers.notifications.deal.lost.body',\n icon: 'x-circle',\n severity: 'warning',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/customers/deals/{sourceEntityId}',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/customers/deals/{sourceEntityId}',\n expiresAfterHours: 168, // 7 days\n },\n]\n\nexport default notificationTypes\n"],
5
- "mappings": "AAEO,MAAM,oBAAkD;AAAA,EAC7D;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA;AAAA,EACrB;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA;AAAA,EACrB;AACF;AAEA,IAAO,wBAAQ;",
4
+ "sourcesContent": ["import type { NotificationTypeDefinition } from '@open-mercato/shared/modules/notifications/types'\n\nexport const notificationTypes: NotificationTypeDefinition[] = [\n {\n type: 'customers.deal.won',\n // Ships without push \u2014 operators re-enable it per type from the Notification Delivery settings.\n channels: ['in_app', 'email'],\n module: 'customers',\n titleKey: 'customers.notifications.deal.won.title',\n bodyKey: 'customers.notifications.deal.won.body',\n icon: 'trophy',\n severity: 'success',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/customers/deals/{sourceEntityId}',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/customers/deals/{sourceEntityId}',\n expiresAfterHours: 168, // 7 days\n },\n {\n type: 'customers.deal.lost',\n // Ships without push \u2014 operators re-enable it per type from the Notification Delivery settings.\n channels: ['in_app', 'email'],\n module: 'customers',\n titleKey: 'customers.notifications.deal.lost.title',\n bodyKey: 'customers.notifications.deal.lost.body',\n icon: 'x-circle',\n severity: 'warning',\n actions: [\n {\n id: 'view',\n labelKey: 'common.view',\n variant: 'outline',\n href: '/backend/customers/deals/{sourceEntityId}',\n icon: 'external-link',\n },\n ],\n linkHref: '/backend/customers/deals/{sourceEntityId}',\n expiresAfterHours: 168, // 7 days\n },\n]\n\nexport default notificationTypes\n"],
5
+ "mappings": "AAEO,MAAM,oBAAkD;AAAA,EAC7D;AAAA,IACE,MAAM;AAAA;AAAA,IAEN,UAAU,CAAC,UAAU,OAAO;AAAA,IAC5B,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA;AAAA,EACrB;AAAA,EACA;AAAA,IACE,MAAM;AAAA;AAAA,IAEN,UAAU,CAAC,UAAU,OAAO;AAAA,IAC5B,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,UAAU;AAAA,IACV,mBAAmB;AAAA;AAAA,EACrB;AACF;AAEA,IAAO,wBAAQ;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,11 @@
1
+ const features = [
2
+ { id: "devices.view", title: "View own devices", module: "devices" },
3
+ { id: "devices.manage", title: "Manage own devices", module: "devices" },
4
+ { id: "devices.admin", title: "Manage devices across users", module: "devices" }
5
+ ];
6
+ var acl_default = features;
7
+ export {
8
+ acl_default as default,
9
+ features
10
+ };
11
+ //# sourceMappingURL=acl.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/modules/devices/acl.ts"],
4
+ "sourcesContent": ["export const features = [\n { id: 'devices.view', title: 'View own devices', module: 'devices' },\n { id: 'devices.manage', title: 'Manage own devices', module: 'devices' },\n { id: 'devices.admin', title: 'Manage devices across users', module: 'devices' },\n]\n\nexport default features\n"],
5
+ "mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,EAAE,IAAI,gBAAgB,OAAO,oBAAoB,QAAQ,UAAU;AAAA,EACnE,EAAE,IAAI,kBAAkB,OAAO,sBAAsB,QAAQ,UAAU;AAAA,EACvE,EAAE,IAAI,iBAAiB,OAAO,+BAA+B,QAAQ,UAAU;AACjF;AAEA,IAAO,cAAQ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,167 @@
1
+ import { NextResponse } from "next/server";
2
+ import { z } from "zod";
3
+ import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
4
+ import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
5
+ import { resolveOrganizationScopeForRequest } from "@open-mercato/core/modules/directory/utils/organizationScope";
6
+ import { isCrudHttpError } from "@open-mercato/shared/lib/crud/errors";
7
+ import { readJsonSafe } from "@open-mercato/shared/lib/http/readJsonSafe";
8
+ import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
9
+ import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
10
+ import { createLogger } from "@open-mercato/shared/lib/logger";
11
+ import { UserDevice } from "../../data/entities.js";
12
+ import { updateDeviceSchema } from "../../data/validators.js";
13
+ import { resolveDeviceActorUserId } from "../auth.js";
14
+ import { executeUpdate, executeDeactivate } from "../deviceOps.js";
15
+ const logger = createLogger("devices");
16
+ const metadata = {
17
+ PUT: { requireAuth: true, requireFeatures: ["devices.manage"] },
18
+ DELETE: { requireAuth: true, requireFeatures: ["devices.manage"] }
19
+ };
20
+ const paramsSchema = z.object({ id: z.string().uuid() });
21
+ async function PUT(req, { params }) {
22
+ const { translate } = await resolveTranslations();
23
+ try {
24
+ const container = await createRequestContainer();
25
+ const auth = await getAuthFromRequest(req);
26
+ const actorUserId = resolveDeviceActorUserId(auth);
27
+ if (!auth || !auth.tenantId || !actorUserId) {
28
+ return NextResponse.json({ error: translate("devices.errors.unauthorized", "Unauthorized") }, { status: 401 });
29
+ }
30
+ const parsedParams = paramsSchema.safeParse({ id: params.id });
31
+ if (!parsedParams.success) {
32
+ return NextResponse.json({ error: translate("devices.errors.invalid_id", "Invalid device id") }, { status: 400 });
33
+ }
34
+ const body = updateDeviceSchema.parse(await readJsonSafe(req, {}));
35
+ const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req });
36
+ const currentOrganizationId = scope?.selectedId ?? auth.orgId ?? null;
37
+ const em = container.resolve("em");
38
+ const device = await findOneWithDecryption(
39
+ em,
40
+ UserDevice,
41
+ {
42
+ id: parsedParams.data.id,
43
+ tenantId: auth.tenantId,
44
+ ...currentOrganizationId ? { organizationId: currentOrganizationId } : {},
45
+ deletedAt: null
46
+ },
47
+ void 0,
48
+ { tenantId: auth.tenantId, organizationId: currentOrganizationId }
49
+ );
50
+ if (!device) {
51
+ return NextResponse.json({ error: translate("devices.errors.not_found", "Device not found") }, { status: 404 });
52
+ }
53
+ if (device.userId !== actorUserId) {
54
+ return NextResponse.json({ error: translate("devices.errors.forbidden", "Access denied") }, { status: 403 });
55
+ }
56
+ const mctx = {
57
+ container,
58
+ auth,
59
+ scope,
60
+ organizationId: device.organizationId ?? null,
61
+ actorUserId,
62
+ request: req
63
+ };
64
+ return await executeUpdate(mctx, device, body);
65
+ } catch (err) {
66
+ if (err instanceof z.ZodError) {
67
+ return NextResponse.json(
68
+ { error: translate("devices.errors.invalid_payload", "Invalid device payload"), details: err.flatten() },
69
+ { status: 400 }
70
+ );
71
+ }
72
+ if (isCrudHttpError(err)) {
73
+ return NextResponse.json(err.body, { status: err.status });
74
+ }
75
+ logger.error("devices.PUT failed", { err });
76
+ return NextResponse.json({ error: translate("devices.errors.update_failed", "Failed to update device") }, { status: 500 });
77
+ }
78
+ }
79
+ async function DELETE(req, { params }) {
80
+ const { translate } = await resolveTranslations();
81
+ try {
82
+ const container = await createRequestContainer();
83
+ const auth = await getAuthFromRequest(req);
84
+ const actorUserId = resolveDeviceActorUserId(auth);
85
+ if (!auth || !auth.tenantId || !actorUserId) {
86
+ return NextResponse.json({ error: translate("devices.errors.unauthorized", "Unauthorized") }, { status: 401 });
87
+ }
88
+ const parsedParams = paramsSchema.safeParse({ id: params.id });
89
+ if (!parsedParams.success) {
90
+ return NextResponse.json({ error: translate("devices.errors.invalid_id", "Invalid device id") }, { status: 400 });
91
+ }
92
+ const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req });
93
+ const currentOrganizationId = scope?.selectedId ?? auth.orgId ?? null;
94
+ const em = container.resolve("em");
95
+ const device = await findOneWithDecryption(
96
+ em,
97
+ UserDevice,
98
+ {
99
+ id: parsedParams.data.id,
100
+ tenantId: auth.tenantId,
101
+ ...currentOrganizationId ? { organizationId: currentOrganizationId } : {},
102
+ deletedAt: null
103
+ },
104
+ void 0,
105
+ { tenantId: auth.tenantId, organizationId: currentOrganizationId }
106
+ );
107
+ if (!device) {
108
+ return NextResponse.json({ error: translate("devices.errors.not_found", "Device not found") }, { status: 404 });
109
+ }
110
+ if (device.userId !== actorUserId) {
111
+ return NextResponse.json({ error: translate("devices.errors.forbidden", "Access denied") }, { status: 403 });
112
+ }
113
+ const mctx = {
114
+ container,
115
+ auth,
116
+ scope,
117
+ organizationId: device.organizationId ?? null,
118
+ actorUserId,
119
+ request: req
120
+ };
121
+ return await executeDeactivate(mctx, device);
122
+ } catch (err) {
123
+ if (isCrudHttpError(err)) {
124
+ return NextResponse.json(err.body, { status: err.status });
125
+ }
126
+ logger.error("devices.DELETE failed", { err });
127
+ return NextResponse.json({ error: translate("devices.errors.delete_failed", "Failed to delete device") }, { status: 500 });
128
+ }
129
+ }
130
+ const okResponseSchema = z.object({ ok: z.literal(true), id: z.string().uuid().optional() });
131
+ const errorResponseSchema = z.object({ error: z.string() });
132
+ const openApi = {
133
+ tag: "Devices",
134
+ summary: "Update or deactivate one of your registered devices",
135
+ methods: {
136
+ PUT: {
137
+ summary: "Update your device",
138
+ description: "Updates last-seen, app/OS metadata, and push token for a device owned by the current user. Set pushToken to null to clear a revoked OS permission.",
139
+ requestBody: { schema: updateDeviceSchema },
140
+ responses: [{ status: 200, description: "Device updated", schema: okResponseSchema }],
141
+ errors: [
142
+ { status: 400, description: "Invalid payload or id", schema: errorResponseSchema },
143
+ { status: 401, description: "Unauthorized", schema: errorResponseSchema },
144
+ { status: 403, description: "Not the device owner", schema: errorResponseSchema },
145
+ { status: 404, description: "Device not found", schema: errorResponseSchema }
146
+ ]
147
+ },
148
+ DELETE: {
149
+ summary: "Deactivate your device",
150
+ description: "Soft-deletes a device owned by the current user.",
151
+ responses: [{ status: 200, description: "Device deactivated", schema: okResponseSchema }],
152
+ errors: [
153
+ { status: 400, description: "Invalid id", schema: errorResponseSchema },
154
+ { status: 401, description: "Unauthorized", schema: errorResponseSchema },
155
+ { status: 403, description: "Not the device owner", schema: errorResponseSchema },
156
+ { status: 404, description: "Device not found", schema: errorResponseSchema }
157
+ ]
158
+ }
159
+ }
160
+ };
161
+ export {
162
+ DELETE,
163
+ PUT,
164
+ metadata,
165
+ openApi
166
+ };
167
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/modules/devices/api/%5Bid%5D/route.ts"],
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'\nimport { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { UserDevice } from '../../data/entities'\nimport { updateDeviceSchema } from '../../data/validators'\nimport { resolveDeviceActorUserId } from '../auth'\nimport { executeUpdate, executeDeactivate, type DeviceMutationContext } from '../deviceOps'\n\nconst logger = createLogger('devices')\n\n// Self-serve: the caller may only mutate their OWN device. Cross-user device administration lives in\n// api/admin/devices/[id] (gated by devices.admin).\nexport const metadata = {\n PUT: { requireAuth: true, requireFeatures: ['devices.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['devices.manage'] },\n}\n\nconst paramsSchema = z.object({ id: z.string().uuid() })\n\nexport async function PUT(req: Request, { params }: { params: { id: string } }) {\n const { translate } = await resolveTranslations()\n try {\n const container = await createRequestContainer()\n const auth = await getAuthFromRequest(req)\n const actorUserId = resolveDeviceActorUserId(auth)\n if (!auth || !auth.tenantId || !actorUserId) {\n return NextResponse.json({ error: translate('devices.errors.unauthorized', 'Unauthorized') }, { status: 401 })\n }\n const parsedParams = paramsSchema.safeParse({ id: params.id })\n if (!parsedParams.success) {\n return NextResponse.json({ error: translate('devices.errors.invalid_id', 'Invalid device id') }, { status: 400 })\n }\n\n const body = updateDeviceSchema.parse(await readJsonSafe(req, {}))\n const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req })\n // Self devices are scoped to the caller's active organization, mirroring the list route and the\n // user-owned-resource convention (e.g. progress jobs): a device outside the current org context\n // reads as not-found. When there is no active org, scope by tenant only.\n const currentOrganizationId = scope?.selectedId ?? auth.orgId ?? null\n const em = container.resolve('em') as EntityManager\n const device = await findOneWithDecryption(\n em,\n UserDevice,\n {\n id: parsedParams.data.id,\n tenantId: auth.tenantId,\n ...(currentOrganizationId ? { organizationId: currentOrganizationId } : {}),\n deletedAt: null,\n },\n undefined,\n { tenantId: auth.tenantId, organizationId: currentOrganizationId },\n )\n if (!device) {\n return NextResponse.json({ error: translate('devices.errors.not_found', 'Device not found') }, { status: 404 })\n }\n if (device.userId !== actorUserId) {\n return NextResponse.json({ error: translate('devices.errors.forbidden', 'Access denied') }, { status: 403 })\n }\n\n const mctx: DeviceMutationContext = {\n container,\n auth,\n scope,\n organizationId: device.organizationId ?? null,\n actorUserId,\n request: req,\n }\n return await executeUpdate(mctx, device, body)\n } catch (err) {\n if (err instanceof z.ZodError) {\n return NextResponse.json(\n { error: translate('devices.errors.invalid_payload', 'Invalid device payload'), details: err.flatten() },\n { status: 400 },\n )\n }\n if (isCrudHttpError(err)) {\n return NextResponse.json(err.body, { status: err.status })\n }\n logger.error('devices.PUT failed', { err })\n return NextResponse.json({ error: translate('devices.errors.update_failed', 'Failed to update device') }, { status: 500 })\n }\n}\n\nexport async function DELETE(req: Request, { params }: { params: { id: string } }) {\n const { translate } = await resolveTranslations()\n try {\n const container = await createRequestContainer()\n const auth = await getAuthFromRequest(req)\n const actorUserId = resolveDeviceActorUserId(auth)\n if (!auth || !auth.tenantId || !actorUserId) {\n return NextResponse.json({ error: translate('devices.errors.unauthorized', 'Unauthorized') }, { status: 401 })\n }\n const parsedParams = paramsSchema.safeParse({ id: params.id })\n if (!parsedParams.success) {\n return NextResponse.json({ error: translate('devices.errors.invalid_id', 'Invalid device id') }, { status: 400 })\n }\n\n const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req })\n // Same active-org scoping as PUT/the list route: a device outside the current org reads as not-found.\n const currentOrganizationId = scope?.selectedId ?? auth.orgId ?? null\n const em = container.resolve('em') as EntityManager\n const device = await findOneWithDecryption(\n em,\n UserDevice,\n {\n id: parsedParams.data.id,\n tenantId: auth.tenantId,\n ...(currentOrganizationId ? { organizationId: currentOrganizationId } : {}),\n deletedAt: null,\n },\n undefined,\n { tenantId: auth.tenantId, organizationId: currentOrganizationId },\n )\n if (!device) {\n return NextResponse.json({ error: translate('devices.errors.not_found', 'Device not found') }, { status: 404 })\n }\n if (device.userId !== actorUserId) {\n return NextResponse.json({ error: translate('devices.errors.forbidden', 'Access denied') }, { status: 403 })\n }\n\n const mctx: DeviceMutationContext = {\n container,\n auth,\n scope,\n organizationId: device.organizationId ?? null,\n actorUserId,\n request: req,\n }\n return await executeDeactivate(mctx, device)\n } catch (err) {\n if (isCrudHttpError(err)) {\n return NextResponse.json(err.body, { status: err.status })\n }\n logger.error('devices.DELETE failed', { err })\n return NextResponse.json({ error: translate('devices.errors.delete_failed', 'Failed to delete device') }, { status: 500 })\n }\n}\n\nconst okResponseSchema = z.object({ ok: z.literal(true), id: z.string().uuid().optional() })\nconst errorResponseSchema = z.object({ error: z.string() })\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Devices',\n summary: 'Update or deactivate one of your registered devices',\n methods: {\n PUT: {\n summary: 'Update your device',\n description:\n 'Updates last-seen, app/OS metadata, and push token for a device owned by the current user. Set pushToken to null to clear a revoked OS permission.',\n requestBody: { schema: updateDeviceSchema },\n responses: [{ status: 200, description: 'Device updated', schema: okResponseSchema }],\n errors: [\n { status: 400, description: 'Invalid payload or id', schema: errorResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 403, description: 'Not the device owner', schema: errorResponseSchema },\n { status: 404, description: 'Device not found', schema: errorResponseSchema },\n ],\n },\n DELETE: {\n summary: 'Deactivate your device',\n description: 'Soft-deletes a device owned by the current user.',\n responses: [{ status: 200, description: 'Device deactivated', schema: okResponseSchema }],\n errors: [\n { status: 400, description: 'Invalid id', schema: errorResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 403, description: 'Not the device owner', schema: errorResponseSchema },\n { status: 404, description: 'Device not found', schema: errorResponseSchema },\n ],\n },\n },\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }