@open-mercato/core 0.6.8-develop.6983.1.e4f794099e → 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
@@ -0,0 +1,104 @@
1
+ import type { MessageContent } from './adapter'
2
+
3
+ /**
4
+ * Flat, provider-agnostic push customization a caller can attach to a
5
+ * notification (via `Notification.pushOptions`) or a silent push. Each push
6
+ * adapter maps the recognized keys onto its own provider message shape (see
7
+ * {@link readPushOptions}); unknown keys are ignored by the adapters but kept on
8
+ * the envelope so a provider that understands them can still read them.
9
+ */
10
+ export interface PushOptions {
11
+ /** Notification sound (provider default when omitted). */
12
+ sound?: string
13
+ /** App icon badge count (iOS / supported Android launchers). */
14
+ badge?: number
15
+ /** Rich image URL shown in the expanded notification. */
16
+ image?: string
17
+ /** Delivery priority. Maps to FCM `android.priority` / `apns-priority` / Expo `priority`. */
18
+ priority?: 'high' | 'normal'
19
+ /** Android notification channel id (FCM `android.notification.channel_id` / Expo `channelId`). */
20
+ channelId?: string
21
+ /** Overrides the push body text without changing the in-app notification body. */
22
+ body?: string
23
+ [key: string]: unknown
24
+ }
25
+
26
+ /**
27
+ * The push payload the `push_notifications` worker packs into
28
+ * `SendMessageInput.content.raw` before calling a push adapter's `sendMessage`
29
+ * (see `push_notifications/lib/push-delivery.ts`). Each provider adapter
30
+ * (fcm/apns/expo) reads it the same way via {@link readPushEnvelope} so the
31
+ * title/body/data contract stays uniform.
32
+ */
33
+ export interface PushEnvelope {
34
+ title: string
35
+ body: string
36
+ data: Record<string, string>
37
+ /** Flat per-provider customization; see {@link PushOptions}. */
38
+ options: PushOptions
39
+ /**
40
+ * When `true`, deliver as a silent / content-available wake-up: no visible
41
+ * alert (title/body omitted), data-only payload. Adapters branch on this.
42
+ */
43
+ silent: boolean
44
+ }
45
+
46
+ function toStringRecord(value: unknown): Record<string, string> {
47
+ if (!value || typeof value !== 'object') return {}
48
+ const out: Record<string, string> = {}
49
+ for (const [key, raw] of Object.entries(value as Record<string, unknown>)) {
50
+ if (raw == null) continue
51
+ out[key] = typeof raw === 'string' ? raw : String(raw)
52
+ }
53
+ return out
54
+ }
55
+
56
+ const KNOWN_PUSH_OPTION_KEYS = new Set(['sound', 'badge', 'image', 'priority', 'channelId', 'body'])
57
+
58
+ /**
59
+ * Normalize caller-supplied push options. The recognized keys are coerced to their declared types and a
60
+ * malformed value is DROPPED rather than passed through: a bad `priority` (e.g. `'urgent'`) would reach
61
+ * the provider SDK as an invalid enum and fail every delivery retry with a misleading error. Unknown
62
+ * keys are preserved verbatim so a provider that understands them can still read them (see PushOptions).
63
+ */
64
+ function toPushOptions(value: unknown): PushOptions {
65
+ if (!value || typeof value !== 'object') return {}
66
+ const raw = value as Record<string, unknown>
67
+ const options: PushOptions = {}
68
+ for (const [key, entry] of Object.entries(raw)) {
69
+ if (!KNOWN_PUSH_OPTION_KEYS.has(key)) options[key] = entry
70
+ }
71
+ if (typeof raw.sound === 'string') options.sound = raw.sound
72
+ if (typeof raw.image === 'string') options.image = raw.image
73
+ if (typeof raw.channelId === 'string') options.channelId = raw.channelId
74
+ if (typeof raw.body === 'string') options.body = raw.body
75
+ if (typeof raw.badge === 'number' && Number.isFinite(raw.badge)) options.badge = raw.badge
76
+ if (raw.priority === 'high' || raw.priority === 'normal') options.priority = raw.priority
77
+ return options
78
+ }
79
+
80
+ /** Read the normalized push envelope from a hub `MessageContent`. Defensive against missing fields. */
81
+ export function readPushEnvelope(content: MessageContent | undefined): PushEnvelope {
82
+ const raw = (content?.raw ?? {}) as {
83
+ title?: unknown
84
+ body?: unknown
85
+ data?: unknown
86
+ options?: unknown
87
+ silent?: unknown
88
+ }
89
+ const title = typeof raw.title === 'string' ? raw.title : ''
90
+ const body = typeof raw.body === 'string' ? raw.body : content?.text ?? ''
91
+ return {
92
+ title,
93
+ body,
94
+ data: toStringRecord(raw.data),
95
+ options: toPushOptions(raw.options),
96
+ silent: raw.silent === true,
97
+ }
98
+ }
99
+
100
+ /** The push body text after applying a non-empty `pushOptions.body` override, if present. */
101
+ export function resolvePushBody(envelope: PushEnvelope): string {
102
+ const override = envelope.options.body
103
+ return typeof override === 'string' && override.length > 0 ? override : envelope.body
104
+ }
@@ -0,0 +1,123 @@
1
+ /**
2
+ * A bounded, LRU client cache whose disposal is fenced on in-flight use.
3
+ *
4
+ * Push adapters cache one live provider client (a firebase-admin App carrying a
5
+ * background OAuth-refresh timer, or a node-apn Provider holding an HTTP/2 socket)
6
+ * per credential identity, and LRU-evict the least-recently-used one when the cache
7
+ * grows past `max`. The hazard the previous inline caches had: eviction disposed the
8
+ * client (`app.delete()` / `provider.shutdown()`) immediately, even while a concurrent
9
+ * `sendMessage` still held it — closing the socket mid-stream. Above the cap that is a
10
+ * steady-state error rate, not a rare race.
11
+ *
12
+ * This cache reference-counts every borrow and DEFERS disposal of an evicted client
13
+ * until its last in-flight borrow releases, so a send never loses its client
14
+ * underneath it. A client that is never evicted is never disposed.
15
+ */
16
+ export type RefCountedClientCacheOptions<TClient> = {
17
+ /** Maximum number of live clients kept at once; the least-recently-used is evicted past this. */
18
+ max: number
19
+ /**
20
+ * Release the underlying resource. Called at most once per created client, and only after the client
21
+ * has been evicted AND every borrow of it has been released. Must not throw synchronously.
22
+ */
23
+ dispose: (client: TClient) => void | Promise<void>
24
+ }
25
+
26
+ export type ClientLease<TClient> = {
27
+ client: TClient
28
+ /**
29
+ * Release this borrow. Idempotent. Once the last borrow of an already-evicted client releases, the
30
+ * client is disposed. Callers MUST call this exactly once per successful `acquire`, in a `finally`.
31
+ */
32
+ release: () => void
33
+ }
34
+
35
+ type CacheEntry<TClient> = {
36
+ key: string
37
+ client: Promise<TClient>
38
+ refs: number
39
+ evicted: boolean
40
+ disposed: boolean
41
+ }
42
+
43
+ export type RefCountedClientCache<TClient> = {
44
+ /**
45
+ * Borrow the client for `key`, creating it via `factory` on a miss. On a hit the entry is promoted to
46
+ * most-recently-used. A rejected factory result is dropped from the cache (never disposed — nothing was
47
+ * constructed) so the next borrow re-creates. The returned lease MUST be released by the caller.
48
+ */
49
+ acquire: (key: string, factory: () => Promise<TClient>) => Promise<ClientLease<TClient>>
50
+ /** Number of live (non-evicted) cached entries. Test/introspection only. */
51
+ size: () => number
52
+ }
53
+
54
+ export function createRefCountedClientCache<TClient>(
55
+ options: RefCountedClientCacheOptions<TClient>,
56
+ ): RefCountedClientCache<TClient> {
57
+ const entries = new Map<string, CacheEntry<TClient>>()
58
+
59
+ const scheduleDispose = (entry: CacheEntry<TClient>): void => {
60
+ if (entry.disposed) return
61
+ entry.disposed = true
62
+ void entry.client.then((client) => options.dispose(client)).catch(() => {})
63
+ }
64
+
65
+ const releaseEntry = (entry: CacheEntry<TClient>): void => {
66
+ if (entry.refs <= 0) return
67
+ entry.refs -= 1
68
+ if (entry.refs === 0 && entry.evicted) scheduleDispose(entry)
69
+ }
70
+
71
+ const enforceMax = (): void => {
72
+ while (entries.size > options.max) {
73
+ const oldest = entries.values().next().value as CacheEntry<TClient> | undefined
74
+ if (!oldest) break
75
+ entries.delete(oldest.key)
76
+ oldest.evicted = true
77
+ // Defer disposal while borrows remain; releaseEntry disposes when the last one returns.
78
+ if (oldest.refs === 0) scheduleDispose(oldest)
79
+ }
80
+ }
81
+
82
+ const obtain = (key: string, factory: () => Promise<TClient>): CacheEntry<TClient> => {
83
+ const existing = entries.get(key)
84
+ if (existing) {
85
+ // Refresh recency: delete + re-insert moves the key to the newest position.
86
+ entries.delete(key)
87
+ entries.set(key, existing)
88
+ existing.refs += 1
89
+ return existing
90
+ }
91
+ const entry: CacheEntry<TClient> = { key, client: factory(), refs: 1, evicted: false, disposed: false }
92
+ entries.set(key, entry)
93
+ // Drop a rejected init (e.g. invalid credentials) so the next borrow re-creates instead of forever
94
+ // returning the cached rejection. Nothing was constructed, so there is nothing to dispose.
95
+ entry.client.catch(() => {
96
+ if (entries.get(key) === entry) entries.delete(key)
97
+ })
98
+ enforceMax()
99
+ return entry
100
+ }
101
+
102
+ return {
103
+ async acquire(key, factory) {
104
+ const entry = obtain(key, factory)
105
+ try {
106
+ const client = await entry.client
107
+ let released = false
108
+ return {
109
+ client,
110
+ release: () => {
111
+ if (released) return
112
+ released = true
113
+ releaseEntry(entry)
114
+ },
115
+ }
116
+ } catch (err) {
117
+ releaseEntry(entry)
118
+ throw err
119
+ }
120
+ },
121
+ size: () => entries.size,
122
+ }
123
+ }
@@ -1004,6 +1004,15 @@
1004
1004
  "unique": false,
1005
1005
  "expression": "create unique index \"communication_channels_user_provider_external_uq\" on \"communication_channels\" (\"tenant_id\", \"user_id\", \"provider_key\", \"external_identifier\") where \"deleted_at\" is null and \"user_id\" is not null and \"external_identifier\" is not null"
1006
1006
  },
1007
+ {
1008
+ "columnNames": [],
1009
+ "composite": false,
1010
+ "constraint": false,
1011
+ "keyName": "communication_channels_tenant_push_provider_uq",
1012
+ "primary": false,
1013
+ "unique": false,
1014
+ "expression": "create unique index \"communication_channels_tenant_push_provider_uq\" on \"communication_channels\" (\"tenant_id\", \"provider_key\") where \"channel_type\" = 'push' and \"user_id\" is null and \"deleted_at\" is null"
1015
+ },
1007
1016
  {
1008
1017
  "columnNames": [
1009
1018
  "id"
@@ -0,0 +1,20 @@
1
+ import { Migration } from '@mikro-orm/migrations';
2
+
3
+ export class Migration20260703123630_communication_channels extends Migration {
4
+
5
+ override up(): void | Promise<void> {
6
+ // Enforce one tenant-wide push channel per (tenant, provider). Push providers
7
+ // (FCM/APNs/Expo) have no external_identifier and user_id IS NULL, so the
8
+ // mailbox unique index (communication_channels_user_provider_external_uq) does
9
+ // not cover them. This keeps an admin reconnect healing the single shared row
10
+ // (createConnectedChannelRow) instead of inserting duplicates the push fan-out
11
+ // would silently ignore. Only covers user_id IS NULL rows, so existing per-user
12
+ // channels are unaffected.
13
+ this.addSql(`create unique index "communication_channels_tenant_push_provider_uq" on "communication_channels" ("tenant_id", "provider_key") where "channel_type" = 'push' and "user_id" is null and "deleted_at" is null;`);
14
+ }
15
+
16
+ override down(): void | Promise<void> {
17
+ this.addSql(`drop index if exists "communication_channels_tenant_push_provider_uq";`);
18
+ }
19
+
20
+ }
@@ -3,6 +3,8 @@ import type { NotificationTypeDefinition } from '@open-mercato/shared/modules/no
3
3
  export const notificationTypes: NotificationTypeDefinition[] = [
4
4
  {
5
5
  type: 'communication_channels.message.received',
6
+ // Ships without push — operators re-enable it per type from the Notification Delivery settings.
7
+ channels: ['in_app', 'email'],
6
8
  module: 'communication_channels',
7
9
  titleKey: 'communication_channels.notifications.message_received.title',
8
10
  bodyKey: 'communication_channels.notifications.message_received.body',
@@ -30,6 +32,8 @@ export const notificationTypes: NotificationTypeDefinition[] = [
30
32
  * integration spec's reconnect flow.
31
33
  */
32
34
  type: 'communication_channels.channel.requires_reauth',
35
+ // Ships without push — operators re-enable it per type from the Notification Delivery settings.
36
+ channels: ['in_app', 'email'],
33
37
  module: 'communication_channels',
34
38
  titleKey: 'communication_channels.notifications.channel_requires_reauth.title',
35
39
  bodyKey: 'communication_channels.notifications.channel_requires_reauth.body',
@@ -57,6 +57,7 @@ export const setup: ModuleSetupConfig = {
57
57
  'communication_channels.react',
58
58
  'communication_channels.assign',
59
59
  'communication_channels.connect_user_channel',
60
+ 'communication_channels.connect_tenant_channel',
60
61
  'communication_channels.admin',
61
62
  'communication_channels.channel.import_history',
62
63
  'communication_channels.channel.push.manage',
@@ -67,6 +68,7 @@ export const setup: ModuleSetupConfig = {
67
68
  'communication_channels.react',
68
69
  'communication_channels.assign',
69
70
  'communication_channels.connect_user_channel',
71
+ 'communication_channels.connect_tenant_channel',
70
72
  'communication_channels.admin',
71
73
  'communication_channels.channel.import_history',
72
74
  'communication_channels.channel.push.manage',
@@ -193,5 +193,9 @@
193
193
  "configs.upgrades.attachmentsOrgReconcile.cta": "Anhang-Organisationen abgleichen",
194
194
  "configs.upgrades.attachmentsOrgReconcile.loading": "Anhang-Organisationen werden abgeglichen…",
195
195
  "configs.upgrades.attachmentsOrgReconcile.message": "Version {{version}} behebt Anhänge, die unter der falschen Organisation gespeichert wurden. Führen Sie den Abgleich aus, um vorhandene Anhänge in die Organisation des zugehörigen Datensatzes zu verschieben.",
196
- "configs.upgrades.attachmentsOrgReconcile.success": "Anhang-Organisationen abgeglichen."
196
+ "configs.upgrades.attachmentsOrgReconcile.success": "Anhang-Organisationen abgeglichen.",
197
+ "configs.upgrades.devicesPushTokenEncryption.cta": "Push-Tokens von Geräten verschlüsseln",
198
+ "configs.upgrades.devicesPushTokenEncryption.loading": "Verschlüsselungszuordnung für Push-Tokens wird angelegt…",
199
+ "configs.upgrades.devicesPushTokenEncryption.message": "Version {{version}} fügt mobile Push-Benachrichtigungen hinzu und verschlüsselt Geräte-Push-Tokens im Ruhezustand. Bestehende Mandanten haben keine Verschlüsselungszuordnung für die neue Geräte-Entität, sodass nach dem Upgrade registrierte Tokens unverschlüsselt gespeichert würden. Führen Sie dies aus, um die Zuordnung anzulegen, damit Push-Tokens verschlüsselt werden.",
200
+ "configs.upgrades.devicesPushTokenEncryption.success": "Verschlüsselungszuordnung für Push-Tokens angelegt."
197
201
  }
@@ -193,5 +193,9 @@
193
193
  "configs.upgrades.attachmentsOrgReconcile.cta": "Reconcile attachment organizations",
194
194
  "configs.upgrades.attachmentsOrgReconcile.loading": "Reconciling attachment organizations…",
195
195
  "configs.upgrades.attachmentsOrgReconcile.message": "Version {{version}} fixes attachments that were saved under the wrong organization. Run the reconciliation to move existing attachments to the organization of the record they belong to.",
196
- "configs.upgrades.attachmentsOrgReconcile.success": "Attachment organizations reconciled."
196
+ "configs.upgrades.attachmentsOrgReconcile.success": "Attachment organizations reconciled.",
197
+ "configs.upgrades.devicesPushTokenEncryption.cta": "Encrypt device push tokens",
198
+ "configs.upgrades.devicesPushTokenEncryption.loading": "Seeding push-token encryption map…",
199
+ "configs.upgrades.devicesPushTokenEncryption.message": "Version {{version}} adds mobile push and encrypts device push tokens at rest. Existing tenants have no encryption map for the new device entity, so tokens registered after the upgrade would be stored unencrypted. Run this to seed the map so push tokens are encrypted.",
200
+ "configs.upgrades.devicesPushTokenEncryption.success": "Push-token encryption map seeded."
197
201
  }
@@ -193,5 +193,9 @@
193
193
  "configs.upgrades.attachmentsOrgReconcile.cta": "Reconciliar organizaciones de adjuntos",
194
194
  "configs.upgrades.attachmentsOrgReconcile.loading": "Reconciliando organizaciones de adjuntos…",
195
195
  "configs.upgrades.attachmentsOrgReconcile.message": "La versión {{version}} corrige los adjuntos guardados en la organización incorrecta. Ejecuta la reconciliación para mover los adjuntos existentes a la organización del registro al que pertenecen.",
196
- "configs.upgrades.attachmentsOrgReconcile.success": "Organizaciones de adjuntos reconciliadas."
196
+ "configs.upgrades.attachmentsOrgReconcile.success": "Organizaciones de adjuntos reconciliadas.",
197
+ "configs.upgrades.devicesPushTokenEncryption.cta": "Cifrar tokens push de dispositivos",
198
+ "configs.upgrades.devicesPushTokenEncryption.loading": "Creando el mapa de cifrado de tokens push…",
199
+ "configs.upgrades.devicesPushTokenEncryption.message": "La versión {{version}} añade notificaciones push móviles y cifra los tokens push de los dispositivos en reposo. Los inquilinos existentes no tienen un mapa de cifrado para la nueva entidad de dispositivo, por lo que los tokens registrados tras la actualización se guardarían sin cifrar. Ejecuta esto para crear el mapa y que los tokens push queden cifrados.",
200
+ "configs.upgrades.devicesPushTokenEncryption.success": "Mapa de cifrado de tokens push creado."
197
201
  }
@@ -193,5 +193,9 @@
193
193
  "configs.upgrades.attachmentsOrgReconcile.cta": "애착 조직을 조정하세요",
194
194
  "configs.upgrades.attachmentsOrgReconcile.loading": "애착단체 화해…",
195
195
  "configs.upgrades.attachmentsOrgReconcile.message": "버전 {{version}}는 잘못된 조직에 저장된 첨부 파일을 수정합니다. 조정을 실행하여 기존 첨부 파일을 해당 첨부 파일이 속한 레코드의 조직으로 이동합니다.",
196
- "configs.upgrades.attachmentsOrgReconcile.success": "첨부 조직이 조정되었습니다."
196
+ "configs.upgrades.attachmentsOrgReconcile.success": "첨부 조직이 조정되었습니다.",
197
+ "configs.upgrades.devicesPushTokenEncryption.cta": "기기 푸시 토큰 암호화",
198
+ "configs.upgrades.devicesPushTokenEncryption.loading": "푸시 토큰 암호화 맵을 생성하는 중…",
199
+ "configs.upgrades.devicesPushTokenEncryption.message": "{{version}} 버전에서 모바일 푸시가 추가되며 기기 푸시 토큰이 저장 시 암호화됩니다. 기존 테넌트에는 새 기기 엔티티에 대한 암호화 맵이 없어, 업그레이드 이후 등록되는 토큰이 암호화되지 않은 상태로 저장됩니다. 이 작업을 실행해 맵을 생성하면 푸시 토큰이 암호화됩니다.",
200
+ "configs.upgrades.devicesPushTokenEncryption.success": "푸시 토큰 암호화 맵이 생성되었습니다."
197
201
  }
@@ -193,5 +193,9 @@
193
193
  "configs.upgrades.attachmentsOrgReconcile.cta": "Uzgodnij organizacje załączników",
194
194
  "configs.upgrades.attachmentsOrgReconcile.loading": "Uzgadnianie organizacji załączników…",
195
195
  "configs.upgrades.attachmentsOrgReconcile.message": "Wersja {{version}} naprawia załączniki zapisane pod niewłaściwą organizacją. Uruchom uzgadnianie, aby przenieść istniejące załączniki do organizacji rekordu, do którego należą.",
196
- "configs.upgrades.attachmentsOrgReconcile.success": "Organizacje załączników zostały uzgodnione."
196
+ "configs.upgrades.attachmentsOrgReconcile.success": "Organizacje załączników zostały uzgodnione.",
197
+ "configs.upgrades.devicesPushTokenEncryption.cta": "Szyfruj tokeny push urządzeń",
198
+ "configs.upgrades.devicesPushTokenEncryption.loading": "Tworzenie mapy szyfrowania tokenów push…",
199
+ "configs.upgrades.devicesPushTokenEncryption.message": "Wersja {{version}} dodaje mobilne powiadomienia push i szyfruje tokeny push urządzeń w spoczynku. Istniejący najemcy nie mają mapy szyfrowania dla nowej encji urządzenia, więc tokeny zarejestrowane po aktualizacji byłyby przechowywane bez szyfrowania. Uruchom to, aby utworzyć mapę i zaszyfrować tokeny push.",
200
+ "configs.upgrades.devicesPushTokenEncryption.success": "Utworzono mapę szyfrowania tokenów push."
197
201
  }
@@ -62,6 +62,27 @@ export const upgradeActions: UpgradeActionDefinition[] = [
62
62
  })
63
63
  },
64
64
  },
65
+ {
66
+ id: 'devices.seed-push-token-encryption-map',
67
+ version: '0.6.6',
68
+ messageKey: 'configs.upgrades.devicesPushTokenEncryption.message',
69
+ ctaKey: 'configs.upgrades.devicesPushTokenEncryption.cta',
70
+ successKey: 'configs.upgrades.devicesPushTokenEncryption.success',
71
+ loadingKey: 'configs.upgrades.devicesPushTokenEncryption.loading',
72
+ // Encryption maps are seeded once at tenant creation (`entities seed-encryption`), so a tenant
73
+ // that predates the devices push-token feature has no `devices:user_device` map row. Without it
74
+ // `encryptEntityPayload` no-ops and `push_token` is written as PLAINTEXT (the map is a declaration
75
+ // of which fields to encrypt; the tenant DEK still drives the actual crypto, so seeding it is safe
76
+ // even when encryption is currently disabled — it only takes effect once encryption is on).
77
+ // Lazy-imported so configs stays decoupled from devices/entities (mirrors the customers action).
78
+ run: async ({ em, tenantId, organizationId }) => {
79
+ const [{ default: devicesEncryptionMaps }, { upsertEncryptionMapSpecs }] = await Promise.all([
80
+ import('@open-mercato/core/modules/devices/encryption'),
81
+ import('@open-mercato/core/modules/entities/cli'),
82
+ ])
83
+ await upsertEncryptionMapSpecs(em, tenantId, organizationId ?? null, devicesEncryptionMaps)
84
+ },
85
+ },
65
86
  {
66
87
  id: 'customers.seed-interaction-statuses',
67
88
  version: '0.6.5',
@@ -353,5 +353,6 @@
353
353
  "customer_accounts.widgets.noAccount": "Kein verknüpftes Konto",
354
354
  "customer_accounts.widgets.noUsers": "Keine verknüpften Benutzer",
355
355
  "customer_accounts.widgets.portalUsers": "Portalbenutzer",
356
- "customer_accounts.widgets.viewAccount": "Konto anzeigen"
356
+ "customer_accounts.widgets.viewAccount": "Konto anzeigen",
357
+ "notifications.categories.customer_accounts": "Kundenkonten"
357
358
  }
@@ -353,5 +353,6 @@
353
353
  "customer_accounts.widgets.noAccount": "No account linked",
354
354
  "customer_accounts.widgets.noUsers": "No users linked",
355
355
  "customer_accounts.widgets.portalUsers": "Portal users",
356
- "customer_accounts.widgets.viewAccount": "View account"
356
+ "customer_accounts.widgets.viewAccount": "View account",
357
+ "notifications.categories.customer_accounts": "Customer accounts"
357
358
  }
@@ -353,5 +353,6 @@
353
353
  "customer_accounts.widgets.noAccount": "No hay cuenta vinculada",
354
354
  "customer_accounts.widgets.noUsers": "No hay usuarios vinculados",
355
355
  "customer_accounts.widgets.portalUsers": "Usuarios del portal",
356
- "customer_accounts.widgets.viewAccount": "Ver cuenta"
356
+ "customer_accounts.widgets.viewAccount": "Ver cuenta",
357
+ "notifications.categories.customer_accounts": "Cuentas de clientes"
357
358
  }
@@ -353,5 +353,6 @@
353
353
  "customer_accounts.widgets.noAccount": "연결된 계정 없음",
354
354
  "customer_accounts.widgets.noUsers": "연결된 사용자 없음",
355
355
  "customer_accounts.widgets.portalUsers": "포털 사용자",
356
- "customer_accounts.widgets.viewAccount": "계정 보기"
356
+ "customer_accounts.widgets.viewAccount": "계정 보기",
357
+ "notifications.categories.customer_accounts": "고객 계정"
357
358
  }
@@ -353,5 +353,6 @@
353
353
  "customer_accounts.widgets.noAccount": "Brak powiązanego konta",
354
354
  "customer_accounts.widgets.noUsers": "Brak powiązanych użytkowników",
355
355
  "customer_accounts.widgets.portalUsers": "Użytkownicy portalu",
356
- "customer_accounts.widgets.viewAccount": "Zobacz konto"
356
+ "customer_accounts.widgets.viewAccount": "Zobacz konto",
357
+ "notifications.categories.customer_accounts": "Konta klientów"
357
358
  }
@@ -3,6 +3,8 @@ import type { NotificationTypeDefinition } from '@open-mercato/shared/modules/no
3
3
  export const notificationTypes: NotificationTypeDefinition[] = [
4
4
  {
5
5
  type: 'customer_accounts.user.signup',
6
+ // Ships without push — operators re-enable it per type from the Notification Delivery settings.
7
+ channels: ['in_app', 'email'],
6
8
  module: 'customer_accounts',
7
9
  titleKey: 'customer_accounts.notifications.user.signup.title',
8
10
  bodyKey: 'customer_accounts.notifications.user.signup.body',
@@ -22,6 +24,8 @@ export const notificationTypes: NotificationTypeDefinition[] = [
22
24
  },
23
25
  {
24
26
  type: 'customer_accounts.user.locked',
27
+ // Ships without push — operators re-enable it per type from the Notification Delivery settings.
28
+ channels: ['in_app', 'email'],
25
29
  module: 'customer_accounts',
26
30
  titleKey: 'customer_accounts.notifications.user.locked.title',
27
31
  bodyKey: 'customer_accounts.notifications.user.locked.body',
@@ -41,6 +45,8 @@ export const notificationTypes: NotificationTypeDefinition[] = [
41
45
  },
42
46
  {
43
47
  type: 'customer_accounts.domain_mapping.verified',
48
+ // Ships without push — operators re-enable it per type from the Notification Delivery settings.
49
+ channels: ['in_app', 'email'],
44
50
  module: 'customer_accounts',
45
51
  titleKey: 'customer_accounts.notifications.domain_mapping.verified.title',
46
52
  bodyKey: 'customer_accounts.notifications.domain_mapping.verified.body',
@@ -60,6 +66,8 @@ export const notificationTypes: NotificationTypeDefinition[] = [
60
66
  },
61
67
  {
62
68
  type: 'customer_accounts.domain_mapping.activated',
69
+ // Ships without push — operators re-enable it per type from the Notification Delivery settings.
70
+ channels: ['in_app', 'email'],
63
71
  module: 'customer_accounts',
64
72
  titleKey: 'customer_accounts.notifications.domain_mapping.activated.title',
65
73
  bodyKey: 'customer_accounts.notifications.domain_mapping.activated.body',
@@ -79,6 +87,8 @@ export const notificationTypes: NotificationTypeDefinition[] = [
79
87
  },
80
88
  {
81
89
  type: 'customer_accounts.domain_mapping.dns_failed',
90
+ // Ships without push — operators re-enable it per type from the Notification Delivery settings.
91
+ channels: ['in_app', 'email'],
82
92
  module: 'customer_accounts',
83
93
  titleKey: 'customer_accounts.notifications.domain_mapping.dns_failed.title',
84
94
  bodyKey: 'customer_accounts.notifications.domain_mapping.dns_failed.body',
@@ -98,6 +108,8 @@ export const notificationTypes: NotificationTypeDefinition[] = [
98
108
  },
99
109
  {
100
110
  type: 'customer_accounts.domain_mapping.tls_failed',
111
+ // Ships without push — operators re-enable it per type from the Notification Delivery settings.
112
+ channels: ['in_app', 'email'],
101
113
  module: 'customer_accounts',
102
114
  titleKey: 'customer_accounts.notifications.domain_mapping.tls_failed.title',
103
115
  bodyKey: 'customer_accounts.notifications.domain_mapping.tls_failed.body',
@@ -2851,5 +2851,6 @@
2851
2851
  "customers.workPlan.customerTodos.table.flash.refreshed": "Aufgaben aktualisiert",
2852
2852
  "customers.workPlan.customerTodos.table.state.empty": "Noch keine Kundenaufgaben.",
2853
2853
  "customers.workPlan.customerTodos.table.state.noMatches": "Keine Aufgaben entsprechen den Filtern.",
2854
- "customers.workPlan.customerTodos.table.title": "Kundenbezogene Aufgaben"
2854
+ "customers.workPlan.customerTodos.table.title": "Kundenbezogene Aufgaben",
2855
+ "notifications.categories.customers": "Kunden"
2855
2856
  }
@@ -2851,5 +2851,6 @@
2851
2851
  "customers.workPlan.customerTodos.table.flash.refreshed": "Tasks refreshed",
2852
2852
  "customers.workPlan.customerTodos.table.state.empty": "No customer tasks yet.",
2853
2853
  "customers.workPlan.customerTodos.table.state.noMatches": "No tasks match your filters.",
2854
- "customers.workPlan.customerTodos.table.title": "Customer related tasks"
2854
+ "customers.workPlan.customerTodos.table.title": "Customer related tasks",
2855
+ "notifications.categories.customers": "Customers"
2855
2856
  }
@@ -2851,5 +2851,6 @@
2851
2851
  "customers.workPlan.customerTodos.table.flash.refreshed": "Tareas actualizadas",
2852
2852
  "customers.workPlan.customerTodos.table.state.empty": "Aún no hay tareas de clientes.",
2853
2853
  "customers.workPlan.customerTodos.table.state.noMatches": "Ninguna tarea coincide con tus filtros.",
2854
- "customers.workPlan.customerTodos.table.title": "Tareas relacionadas con clientes"
2854
+ "customers.workPlan.customerTodos.table.title": "Tareas relacionadas con clientes",
2855
+ "notifications.categories.customers": "Clientes"
2855
2856
  }
@@ -2851,5 +2851,6 @@
2851
2851
  "customers.workPlan.customerTodos.table.flash.refreshed": "작업 목록을 새로고침했습니다",
2852
2852
  "customers.workPlan.customerTodos.table.state.empty": "고객 관련 작업이 아직 없습니다.",
2853
2853
  "customers.workPlan.customerTodos.table.state.noMatches": "필터와 일치하는 작업이 없습니다.",
2854
- "customers.workPlan.customerTodos.table.title": "고객 관련 작업"
2854
+ "customers.workPlan.customerTodos.table.title": "고객 관련 작업",
2855
+ "notifications.categories.customers": "고객"
2855
2856
  }
@@ -2851,5 +2851,6 @@
2851
2851
  "customers.workPlan.customerTodos.table.flash.refreshed": "Zadania odświeżone",
2852
2852
  "customers.workPlan.customerTodos.table.state.empty": "Brak zadań klientów.",
2853
2853
  "customers.workPlan.customerTodos.table.state.noMatches": "Brak zadań spełniających filtry.",
2854
- "customers.workPlan.customerTodos.table.title": "Zadania związane z klientami"
2854
+ "customers.workPlan.customerTodos.table.title": "Zadania związane z klientami",
2855
+ "notifications.categories.customers": "Klienci"
2855
2856
  }
@@ -3,6 +3,8 @@ import type { NotificationTypeDefinition } from '@open-mercato/shared/modules/no
3
3
  export const notificationTypes: NotificationTypeDefinition[] = [
4
4
  {
5
5
  type: 'customers.deal.won',
6
+ // Ships without push — operators re-enable it per type from the Notification Delivery settings.
7
+ channels: ['in_app', 'email'],
6
8
  module: 'customers',
7
9
  titleKey: 'customers.notifications.deal.won.title',
8
10
  bodyKey: 'customers.notifications.deal.won.body',
@@ -22,6 +24,8 @@ export const notificationTypes: NotificationTypeDefinition[] = [
22
24
  },
23
25
  {
24
26
  type: 'customers.deal.lost',
27
+ // Ships without push — operators re-enable it per type from the Notification Delivery settings.
28
+ channels: ['in_app', 'email'],
25
29
  module: 'customers',
26
30
  titleKey: 'customers.notifications.deal.lost.title',
27
31
  bodyKey: 'customers.notifications.deal.lost.body',